Работа с векторной графикой в FireMonkey с помощью SVG
SVG удобно использовать в приложениях FireMonkey, когда один графический ресурс должен одинаково хорошо выглядеть на смартфоне, планшете, мониторе и экране с высокой плотностью пикселей. Логотипы, иконки, схемы, элементы навигации и простые иллюстрации в этом формате описываются XML-кодом, а не набором заранее подготовленных растровых изображений.
Для разработчика на Delphi это особенно полезно в кроссплатформенных проектах. FireMonkey позволяет создавать интерфейсы для Android, iOS, Windows, macOS и Linux, а SVG помогает сохранить единый визуальный стиль приложения. При этом важно учитывать особенности конкретной версии Delphi, используемых компонентов и целевой операционной системы.
Почему SVG подходит для FireMonkey
Растровая картинка хранит цвет каждого пикселя. При увеличении изображения появляются размытые края, а для разных разрешений приходится создавать несколько вариантов одного ресурса. SVG описывает линии, кривые, контуры, заливки и трансформации, поэтому движок может заново рассчитать изображение под текущий размер элемента.
Векторный формат хорошо подходит для интерфейсной графики. Иконка размером 16 пикселей и та же иконка размером 128 пикселей используют один исходный файл. Это упрощает сопровождение проекта, уменьшает количество ресурсов и помогает избежать заметной пикселизации на современных дисплеях.
SVG также поддерживает прозрачность, градиенты, обводки, группировку объектов и простую анимационную структуру. Однако это не означает, что любой сложный SVG будет одинаково обработан всеми версиями FireMonkey. Фильтры, маски, внешние шрифты и некоторые расширения формата могут потребовать предварительной оптимизации или специального решения.
Представление векторных данных в FireMonkey
В FireMonkey графика обычно отображается через визуальные объекты, такие как TImage, TPath, TPaintBox и элементы списков изображений. TImage удобен для готовых ресурсов, а TPath подходит для построения контуров средствами Delphi и последующего управления их заливкой, обводкой и геометрией.
В зависимости от версии RAD Studio SVG может загружаться через стандартные механизмы изображения, список ресурсов или дополнительные классы и библиотеки. Поэтому перед реализацией стоит проверить документацию конкретной версии Delphi и фактическую поддержку SVG на каждой целевой платформе. Одинаковый исходный код не всегда означает одинаковый набор поддерживаемых возможностей.
Если нужен только простой контур, SVG можно преобразовать в данные пути и использовать объект TPath. Такой подход позволяет программно менять цвет, толщину линии, масштаб и положение. Он особенно удобен для небольших пиктограмм, которые должны реагировать на состояние кнопки или тему оформления приложения.
Загрузка SVG-ресурса
В простом случае изображение можно загрузить в TImage из файла:
procedure TMainForm.LoadIcon;
begin
ImageIcon.Bitmap.LoadFromFile('assets/icon.svg');
ImageIcon.WrapMode := TImageWrapMode.Fit;
end;
Этот пример предполагает, что текущая версия FireMonkey и подключенный графический код умеют распознавать SVG через TBitmap. На практике поведение может различаться, поэтому обработку ошибок лучше добавить сразу. Если формат не поддерживается напрямую, SVG можно преобразовать в TPathData, использовать сторонний SVG-рендерер или заранее экспортировать ресурс в несколько растровых вариантов.
Для мобильных приложений не стоит полагаться на относительный путь к файлу. SVG следует включать в проект как ресурс, размещать в каталоге, доступном приложению, либо загружать через TResourceStream. Такой вариант надежнее при установке APK, IPA или пакета для настольной системы, поскольку рабочий каталог приложения может отличаться от каталога проекта.
var
Stream: TResourceStream;
begin
Stream := TResourceStream.Create(HInstance, 'APP_ICON', RT_RCDATA);
try
ImageIcon.Bitmap.LoadFromStream(Stream);
finally
Stream.Free;
end;
end;
Имя ресурса и способ регистрации зависят от проекта. При использовании набора иконок полезно создать единый слой загрузки: он проверяет наличие ресурса, выбирает нужный вариант и возвращает понятную ошибку вместо аварийного завершения формы.
Масштабирование и координатная система
Качество отображения во многом определяется атрибутом viewBox. Он задает внутреннюю систему координат SVG и позволяет масштабировать содержимое без изменения самих контуров. Например, viewBox="0 0 24 24" часто используется для интерфейсных иконок, после чего изображение можно выводить в область 24, 48 или 96 пикселей.
У самого компонента FireMonkey нужно правильно выбрать режим вписывания. Для TImage важны свойства WrapMode, выравнивание и размеры контейнера. Режим Fit сохраняет пропорции, но может оставить свободное место по одной из сторон. Режим, растягивающий изображение по всей области, заполнит контейнер, однако способен исказить окружность или симметричную иконку.
Проблемы часто возникают из-за несовпадения пропорций viewBox и видимой области. Если изображение выглядит смещенным, обрезанным или неожиданно растянутым, нужно проверить исходный SVG, размеры компонента и правила сохранения пропорций. Для адаптивного интерфейса лучше масштабировать контейнер, а не изменять координаты каждой фигуры вручную.
На экранах с высокой плотностью пикселей SVG обычно дает особенно заметный выигрыш. Тем не менее итоговая резкость зависит от качества рендеринга и сглаживания на конкретной платформе. Тонкие линии могут выглядеть по-разному на Windows, Android и macOS, поэтому важные элементы интерфейса стоит проверять на реальных устройствах.
Цвета, темы и интерактивные элементы
Статический SVG часто содержит жестко заданные значения fill и stroke. Для приложения с темной и светлой темой это неудобно: один и тот же файл может иметь недостаточный контраст на другом фоне. Практичным решением становится подготовка вариантов ресурса или замена цветов после разбора SVG.
Когда контур представлен объектом TPath, цвет можно менять через свойства кисти и пера FireMonkey. Условный пример выглядит так:
PathIcon.Fill.Kind := TBrushKind.Solid;
PathIcon.Fill.Color := TAlphaColorRec.White;
PathIcon.Stroke.Kind := TBrushKind.None;
Названия свойств и доступные перечисления могут отличаться в зависимости от типа объекта и версии Delphi. Важно разделять цвет самого SVG и цвет фонового элемента. Если иконка должна менять состояние при наведении, нажатии или блокировке, заранее определите набор цветов и не смешивайте его с логикой загрузки ресурсов.
Для символов, логотипов и декоративных элементов можно оставить исходную палитру. Для кнопок и элементов навигации лучше использовать контрастные цвета, соответствующие общей теме приложения. Если SVG содержит текст, желательно перевести его в кривые либо обеспечить наличие нужного шрифта на каждой платформе.
Производительность и организация ресурсов
Небольшая иконка почти не влияет на производительность, но сложная иллюстрация с большим числом путей, градиентов и фильтров может дорого обходиться при повторной отрисовке. Это особенно заметно в прокручиваемых списках, где десятки элементов одновременно используют векторную графику.
SVG, который не меняется во время работы, лучше загрузить один раз и переиспользовать. Не следует читать файл с диска при каждом появлении формы или каждом вызове OnPaint. Для часто используемых ресурсов полезно применять кэш, TImageList или заранее подготовленные объекты, если выбранная версия FireMonkey поддерживает такое хранение.
Сложные изображения стоит упростить в графическом редакторе: удалить невидимые слои, объединить лишние контуры, убрать неиспользуемые стили и сократить количество узлов. Для фотографий SVG не подходит — там эффективнее обычные растровые форматы. Векторный ресурс раскрывает свои преимущества прежде всего в логотипах, диаграммах, схемах и интерфейсных пиктограммах.
Перед выпуском кроссплатформенного приложения необходимо проверить загрузку и отображение SVG на каждой целевой системе. Нужно протестировать прозрачность, масштабирование, цвета, поведение при смене ориентации и работу без доступа к исходной файловой системе. Такой контроль помогает обнаружить различия между графическими бэкендами FireMonkey еще до публикации приложения.