Skip to content

Latest commit

 

History

History
229 lines (154 loc) · 29.1 KB

File metadata and controls

229 lines (154 loc) · 29.1 KB

ISO/IEC 228666:2021

Унифицированный интерфейс плагинов для графических редакторов

Что такое плагин

Плагин является расширением возможностей графического редактора. Каждый плагин является либо инструментом, либо эффектом.

  • Эффект - обработка, применяемая относительно всего изображения.
  • Инструмент - позиционная обработка, может учитывать текущее положение и состояние мыши.

Что такое расширение

Расширение - это набор функций, реализованных вне стандарта. Может предоставляться как плагином, так и редактором. Название расширения должно быть не длиннее 31 символа, не должно начинаться с цифры, и должно состоять из строчных латинских букв, цифр, и знаков '_', '-'. Названия функций в них должны соответствовать этим же требованиям. Дополнительная информация о расширениях предоставлена в секции "Расширения".

Основные структуры

PPluginInterface

Плагин является разделяемой библиотекой. Для начала работы с плагином редактор загружает разделяемую библиотеку в свое адресное пространство и находит в ней функцию get_plugin_interface. Она возвращает структуру PPluginInterface (см. исходник). В ней располагаются указатели на функции, реализуемые плагином и вызываемые редактором. Также в структуре указана версия Стандарта, с которым готов работать плагин. В текущей итерации Стандарта версия должна являться нулевым значением (0). Номер версии располагается самым первым полем в PPluginInterface - гарантируется, что это будет верно и для последующих версий стандарта. Таким образом, вся дальнейшая интерпретация структур должна зависеть от номера версии.

Поля структуры

  • std_version - версия стандарта, с которой плагин готов работать
  • reserved - зарезервированный указатель. Плагину следует игнорировать его в текущей версии стандарта
  • general.feature_level - уровень поддержки. Значение поля описано ниже.

Секция extensions:

  • enable: - активировать расширение плагина. Возвращает индикатор того, реализовано ли это расширение.
  • get_func: - получить указатель на функцию, реализованную в расширении с данным именем. Если функция не реализована, или если расширение, частью которого оно является, не реализовано или не было активировано, get_func должна вернуть нулевой указатель.

Cекция general:

  • init - функция инициализации плагина. Редактор обязуется вызвать эту функцию при загрузке плагина, передав в нее заполненную структуру PAppInterface - указатели на функции редактора. Содержимое PAppInterface определяется ниже. Функция возвращает статус исполнения - если статус не PPS_OK, то инициализация плагина провалилась и редактор не может продолжпть работу с плагином.

  • get_info - возвращает структуру PPluginInfo c базовой информацией и типом плагина - эффект или инструмент. Также содержит указатель на PPluginInterface.

  • deinit - деинициализация плагина. Редактор обязуется вызвать эту функцию при выгрузке плагина. Функция возвращает статус исполнения - если статус не PPS_OK, то деинициализация плагина провалилась и возможны утечки памяти.

  • dump - в ответ на вызов этой функции редактором плагин может вывести свое состояние глобальный лог приложения посредством функции log PAppInterface (см. ниже)

  • on_tick - данная функция периодически вызывается приложением, передавая в качестве аргумента время, прошедшее с предыдущего вызова в секундах

  • on_settings_update - данная функция (если имеется) вызывается тогда, когда изменены какие-то настройки. Поле может быть нулевым, в ином случае приложение обязяано вызывать его каждый раз, когда меняется какая-либо настройка.

  • get_flush_policy - данная функция возвращает политику замещения плагина. Если плагин возвращает PPLP_BLEND, то превью-слой должен альфа-смешиваться с основным, если PPLP_COPY - полностью заменять основной слой (про превью слой см. ниже)

Секция effect:

Секция должна быть определена для PPT_EFFECT. Если тип плагина отличен от PPT_EFFECT, секция должна быть заполнена нулями.

  • apply - при вызове приложением этой функции плагин должен произвести желаемые манипуляции со слоями (основным/preview).

Секция tool:

Секция должна быть определена для PPT_TOOL. Если тип плагина отличен от PPT_TOOL, секция должна быть заполнена нулями.

  • on_press - вызовом этой функции приложение уведомляет плагин о нажатии на кнопку мыши. Сообщается позиция мыши в момент нажатия. Плагин должен произвести желаемые манипуляции со слоями (основным/preview).
  • on_move - вызовом этой функции приложение уведомляет плагин о перемещении мыши. Сообщается старая и новая позиции мыши. Плагин должен произвести желаемые манипуляции со слоями (основным/preview).
  • on_release - вызовом этой функции приложение уведомляет плагин об отпуске кнопки мыши. Сообщается позиция мыши в момент отпуска. Плагин должен произвести желаемые манипуляции со слоями (основным/preview).

PAppInterface

Приложение предоставляет плагину набор функций, посредством которых он может делать что-то полезное. Этот набор функций определен структурой PAppInterface, которая является набором указателей на функции и передается приложением в плагин при инициализации.

Поля структуры

  • std_version - версия стандарта, с которой приложение готово работать
  • reserved - зарезервированный указатель. Плагину следует игнорировать ее в текущей версии стандарта

Секция extensions:

  • enable: - активировать расширение редактора. Возвращает индикатор того, реализовано ли это расширение.
  • get_func: - получить указатель на функцию, реализованную в расширении с данным именем. Если функция не реализована, или если расширение, частью которого оно является, не реализовано или не было активировано, get_func должна вернуть нулевой указатель.

Секция general:

  • feature_level - каждый бит поля соответствует элементу перечисления по степеням двойки PFeatureLevel. Бит выставляется тогда и только тогда, когда указанная особенность в полной мере поддерживается приложением.
  • log - функция логгирования. Позволяет плагину печатать сообщения в лог программы. Сигнатура как у printf без возвращаемого значения - void (char const*, ...)
  • get_absolute_time - возвращает время в секундах относительно запуска редактора.
  • release_pixels - удаляет массив пикселей, полученный от функции get_pixels (см. ниже). Плагин не имеет права передавать в эту функцию другие указатели или дважды вызывать ее с одним и тем же массивом, порождая ситуацию double-free.
  • get_color - возвращает текущий цвет. Плагин не обязан согласовывать цвет с предоставляемым программой. Программа не обязана поддерживать цвета всех инструментов одинаковыми, равно как и уникальными.
  • get_size - возвращает текущий размер (толщину). Плагин не обязан согласовывать толщину с предоставляемой программой. Программа не обязана поддерживать размеры всех инструментов одинаковыми, равно как и уникальными.

Секция target:

  • get_pixels - возвращает текущий слой как массив пикселей (массив цветов). Порядок следования пикселей построчный - сначала идут пиксели (0, 0), (0, 1), ..., непосредственно после окончания нулевой строки идет следующая (1, 0), (1, 1), ... и так до последней строки. Возвращаемый буфер является динамическим - плагин обязуется освободить его посредством release_pixels.
  • get_size - записывает размеры текущего слоя по переданным указателям.

Секция render:

  • circle - рисует круг (с заливкой) с заданным центром, радиусом, цветом и параметрами отрисовки.
  • line - рисует линию с заданным началом/концом с заданным цветом и параметрами отрисовки.
  • triangle - рисует треугольник (с заливкой) с заданными вершинами, цветом и параметрами отрисовки.
  • rectangle - рисует прямоугольник (с заливкой) со сторонами, параллельными осям координат по двум углам с заданным цветом и параметрами отрисовки.
  • pixels - рисует массив пикселей заданного размера на заданном смещении и c заданными параметрами отрисовки.

Секция settings:

В функции этой секции плагин передает свой PPluginInterface для идентификации - он должен совпадать с возвращенным get_plugin_interface!

  • create_surface - редактор создает настроек для плагина. Принимает желаемый плагином размер окна. Редактор может игнорировать пожелание.
  • destroy_surface - редактор уничтожает окно настроек.
  • add - добавляет новый параметр заданного типа с заданным названием в окно настроек. Возвращает хендл для использования функции get.
  • get - позволяет получить значение настройки по переданному хендлу. Принимает указатель на структуру, которую необходимо заполнить.

Секция shader:

Секция должна быть определена, если приложение заявляет 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.

PluginInfo

Содержит информацию о плагине, а также указатель на интерфейс плагина.

Поля структуры:

  • std_version - версия стандарта, с которой плагин готов работать. Должна совпадать с той, которая содержится в PPluginInterface
  • reserved - зарезервированный указатель. Плагину следует игнорировать ее в текущей версии стандарта
  • interface - указатель на интерфейс. Плагин гарантирует совпадение этого значения с тем, которое он возвращает в функции get_plugin_interface
  • name - название плагина (нуль-терминированная строка неограниченной длины)
  • version - версия плагина (нуль-терминированная строка неограниченной длины)
  • author - автор плагина (нуль-терминированная строка неограниченной длины)
  • description - описание плагина (нуль-терминированная строка неограниченной длины)
  • type - тип плагина (эффект или инструмент)

Служебные структуры и перечисления

PVec2f

Абстракция над двумерным вектором. Содержит два поля - координаты x и у типа float.

PRGBA

Абстракция над четырехкомпонентных цветом. Массив из четырех однобайтовых компонент в порядке RGBA.

PTextFieldSetting

Значение настройки плагина типа "текстовое поле". Содержит поле типа const char* с указателем на текст

PSlider1dSetting

Значение настройки плагина типа "ползунок". Содержит поле типа float с значением ползунка в пределаx [0;1]

PSlider2dSetting

Значение настройки плагина типа "2D-ползунок". Содержит вектор с значением ползунка в пределаx [0;1]x[0;1]

PColorPickerSetting

Значение для настройки плагина типа "выбор цвета". Содержит поле типа PRGBA с цветом.

PRenderMode

Содержит информацию о желаемых параметрах отрисовки

Поля структуры:

  • blend - режим смешивания
  • draw_policy - желаемый слой для рисования - preview-слой или основной

Перечисления

Все перечисления начинаются с нуля и дальше непрерывно увеличиваются, если явно не указано иное.

PPluginStatus

  • PPS_OK - возвращается функциями (де)инициализации плагина в случае успеха
  • PPS_ERR - возвращается функциями (де)инициализации плагина в случае успеха

PFeatureLevel

  • PFL_SHADER_SUPPORT (значение 1) - выставленный бит означает, что приложение поддерживает шейдеры
  • PFL_SETTINGS_SUPPORT (значение 2) - выставленный бит означает, что приложение поддерживает настройки плагинов

PPluginType

  • PPT_EFFECT - плагин реализует эффект
  • PPT_TOOL - плагин реализует инструмент

PPreviewLayerPolicy

  • PPLP_BLEND - альфа-смешивание preview-слоя с основным при сбросе preview-слоя на основной
  • PPLP_COPY - смешивание замещением preview-слоя с основным при сбросе preview-слоя на основной

PBlendMode

  • PPBM_COPY - смешивание замещением при вызове функций render
  • PPBM_ALPHA_BLEND - альфа-смешивание при вызове функций render

PDrawPolicy

  • PPDP_PREVIEW - функции render применяются к preview-слою
  • PPDP_ACTIVE - функции render применяются к основному слою

Терминология

Уровни поддержки

Некоторые части Стандарта не являются обязательными для поддержки. В секции general структуры PAppInterface имеется поле feature_level - в нем хранится битовая маска поддерживаемых необязательных возможностей. Значение поля определяется константами PFeatureLevel, каждая из которых ответственна за один бит поля. Если соответствующий бит стоит, приложение заявляет о поддержке соответствующих возможностей. Если какие-то возможности не поддерживаются приложением, соответствующие указатели на функции в структуре PAppInterface обязаны быть нулевыми.

Preview-слой

Для плагина видимыми являются два слоя - текущий выбранный слой (далее основной) в редакторе и 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