Импорт Form XObject из SVG
THotPDF.ImportSVGFormXObject разбирает SVG один раз и регистрирует один переиспользуемый PDF Form XObject, а THPDFPage.DrawSVGFormXObject размещает его в любом размере и опционально создаёт link-аннотации страниц
Объявление
function ImportSVGFormXObject(const Input: TBytes): AnsiString; overload;
function ImportSVGFormXObject(
const Input: TBytes;
out Statistics: THPDFSVGImportStatistics
): AnsiString; overload;
procedure DrawSVGFormXObject(
const FormName: AnsiString;
X, Y, W, H: Single;
AddLinks: Boolean = True
);
Векторный профиль
- Геометрия включает path с эллиптическими дугами, прямоугольники, скруглённые прямоугольники, круги, эллипсы, линии, polyline, polygon, трансформации, группы, symbol и ссылки
useтолько на фрагменты - Заливка включает сплошные RGB-цвета, opacity fill и stroke, fill rules, окончания и соединения линий, унаследованные dash-массивы и смещения, miter limit, векторные полосы линейных и радиальных градиентов, градиентные штрихи на основе цветных tiling-паттернов и clip path
- Opacity объектов и групп использует изолированные векторные Form прозрачности, поэтому перекрывающиеся потомки компонуются до применения объемлющей opacity
- Mask становятся ресурсами Form с группами прозрачности и PDF soft mask Alpha или Luminosity, включая отсечение области маски,
maskUnits,maskContentUnitsи ограниченные вложенные ссылки mask - CSS включает встроенные селекторы типа, класса, ID и составные, presentation attributes, inline-стили, специфичность, порядок в источнике и
!important - Импорт документов встраивает подмножества Unicode-шрифтов и карты
ToUnicodeчерез нативный движок авторинга, использует настроенные fallback-цепочки шрифтов, выравнивает fallback-прогоны по общей алфавитной базовой линии и вычисляет якорение текста по реальным ширинам глифов - Встроенные изображения PNG и JPEG становятся переиспользуемыми Image XObject, сохраняют alpha PNG как soft mask и поддерживают
preserveAspectRatio="none", центрированныйmeetи центрированныйslice - Ссылки HTTP, HTTPS и mail сохраняются как PDF link-аннотации с учётом размещения и не становятся частью переиспользуемого Form stream
Границы текста и заливки
Текст поддерживает сплошную заливку, варианты bold и italic, размер шрифта, трансформации, якорение, opacity и геометрическое отсечение; градиентная заливка текста жёстко отклоняется, а каждый узел text или tspan остаётся независимо позиционируемым прогоном, а не полноценным движком вёрстки текстового потока SVG
Импорт текста документов сохраняет выбранное начертание bold и italic через учитывающие стиль проверки глифов и резервную вёрстку, хранит измеренные границы краски и отклоняет действительно неразрешённые глифы
UTF-8-текст и XML-ссылки на символы в шестнадцатеричном или десятичном виде сохраняют одинаковые скаляры Unicode в Delphi и FPC, включая дополнительные скаляры в UTF-16 surrogate-парах
Автономная перегрузка HPDFBuildSVGFormData без text builder использует измеренные ширины Base 14 — Helvetica, Times и Courier — и отклоняет символы вне WinAnsi вместо подстановки вопросительных знаков; перегрузка с THPDFSVGTextRunBuilder принимает переданные вызывающим встроенные текстовые формы и метрики
Градиенты сохраняют ограниченную аппроксимацию векторными полосами; прозрачные ресурсы требуют PDF 1.4 и отклоняются строгим профилем PDF/A-1
Стили штрихов
stroke-dasharray, stroke-dashoffset и stroke-miterlimit работают через presentation attributes, встроенный CSS, inline-стили и наследование, включая группы и экземпляры use только на фрагменты
Dash-массивы принимают числа, разделённые запятыми или пробелами, и поддерживаемые длины; проценты считаются от нормализованной диагонали viewport, вычисляемой как sqrt((viewWidth * viewWidth + viewHeight * viewHeight) / 2)
Массивы нечётной длины повторяются до шаблона чётной длины, каждый подпуть перезапускает шаблон, а положительные и отрицательные смещения заворачиваются по полному шаблону; none и массивы из одних нулей дают сплошные штрихи
Рисуемые штрихи нулевой длины сохраняют marks с round или square caps; обычные сплошные штрихи, pattern градиентных штрихов, клипы, mask и изолированные группы opacity используют одни и те же настройки штриха
Miter limit по умолчанию равен 4; значения SVG 2 от 0 до 1 принимаются и используют bevel-соединения там, где miter превысил бы лимит, при этом границы градиентных и transparency-ресурсов сохраняют острые соединения в рамках выбранного лимита
Нативный рендеринг использует ограниченную dash-геометрию, чтобы сохранить смещения, дробные длины и массивы длиннее лимита GDI-пера, с адаптивным упрощением кривых и непрерывными рисуемыми соединениями через границы сегментов
Калибровка штрихов через pathLength остаётся за пределами профиля; фигуры, сочетающие несплошной dash-массив с pathLength, жёстко отклоняются, а не молча используют некалиброванные длины
Семантика штрихов следует модели штрихов SVG 2 в пределах бюджетов парсера и рендерера, описанных ниже
Конфигурация шейпинга текста
Встроенный SVG-текст использует настройки импортирующего документа ShapingFeatures, AutoShapeArabic, AutoShapeSyriac, AutoShapeNko, AutoShapeAdlam и AutoShapeHanifiRohingya, а также его выборы GSUB-скрипта и языка и fallback-цепочки шрифтов
Эти настройки применяются и при измерении ширин, и при генерации text appearance без изменения конфигурации вызывающего; шейпинг остаётся opt-in и требует шрифт с нужными глифами и таблицами OpenType
Каждое сгенерированное text appearance принимает не более 256 различных выборов шрифтов для шейпинга и 64 MiB суммарных сырых данных шрифтов; неподдерживаемые данные шрифта или превышенный лимит атомарно срывают импорт
Opacity объектов и групп
opacity применяется один раз к полному закрашенному результату своего узла и не наследуется потомками; fill-opacity и stroke-opacity сохраняют свои отдельные унаследованные значения заливки
Два перекрывающихся непрозрачных красных прямоугольника внутри <g opacity="0.5"> остаются одинаково полупрозрачными в перекрытии, а два независимо полупрозрачных прямоугольника в перекрытии становятся темнее
Вложенные группы компонуются по порядку: две объемлющие opacity 0.5 дают эффективные 0.25 поверх непрозрачного потомка, а явная opacity 1 у потомка не переопределяет объемлющую группу
Корневые узлы SVG, контейнеры, ссылки, ссылки на фрагменты, текст, изображения и фигуры идут одним путём opacity объектов; ссылки use только на фрагменты сохраняют стили и экземпляра, и ссылаемого узла
Alpha fill и stroke остаются независимыми, в том числе в их перекрытии внутри полупрозрачного объекта, а alpha градиентных stop комбинируется с alpha соответствующей заливки до композитинга объекта
Эффекты clip и mask принадлежат своему узлу, а не наследуются как настройки заливки потомков; геометрия ссылок остаётся с учётом размещения, а границы изолированных Form консервативно удерживают трансформированные штрихи и caps
Импортер сохраняет векторные операторы, встроенные текстовые Form, ресурсы изображений, pattern и mask внутри изолированных групп; он не сплющивает весь SVG в bitmap
Поддерживаемое поведение следует модели opacity объектов и групп SVG; прочие ограничения этой страницы на текст, градиенты и геометрию продолжают действовать
Безопасность и бюджеты
Импортер принимает обычный или gzip-сжатый SVG до 8 MiB и ограничивает развёрнутый ввод 32 MiB, суммарные операторы main, pattern, mask и group — 16 MiB, узлы — 4,096, вложенность — 64 уровнями, правила CSS — 256, а значения path — 100,000
Встроенные изображения принимают только строгие Base64 payload data:image/png;base64, и data:image/jpeg;base64, — не более 128 изображений, 16,384 пикселей по измерению и 16,777,216 декодированных пикселей на все изображения; размеры проверяются до нативного декодирования
Текст ограничен 128 прогонами и 65,536 единицами UTF-16 на прогон, а pattern градиентных штрихов, mask и изолированные группы opacity — 128 ресурсами каждого типа; рекурсивные ссылки mask жёстко отклоняются
Dash-массивы содержат не более 64 исходных записей до развёртывания нечётных массивов; положительные записи должны быть не меньше 0.000001 user units, отдельные длины и нормализованный цикл не должны превышать 1,000,000,000, абсолютные смещения — 1,000,000,000, а miter limit должен оставаться в диапазоне от 0 до 1,000,000
Реальные вложенные transparency-эффекты ограничены восемью уровнями, чтобы совпадать с нативным рендерером, независимо от лимита глубины дерева SVG; обычные вложенные контейнеры без transparency-эффектов эту квоту не расходуют
Границы transparency-эффектов должны быть конечными, и каждая координата должна оставаться в пределах абсолютного значения 1,000,000,000; импорты за рамками этого ограниченного координатного профиля отклоняются до регистрации групп или mask
Неудавшиеся импорты откатывают сгенерированные объекты, встроенные текстовые Form, записи реестра и состояние версии и device-цветов, так что вызывающий может переиспользовать тот же документ и сохранить объемлющую graph transaction
Скрипты, event handler'ы, DTD, foreignObject, неподдерживаемые data media types, JavaScript-URL и внешние URL заливки или ресурсов изображений жёстко отклоняются
Ссылки на фрагменты вроде url(#gradient), url(#clip) и href="#symbol" остаются внутри разобранного документа и никогда не приводят к доступу к файлам или сети
Статистика
THPDFSVGImportStatistics сообщает узлы, правила CSS, gradient, gradient stroke, mask, изображения, ссылки, text run, изолированные группы opacity через GroupCount и суммарные байты сгенерированных операторов main, pattern, mask и group
HPDFBuildSVGFormData открывает ограниченный парсер отдельно — через THPDFSVGFormData и THPDFSVGLinkInfo — для тех, кому нужно содержимое Form, собственные размеры, ресурсы opacity, payload изображений, потоки pattern и mask, имена текстовых ресурсов или метаданные ссылок до регистрации; Groups предоставляет потоки операторов изолированных групп и консервативные границы Form
Пример
Document.BeginDoc;
FormName := Document.ImportSVGFormXObject(SVGBytes, Statistics);
if FormName = '' then
raise Exception.Create('SVG import failed');
Document.CurrentPage.DrawSVGFormXObject(
FormName,
36,
72,
240,
120,
True
);
Document.CurrentPage.DrawSVGFormXObject(
FormName,
320,
72,
120,
60,
False
);
См. также: THotPDF.ImportSVGFormXObject, THPDFPage.DrawSVGFormXObject, HTML5 Paged-Media Import