Импорт HTML5 paged media
THPDFHTMLImporter.RenderHTML5 превращает терпимый к ошибкам HTML5-маркап и print CSS в разбитый на страницы PDF-контент, сохраняя компактный прежний путь RenderHTML
CSS-длины и Margin, BaseFontSize, ListIndent и BlockSpacing импортера заданы в пунктах, поэтому оба рендерера дают одинаковую страницу при любом THotPDF.Resolution; ваша собственная отрисовка до и после импорта по-прежнему использует 1/Resolution дюйма
Объявление
function RenderHTML5(
const HTML: WideString;
const AuthorStyleSheet: WideString = ''
): Boolean;
function HPDFRenderHTML5Document(
Doc: THotPDF;
const HTML: WideString;
const AuthorStyleSheet: WideString = '';
MarginPt: Single = 72;
const FontName: AnsiString = 'Arial';
FontSize: Single = 12
): Boolean;
Контракт профиля
HTML5ProfileVersion возвращает 1, а HTML5ProfileMilestones перечисляет этапы: парсер и cascade, постраничная вёрстка, таблицы и формы, ограниченные ресурсы
- Терпимый DOM допускает типичные пропущенные закрывающие теги, сохраняет порядок текста, пропускает неактивные области документа и соблюдает
MaxDOMNodes - Cascade поддерживает селекторы типа, класса, ID, атрибута равенства, потомков и прямых детей, порядок в исходнике, специфичность, inline-объявления,
!important,@media printи поля@page - Постраничная вёрстка поддерживает блочный поток, заголовки, списки, рамки, фоны, отступы блоков, явные разрывы страниц, таблицы, изображения и автоматическую пагинацию переполнения
- Текстовые поля, кнопки, флажки, переключатели, textarea и select рендерятся как статические изображения либо как нативные поля AcroForm, если включён
CreateAcroForms
Измеряемые абзацы и направление
Абзацы переносятся по измеренным ширинам текущего шрифта, включая смены шрифта, прогоны bold и italic, letter spacing, word spacing, явные разрывы строк и границы East Asian символов; выравнивание и декор применяются отдельно к каждой получившейся строке
direction: ltr, direction: rtl и HTML-атрибут dir выбирают направление абзаца; dir="auto" использует направление Unicode первого сильного символа
В Windows двунаправленные прогоны скриптов разрешаются через Uniscribe и переупорядочиваются через границы стилей, а существующий текстовый движок PDF обрабатывает шейпинг глифов внутри каждого прогона; направление документа, viewer preferences и сохранённое текстовое состояние страницы восстанавливаются после строки
Inline-переопределения направления, bdi и bdo пока используют порядок абзаца и дают диагностику hdkLayoutFallback; unicode-bidi вне этого профиля, а шейпинг скриптов по-прежнему следует конфигурации шейпинга документа
Фрагментация абзацев
widows и orphans — наследуемые положительные целые, обе по умолчанию 2; пагинация использует измеренные строчные боксы, а не оценочное число символов
Импортер переносит абзац или подстраивает его разрыв так, чтобы до и после разрыва страницы осталось запрошенное минимальное число строк; break-inside: avoid держит абзац целиком, когда он помещается на свежей странице
Когда страница не может вместить запрошенное ограничение, рендеринг продолжает движение, ослабляя ограничение и записывая hdkPaginationConstraint; каждый фрагмент страницы получает собственные фон и рамку
Опциональные переносы
hyphens: none подавляет discretionary-разрывы, а hyphens: manual по умолчанию использует U+00AD или ­; видимый дефис ставится, только когда выбранный разрыв использован
hyphens: auto дополнительно вызывает OnHyphenate со словом и унаследованным значением HTML lang; без callback сохраняются ручные разрывы и сообщается layout fallback, потому что словарь языка в комплект не входит
Позиции разрывов считаются в единицах кода UTF-16 от начала слова; невалидные, вне диапазона, режущие surrogate и режущие базовые combining mark позиции игнорируются
THPDFHTMLHyphenationEvent = procedure(
Sender: TObject;
const WordText, Language: WideString;
var BreakPositions: TArray<Integer>
) of object;
Ограниченные flex- и grid-боксы
display: flex поддерживает row, row-reverse, column и column-reverse; дети строки используют явные ширины или делят остаток ширины, а положительные flex-grow взвешивают дополнительное пространство
Строки поддерживают justify-content start, end, center, space-between, space-around и space-evenly плюс выравнивание поперечной оси start, end, center и stretch; поток колонок поддерживает естественную вертикальную вёрстку и даёт диагностику на неподдерживаемое распределение фиксированной высоты или выравнивание поперечной оси
display: grid поддерживает положительные треки колонок фиксированной длины и fr, включая ограниченный repeat(n, tracks) до 64 колонок; ячейки размещаются в порядке исходника, заполняя по одной строке за раз
grid-column: span N и grid-column-end: span N позволяют ребёнку занять последовательные треки и промежуточные gap; элемент, не влезающий в текущую строку, переходит на следующую, а span больше числа треков даёт layout fallback
flex-wrap: wrap начинает новую строку, когда явная ширина следующего элемента и gap не влезают; каждая строка независимо применяет flex-grow и justify-content, при этом row-reverse и RTL обращают позиции внутри каждой строки, не перенося элементы между строками
gap принимает одну или две длины, с независимыми переопределениями row-gap и column-gap; параллельные строки остаются на одной странице и проверяются до отрисовки
Параллельные дети поддерживают текстовые блоки с inline-стилями, рекурсивно вложенные обычные блочные контейнеры с padding, рамками и фонами, вложенные flex- и grid-контейнеры, изображения и статические или нативные контролы форм
Изображения используют байты из callback или data URI, сохраняют внутренние пропорции, когда высота не задана, и декодируются один раз на узел DOM; preflight и fallback переиспользуют то же кэшированное изображение, не расходуя новый запрос ресурса
Все дочерние боксы измеряются до отрисовки любой параллельной строки, поэтому неподдерживаемое или слишком крупное содержимое откатывается к вертикальному потоку страницы без повторения уже нарисованных строк; вложенное планирование ограничено 64 уровнями и расходует существующий бюджет операций вёрстки
Оборачивающиеся дети без явной ширины занимают целую строку; таблицы и списки внутри параллельных детей, flex basis и shrink, wrap-reverse, intrinsic sizing треков, треки строк и row span grid, а также явное grid-размещение остаются вне профиля и дают наблюдаемую диагностику
Диагностика неподдерживаемого CSS
Diagnostics раскрывает записи с Kind, Subject, Value и MessageText; OnDiagnostic получает ту же информацию во время рендеринга
Неизвестные свойства, неподдерживаемые значения, селекторы и at-rules игнорируются с диагностикой, включая объявления в неиспользуемых правилах стилей; pseudo-селекторы пропускаются, а не трактуются как обычные селекторы типа
StrictCSS, по умолчанию выключенный, поднимает EHPDFHTMLUnsupportedCSS на диагностике; предыдущее содержимое уже могло быть выведено, поэтому для импорта «всё или ничего» используйте отдельный документ
MaxDiagnostics по умолчанию 256 и ограничивает хранимые записи; DiagnosticCount и доставка в callback остаются наблюдаемыми после достижения лимита хранения, а неположительный лимит отключает хранение записей
Ограниченные ресурсы
Внешние стили, изображения и шрифты @font-face отключены, пока OnResource не передаст их байты, поэтому HTML-импорт никогда не открывает файлы и сетевые соединения неявно
@font-face поддерживает один источник url(...), опциональные format('truetype') или format('opentype'), псевдоним семейства, стиль normal или italic и вес normal, bold, 400 или 700; font-display принимает стандартные политики, потому что офлайн-импорт загружает ресурсы синхронно
Шрифты должны быть встраиваемыми ресурсами TrueType или OpenType sfnt с ASCII-именем семейства Windows длиной до 31 символа; WOFF, коллекции шрифтов, local(...), variable-дескрипторы и списки источников дают диагностику
Принятые шрифты регистрируются приватно в памяти процесса на Windows и остаются собственностью документа до его уничтожения, поэтому освобождение импортера до EndDoc не инвалидирует отложенное встраивание шрифтов
Ресурсы data: и результаты callback делят лимиты MaxResources, MaxResourceBytes и MaxTotalResourceBytes
MaxDecodedImageBytes по умолчанию 128 MiB и независимо ограничивает кэш декодированных изображений четырьмя байтами на пиксель; размеры BMP и PNG проверяются до декодирования, и каждая принятая картинка проверяется перед сохранением
MaxDOMNodes, MaxCSSRules и MaxLayoutOperations независимо ограничивают парсинг, построение cascade и работу вёрстки
THPDFHTMLResourceEvent = procedure(
Sender: TObject;
const URI: WideString;
ResourceKind: THPDFHTMLResourceKind;
var Data: TBytes;
var ContentType: string;
var Handled: Boolean
) of object;
Статистика
THPDFHTMLImportStatistics сообщает версию профиля, распарсенные узлы, CSS-правила, операции вёрстки, разрывы страниц, таблицы, контролы форм, запросы ресурсов, принятые и отклонённые загрузки, принятые байты ресурсов, измеренные текстовые строки, строки с переносами, диагностику, flex-контейнеры и grid-контейнеры
OnLineLayout получает индексы страницы и строки абзаца (с нуля), начало, измеренные ширину и высоту, логический текст, направление и флаг переноса после фактического вывода PDF-текста
Каждый вызов RenderHTML5 сбрасывает запись статистики, а нарушение бюджетов поднимает EHPDFHTMLImportBudget
Пример
Importer := THPDFHTMLImporter.Create(Doc);
try
Importer.CreateAcroForms := True;
Importer.MaxResources := 16;
Importer.RenderHTML5(
'<style>@page { margin: 36pt } ' +
'table { width: 100% }</style>' +
'<h1>Invoice</h1>' +
'<table><tr><td>Total</td><td>42</td></tr></table>' +
'<input name="approved" type="checkbox">'
);
finally
Importer.Free;
end;
См. также: THPDFPage.TextOutHTML, Декларативный layout DOM, Поддержка AcroForm