Імпорт пейдінгових медіа HTML5

THPDFHTMLImporter.RenderHTML5 перетворює толерантну розмітку HTML5 і друкарський 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 повідомляє про аналізатор і каскад, пейдінговий макет, таблиці та форми та обмежені ресурси

Виміряні абзаци та напрямок

Абзаци переносяться за виміряними ширинами поточного шрифту, зокрема зміни шрифтів, проходи жирного та курсиву, міжлітерні й міжсловні проміжки, явні розриви рядків і межі символів східноазійських письмів; вирівнювання та оздоблення застосовуються окремо до кожного утвореного рядка

direction: ltr, direction: rtl та HTML-атрибут dir обирають напрямок абзацу; dir="auto" використовує напрямок Unicode першого сильного символу

У Windows двонаправлені проходи письма розв'язуються через Uniscribe і перевпорядковуються крізь межі стилів, тоді як наявний текстовий рушій PDF виконує формування гліфів усередині кожного проходу; напрямок документа, уподобання переглядача та збережений текстовий стан сторінки відновлюються після рядка

Вбудовані перевизначення напрямку, bdi та bdo нині використовують порядок абзацу і дають діагностику hdkLayoutFallback; unicode-bidi поза цим профілем, а shaping письма досі слідує конфігурації shaping документа

Фрагментація абзаців

widows і orphans — успадковані додатні цілі числа, типово обидва 2; пагінація використовує виміряні рядкові блоки, а не оцінну кількість символів

Імпортер пересуває абзац або коригує його розбиття, щоб залишити запитану мінімальну кількість рядків до і після розриву сторінки; break-inside: avoid втримує абзац разом, коли він вміщується на свіжій сторінці

Коли сторінка не може вмістити запитане обмеження, рендеринг просувається, пом'якшуючи обмеження та записуючи hdkPaginationConstraint; кожен фрагмент сторінки отримує власний фон і межі

Опційне перенесення слів

hyphens: none пригнічує дискреційні розриви, а усталений hyphens: manual використовує U+00AD чи ­; видимий дефіс виводиться лише тоді, коли використано обраний розрив

hyphens: auto додатково викликає OnHyphenate зі словом та успадкованим значенням HTML lang; без зворотного виклику він зберігає ручні розриви та повідомляє резервний макет, адже словник мови до комплекту не входить

Позиції розривів відлічуються в одиницях коду UTF-16 від початку слова; недійсні, поза діапазоном, такі, що розрізають сурогатну пару, і базові позиції, що розрізають сполучну діакритику, ігноруються

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 дозволяють дочірньому елементу займати послідовні доріжки та проміжки між ними; елемент, що не вміщується в поточний рядок, пересувається до наступного, а проміжки, більші за кількість доріжок, дають резервний макет

flex-wrap: wrap починає новий рядок, коли явна ширина та проміжок наступного елемента не вміщуються; кожен рядок незалежно застосовує flex-grow і justify-content, тоді як row-reverse і RTL обертають позиції всередині кожного рядка, не пересуваючи елементи між рядками

gap приймає одну чи дві довжини, з незалежними перевизначеннями row-gap і column-gap; паралельні рядки залишаються на одній сторінці та перевіряються до малювання

Паралельні дочірні елементи підтримують текстові блоки з вбудованим стилюванням, рекурсивно вкладені звичайні блокові контейнери з padding, межами та фонами, вкладені контейнери flex і grid, зображення та статичні чи власні елементи керування форм

Зображення використовують байти від зворотного виклику чи data URI, зберігають власні пропорції, коли висота не задана, і декодуються один раз на вузол DOM; попередня перевірка та резервний шлях повторно використовують те саме кешоване зображення, не витрачаючи ще один запит ресурсу

Усі дочірні блоки вимірюються до малювання будь-якого паралельного рядка, тож непідтримуваний чи надмірний вміст повертається до вертикального потоку сторінки без повторення вже намальованих рядків; вкладене планування обмежене 64 рівнями та витрачає наявний бюджет операцій макета

Дочірні елементи, що переносяться, без явної ширини займають один повний рядок; таблиці та списки всередині паралельних дочірніх елементів, flex basis і shrink, wrap-reverse, внутрішнє визначення розміру доріжок, доріжки та проміжки рядків grid і явне розміщення grid залишаються поза цим профілем і дають спостережувану діагностику

Діагностика непідтримуваного CSS

Diagnostics відкриває записи з Kind, Subject, Value і MessageText; OnDiagnostic отримує ту саму інформацію під час рендерингу

Невідомі властивості, непідтримувані значення, непідтримувані селектори та непідтримувані at-правила ігноруються з діагностикою, зокрема оголошення в решті невикористовуваних правилах таблиці стилів; псевдоселектори пропускаються, а не трактуються як звичайні селектори типів

StrictCSS, вимкнений типово, викликає EHPDFHTMLUnsupportedCSS при діагностиці; попередній вміст міг уже бути виданий, тож викликачам, яким потрібен імпорт усе-або-нічого, варто використовувати окремий документ

MaxDiagnostics типово дорівнює 256 і обмежує збережені записи; DiagnosticCount і доставка через зворотний виклик залишаються спостережуваними після досягнення межі сховища, а недодатна межа вимикає збереження записів

Обмежені ресурси

Зовнішні таблиці стилів, зображення та шрифти @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(...), дескриптори варіативних шрифтів і списки джерел дають діагностику

Прийняті шрифти реєструються приватно в пам'яті процесу на Windows і залишаються власністю документа до його знищення, тож вивільнення імпортера до EndDoc не інвалідує відкладене вбудування шрифтів

Ресурси data: та результати зворотних викликів поділяють межі MaxResources, MaxResourceBytes і MaxTotalResourceBytes

MaxDecodedImageBytes типово дорівнює 128 MiB і незалежно обмежує кеш декодованих зображень чотирма байтами на піксель; розміри BMP і PNG перевіряються перед декодуванням, а кожне прийняте зображення перевіряється перед збереженням

MaxDOMNodes, MaxCSSRules і MaxLayoutOperations незалежно обмежують аналіз, побудову каскаду та роботу макета

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, Декларативний DOM макета, Підтримка AcroForm