Плагин является расширением возможностей графического редактора. Каждый плагин является либо инструментом, либо эффектом.
- Эффект - обработка, применяемая относительно всего изображения.
- Инструмент - позиционная обработка, может учитывать текущее положение и состояние мыши.
Расширение - это набор функций, реализованных вне стандарта. Может предоставляться как плагином, так и редактором. Название расширения должно быть не длиннее 31 символа, не должно начинаться с цифры, и должно состоять из строчных латинских букв, цифр, и знаков '_', '-'. Названия функций в них должны соответствовать этим же требованиям. Дополнительная информация о расширениях предоставлена в секции "Расширения".
Плагин является разделяемой библиотекой. Для начала работы с плагином редактор загружает разделяемую библиотеку в свое адресное пространство и находит в ней функцию get_plugin_interface. Она возвращает структуру PPluginInterface (см. исходник). В ней располагаются указатели на функции, реализуемые плагином и вызываемые редактором. Также в структуре указана версия Стандарта, с которым готов работать плагин. В текущей итерации Стандарта версия должна являться нулевым значением (0). Номер версии располагается самым первым полем в PPluginInterface - гарантируется, что это будет верно и для последующих версий стандарта. Таким образом, вся дальнейшая интерпретация структур должна зависеть от номера версии.
std_version- версия стандарта, с которой плагин готов работатьreserved- зарезервированный указатель. Плагину следует игнорировать его в текущей версии стандартаgeneral.feature_level- уровень поддержки. Значение поля описано ниже.
enable: - активировать расширение плагина. Возвращает индикатор того, реализовано ли это расширение.get_func: - получить указатель на функцию, реализованную в расширении с данным именем. Если функция не реализована, или если расширение, частью которого оно является, не реализовано или не было активировано,get_funcдолжна вернуть нулевой указатель.
-
init- функция инициализации плагина. Редактор обязуется вызвать эту функцию при загрузке плагина, передав в нее заполненную структуруPAppInterface- указатели на функции редактора. СодержимоеPAppInterfaceопределяется ниже. Функция возвращает статус исполнения - если статус неPPS_OK, то инициализация плагина провалилась и редактор не может продолжпть работу с плагином. -
get_info- возвращает структуруPPluginInfoc базовой информацией и типом плагина - эффект или инструмент. Также содержит указатель на PPluginInterface. -
deinit- деинициализация плагина. Редактор обязуется вызвать эту функцию при выгрузке плагина. Функция возвращает статус исполнения - если статус неPPS_OK, то деинициализация плагина провалилась и возможны утечки памяти. -
dump- в ответ на вызов этой функции редактором плагин может вывести свое состояние глобальный лог приложения посредством функции logPAppInterface(см. ниже) -
on_tick- данная функция периодически вызывается приложением, передавая в качестве аргумента время, прошедшее с предыдущего вызова в секундах -
on_settings_update- данная функция (если имеется) вызывается тогда, когда изменены какие-то настройки. Поле может быть нулевым, в ином случае приложение обязяано вызывать его каждый раз, когда меняется какая-либо настройка. -
get_flush_policy- данная функция возвращает политику замещения плагина. Если плагин возвращаетPPLP_BLEND, то превью-слой должен альфа-смешиваться с основным, еслиPPLP_COPY- полностью заменять основной слой (про превью слой см. ниже)
Секция должна быть определена для PPT_EFFECT. Если тип плагина отличен от PPT_EFFECT, секция должна быть заполнена нулями.
apply- при вызове приложением этой функции плагин должен произвести желаемые манипуляции со слоями (основным/preview).
Секция должна быть определена для PPT_TOOL. Если тип плагина отличен от PPT_TOOL, секция должна быть заполнена нулями.
on_press- вызовом этой функции приложение уведомляет плагин о нажатии на кнопку мыши. Сообщается позиция мыши в момент нажатия. Плагин должен произвести желаемые манипуляции со слоями (основным/preview).on_move- вызовом этой функции приложение уведомляет плагин о перемещении мыши. Сообщается старая и новая позиции мыши. Плагин должен произвести желаемые манипуляции со слоями (основным/preview).on_release- вызовом этой функции приложение уведомляет плагин об отпуске кнопки мыши. Сообщается позиция мыши в момент отпуска. Плагин должен произвести желаемые манипуляции со слоями (основным/preview).
Приложение предоставляет плагину набор функций, посредством которых он может делать что-то полезное. Этот набор функций определен структурой PAppInterface, которая является набором указателей на функции и передается приложением в плагин при инициализации.
std_version- версия стандарта, с которой приложение готово работатьreserved- зарезервированный указатель. Плагину следует игнорировать ее в текущей версии стандарта
enable: - активировать расширение редактора. Возвращает индикатор того, реализовано ли это расширение.get_func: - получить указатель на функцию, реализованную в расширении с данным именем. Если функция не реализована, или если расширение, частью которого оно является, не реализовано или не было активировано,get_funcдолжна вернуть нулевой указатель.
feature_level- каждый бит поля соответствует элементу перечисления по степеням двойкиPFeatureLevel. Бит выставляется тогда и только тогда, когда указанная особенность в полной мере поддерживается приложением.log- функция логгирования. Позволяет плагину печатать сообщения в лог программы. Сигнатура как уprintfбез возвращаемого значения -void (char const*, ...)get_absolute_time- возвращает время в секундах относительно запуска редактора.release_pixels- удаляет массив пикселей, полученный от функцииget_pixels(см. ниже). Плагин не имеет права передавать в эту функцию другие указатели или дважды вызывать ее с одним и тем же массивом, порождая ситуацию double-free.get_color- возвращает текущий цвет. Плагин не обязан согласовывать цвет с предоставляемым программой. Программа не обязана поддерживать цвета всех инструментов одинаковыми, равно как и уникальными.get_size- возвращает текущий размер (толщину). Плагин не обязан согласовывать толщину с предоставляемой программой. Программа не обязана поддерживать размеры всех инструментов одинаковыми, равно как и уникальными.
get_pixels- возвращает текущий слой как массив пикселей (массив цветов). Порядок следования пикселей построчный - сначала идут пиксели (0, 0), (0, 1), ..., непосредственно после окончания нулевой строки идет следующая (1, 0), (1, 1), ... и так до последней строки. Возвращаемый буфер является динамическим - плагин обязуется освободить его посредствомrelease_pixels.get_size- записывает размеры текущего слоя по переданным указателям.
circle- рисует круг (с заливкой) с заданным центром, радиусом, цветом и параметрами отрисовки.line- рисует линию с заданным началом/концом с заданным цветом и параметрами отрисовки.triangle- рисует треугольник (с заливкой) с заданными вершинами, цветом и параметрами отрисовки.rectangle- рисует прямоугольник (с заливкой) со сторонами, параллельными осям координат по двум углам с заданным цветом и параметрами отрисовки.pixels- рисует массив пикселей заданного размера на заданном смещении и c заданными параметрами отрисовки.
В функции этой секции плагин передает свой PPluginInterface для идентификации - он должен совпадать с возвращенным get_plugin_interface!
create_surface- редактор создает настроек для плагина. Принимает желаемый плагином размер окна. Редактор может игнорировать пожелание.destroy_surface- редактор уничтожает окно настроек.add- добавляет новый параметр заданного типа с заданным названием в окно настроек. Возвращает хендл для использования функции get.get- позволяет получить значение настройки по переданному хендлу. Принимает указатель на структуру, которую необходимо заполнить.
Секция должна быть определена, если приложение заявляет PFL_SHADER_SUPPORT, функции секции могут вызываться плагином только в случае заявленного PFL_SHADER_SUPPORT. В случае, если бит PFL_SHADER_SUPPORT не равен 1, секция должна быть заполнена нулями.
apply- применяет шейдер с переданным хендлом к слою, определенному в передаваемом RenderMode. ЕслиRenderMode == nullptr, не делает ничего.compile- компилирует шейдер из исходного кода, еслиis_filename == false, из файла с переданным именем, еслиis_filename == true. Возвращает хендл. Шейдер должен быть освобожден посредством вызоваreleaseпосле того, как шейдеру он перестает быть нужен, за время исполненияdeinitинтерфейса плагина все неосвобожденные шейдеры должны быть освобождены.release- освобождает шейдер по переданному хендлу, хендл после этой операции инвалидируется.set_uniform_int- устанавливает uniform-значение с именемnameв переданное, работает с переменной типаint.set_uniform_int_arr- устанавливает uniform-значение с именемnameв переданное, работает с массивом переменных типаint.set_uniform_float- устанавливает uniform-значение с именемnameв переданное, работает с переменной типаfloat.set_uniform_float_arr- устанавливает uniform-значение с именемnameв переданное, работает с массивом переменных типаfloat.
Содержит информацию о плагине, а также указатель на интерфейс плагина.
std_version- версия стандарта, с которой плагин готов работать. Должна совпадать с той, которая содержится в PPluginInterfacereserved- зарезервированный указатель. Плагину следует игнорировать ее в текущей версии стандартаinterface- указатель на интерфейс. Плагин гарантирует совпадение этого значения с тем, которое он возвращает в функцииget_plugin_interfacename- название плагина (нуль-терминированная строка неограниченной длины)version- версия плагина (нуль-терминированная строка неограниченной длины)author- автор плагина (нуль-терминированная строка неограниченной длины)description- описание плагина (нуль-терминированная строка неограниченной длины)type- тип плагина (эффект или инструмент)
Абстракция над двумерным вектором. Содержит два поля - координаты x и у типа float.
Абстракция над четырехкомпонентных цветом. Массив из четырех однобайтовых компонент в порядке RGBA.
Значение настройки плагина типа "текстовое поле". Содержит поле типа const char* с указателем на текст
Значение настройки плагина типа "ползунок". Содержит поле типа float с значением ползунка в пределаx [0;1]
Значение настройки плагина типа "2D-ползунок". Содержит вектор с значением ползунка в пределаx [0;1]x[0;1]
Значение для настройки плагина типа "выбор цвета". Содержит поле типа PRGBA с цветом.
Содержит информацию о желаемых параметрах отрисовки
blend- режим смешиванияdraw_policy- желаемый слой для рисования - preview-слой или основной
Все перечисления начинаются с нуля и дальше непрерывно увеличиваются, если явно не указано иное.
PPS_OK- возвращается функциями (де)инициализации плагина в случае успехаPPS_ERR- возвращается функциями (де)инициализации плагина в случае успеха
PFL_SHADER_SUPPORT(значение 1) - выставленный бит означает, что приложение поддерживает шейдерыPFL_SETTINGS_SUPPORT(значение 2) - выставленный бит означает, что приложение поддерживает настройки плагинов
PPT_EFFECT- плагин реализует эффектPPT_TOOL- плагин реализует инструмент
PPLP_BLEND- альфа-смешивание preview-слоя с основным при сбросе preview-слоя на основнойPPLP_COPY- смешивание замещением preview-слоя с основным при сбросе preview-слоя на основной
PPBM_COPY- смешивание замещением при вызове функцийrenderPPBM_ALPHA_BLEND- альфа-смешивание при вызове функцийrender
PPDP_PREVIEW- функцииrenderприменяются к preview-слоюPPDP_ACTIVE- функцииrenderприменяются к основному слою
Некоторые части Стандарта не являются обязательными для поддержки. В секции general структуры PAppInterface имеется поле feature_level - в нем хранится битовая маска поддерживаемых необязательных возможностей. Значение поля определяется константами PFeatureLevel, каждая из которых ответственна за один бит поля. Если соответствующий бит стоит, приложение заявляет о поддержке соответствующих возможностей. Если какие-то возможности не поддерживаются приложением, соответствующие указатели на функции в структуре PAppInterface обязаны быть нулевыми.
Для плагина видимыми являются два слоя - текущий выбранный слой (далее основной) в редакторе и preview-слой редактора. Preview-слой отображается выше основного, но ниже следующего после основного в редакторе.
Поведение preview-слоя для эффекта: непосредственно перед вызовом apply preview-слой очищается прозрачным, после работы apply preview-слой смешивается/заменяет текущий (согласно политике замещения).
Поведение preview-слоя для инструмента: непосредственно перед вызовом on_press preview-слой очищается прозрачным цветом, после работы on_release preview-слой смешивается/заменяет текущий (согласно политике замещения).
Редактор обязуется проверять политику замещения вызовом get_flush_policy каждый раз перед непосредственно замещением основного слоя. Тем самым, плагин может менять политику замещения во время работы.
При отрисовке всех примитивов плагин передает структуру PRenderMode, позволяющую плагину определить желаемые параметры отрисовки:
PDrawPolicy- желаемый слой для рисования - preview-слой или основнойPBlendMode- режим смешивания - либо примитив смешивается с текущим содержимым слоя, либо пиксели примитиво заменяют пиксели слоя.
Примитивы отрисовки и шейдеры были описаны в описании структуры PAppInterface, секции render и shader.
Посредством функций get_color и get_size (PAppInterface, секция general) плагин может узнать текущий цвет и размер. Редактор сам решает, что передавать. Подразумевается, что в качестве цвета передается текущий выбранный в палитре приложения, в качестве размера текущий выбранный размер кисти.
Плагины имеют возможность получать настройки от пользователя. Для этого плагин может определить набор настроек, которые редактор обязуется показать пользователю в виде окна. Размер, расположение окон, их компоновку редактор осуществляет самостоятельно. Существуют несколько типов настроек - для работы с каждым из них необходимо использовать соответствующую структуру. Функции работы с настройками принимают указатели типа void на эти структуры. Плагин должен передавать указатель на структуру, соответствующую переданному типу.
Как со стороны плагина, так и со стороны приложения может предоставляться дополнительный функционал. Для этого в стандарте реализован механизм расширений ("extensions"). Каждый разработчик плагина или приложения имеет право реализовать своё расширение и через него предоставить доступ к дополнительному функционалу. (Прежде чем приступать к разработке, однако, рекомендуется ознакомиться с секцией "Рекомендации по работе с расширениями"). Расширение "std" (PEXT_STD) зарезервировано для последующей стандартизации отдельным документом. На момент написания этого документа (04.12.2021) его использование запрещено, в дальнейшем всё взаимодействие с этим расширением будет урегулировано вышеупомянутым стандартом.
-
При разработке расширения следует реализовать возможность проверки коллизии имён расширений, например с помощью специальной функции, возвращающей некоторое уникальное магическое число.
-
Если вы предполагаете, что вашим расширением будут пользоваться другие лица, в рекомендательном порядке предлагаем вам внести информацию о нём в документ
plugin_common_extensions.mdв свободном формате, указав:- Название расширения
- Его автора
- Предоставляется ли оно плагином, приложением или обоими
- Примерную суть содержимого (кратко)
- Ссылку на собственный документ, документирующий использование расширения
Таким образом можно уменшить вероятность коллизий имён (что, однако, не даёт полной гарантии, так что дополнительная валидация всё же рекомендуется) и проинформировать потенциальных пользователей о своём расширении.
-
Продолжая предыдущий пункт, рекомендуется до реализации расширения удостовериться, что его имя ещё не используется никаким уже описанным в
plugin_common_extensions.md