ייבוא מדיה מפולחת של HTML5

THPDFHTMLImporter.RenderHTML5 ממיר סימון HTML5 סלחני ו-CSS להדפסה לתוכן PDF ממוסגר תוך שימור נתיב ה-RenderHTML הקומפקטי הקודם

אורכי CSS וה-Margin, ‏BaseFontSize, ‏ListIndent ו-BlockSpacing של ה-importer נמדדים בנקודות, כך ששני ה-renderers מפיקים את אותו עמוד לא משנה למה 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 מדווח פרסור ואשכולות, פריסה ממוסגרת, טבלאות וטפסים ומשאבים מוגבלים

פסקאות ממודדות וכיוון

פסקאות נארזות לפי ההתקדמויות הממודדות של הגופן הנוכחי, לרבות שינויי גופן, ריצות bold ו-italic, מרווחי אותיות, מרווחי מילים, מעברי שורה מפורשים וגבולות תווים של מזרח-אסיה; יישור ועיטור חלים בנפרד על כל שורה שנוצרת

direction: ltr, direction: rtl ומאפיין ה-dir של HTML בוחרים את כיוון הפסקה; dir="auto" משתמש בכיוון ה-Unicode של התו החזק הראשון

ב-Windows ריצות כתב דו-כיווניות נפתרות עם Uniscribe ומסודרות מחדש על פני גבולות סגנון, בעוד מנוע טקסט ה-PDF הקיים מטפל בעיצוב הגליפים בתוך כל ריצה; כיוון המסמך, העדפות ה-viewer ומצב טקסט העמוד השמור משוחזרים אחרי השורה

עקיפות כיוון בשורה, bdi ו-bdo כרגע משתמשות בסידור של הפסקה ומפיקות אבחון hdkLayoutFallback; unicode-bidi נמצא מחוץ לפרופיל הזה, ועיצוב הכתב עדיין עוקב אחרי תצורת ה-shaping של המסמך

פיצול פסקאות

widows ו-orphans הם מספרים שלמים חיוביים בירושה, שניהם עם ברירת מחדל 2; הפניאה משתמשת בתיבות השורה הממודדות ולא בהערכה של מספר תווים

המייבא מזיז פסקה או מכוונן את הפיצול שלה כדי להשאיר את המספר המינימלי המבוקש של שורות לפני ואחרי מעבר עמוד; break-inside: avoid שומר פסקה ביחד כשהיא נכנסת לעמוד חדש

כשעמוד לא יכול להכיל את האילוץ המבוקש, העיבוד מתקדם בהקלת האילוץ וברישום hdkPaginationConstraint; כל מקטע עמוד מקבל רקע וגבול משלו

מיקוף אופציונלי

hyphens: none מדכא מעברים וולונטריים, וברירת המחדל hyphens: manual משתמשת ב-U+00AD או ב-­; מיקוף גלוי נפלט רק כשהמעבר שנבחר אכן בשימוש

hyphens: auto בנוסף קורא ל-OnHyphenate עם המילה ועם ערך ה-lang של ה-HTML בירושה; בלי callback הוא שומר על מעברים ידניים ומדווח על fallback של פריסה, כי לא מצורף מילון שפה

מיקומי מעבר נספרים ביחידות קוד UTF-16 מתחילת המילה; מיקומים לא תקינים, מחוץ לטווח, כאלה שחוצים זוג surrogate וכאלה שחוצים סימן משולב בסיסי מוזנחים

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 מאפשרים לצאצא לתפוס מסילות עוקבות ואת המרווחים שביניהן; פריט שלא נכנס לשורה הנוכחית עובר לשורה הבאה, ו-span גדול ממספר המסילות מפיק fallback של פריסה

flex-wrap: wrap פותח שורה נוספת כשהרוחב המפורש והמרווח של הפריט הבא לא נכנסים; כל שורה מחילה בנפרד flex-grow ו-justify-content, בעוד row-reverse ו-RTL הופכים מיקומים בתוך כל שורה בלי להעביר פריטים בין שורות

gap מקבל אורך אחד או שניים, עם עקיפות בלתי-תלויות של row-gap ו-column-gap; שורות מקבילות נשארות בעמוד אחד ונבדקות לפני הציור

צאצאים מקבילים תומכים בבלוקי טקסט עם עיצוב בשורה, במכולות בלוק רגילות מקוננות רקורסיבית עם padding, גבולות ורקעים, במכולות flex ‏ו-grid ‏מקוננות, בתמונות ובבקרות טופס סטטיות או native

תמונות משתמשות ב-bytes שסיפק callback או ב-data URI, שומרות על יחס-המידות הטבעי שלהן כשלא צוין גובה, ומפוענחות פעם אחת לכל צומת DOM; preflight ו-fallback עושים שימוש חוזר באותה תמונה שנשמרה במטמון בלי לצרוך בקשת משאב נוספת

כל תיבות הצאצאים ממודדות לפני ציור של כל שורה מקבילה, כך שתוכן שאינו נתמך או עודף נופל בחזרה לזרימת עמוד אנכית בלי לחזור על שורות שכבר צוירו; תכנון מקונן תחום ל-64 רמות וצורך את תקציב פעולות הפריסה הקיים

צאצאים אורזים בלי רוחב מפורש תופסים שורה שלמה; טבלאות ורשימות בתוך צאצאים מקבילים, flex basis ‏ו-shrink, wrap-reverse, מדידת מסילות טבעית, מסילות שורות ו-row span של grid, ומיקום grid ‏מפורש נשארים מחוץ לפרופיל הזה ומפיקים אבחונים ניתנים לצפייה

אבחוני CSS ‏לא נתמך

Diagnostics חושף רשומות המכילות Kind, Subject, Value ‏ו-MessageText; OnDiagnostic מקבל את אותו מידע בזמן העיבוד

מאפיינים לא מוכרים, ערכים שאינם נתמכים, בוררים שאינם נתמכים וכללי at-rule ‏שאינם נתמכים מוזנחים עם אבחון, לרבות הצהרות בכללי גיליון-סגנון שאחרת אינם בשימוש; בוררי pseudo מדולגים במקום להיחשב בוררי סוג רגילים

StrictCSS, המנוטרל כברירת מחדל, מעלה EHPDFHTMLUnsupportedCSS עם כל אבחון; ייתכן שתוכן קודם כבר נפלט, ולכן קוראים שדורשים ייבוא הכול-או-כלום צריכים להשתמש במסמך נפרד

MaxDiagnostics שואף כברירת מחדל ל-256 ותוחם את הרשומות שנשמרות; DiagnosticCount ומסירת ה-callback נשארים נצפים גם אחרי הגעה למגבלת האחסון, ומגבלה שאינה חיובית מנטרלת אחסון רשומות

משאבים מוגבלים

גליונות סגנון חיצוניים, תמונות וגופני @font-face מושבתים אלא אם OnResource מספק את ה-bytes שלהם, כך שייבוא HTML לעולם אינו פותח קובץ או חיבור רשת באופן משתמע

@font-face תומך במקור url(...) אחד, ב-format('truetype') או format('opentype') אופציונליים, בכינוי משפחה, בסגנון normal או italic ובמשקל normal, bold, 400 או 700; font-display מקבל את המדיניות הסטנדרטיות כי ייבוא אופליין טוען משאבים באופן סינכרוני

גופנים חייבים להיות משאבי TrueType או OpenType sfnt הניתנים להטמעה עם שם משפחת Windows ב-ASCII של עד 31 תווים; WOFF, אוספי גופנים, local(...), descriptors משתנים ורשימות מקורות מפיקים אבחונים

גופנים שהתקבלו נרשמים באופן פרטי בזיכרון התהליך ב-Windows ונשארים בבעלות המסמך עד שהוא נהרס, כך ששחרור המייבא לפני EndDoc לא מבטל הטמעת גופנים נדחית

משאבי data: ותוצאות callback חולקים את מגבלות MaxResources, MaxResourceBytes ו-MaxTotalResourceBytes

MaxDecodedImageBytes ברירת המחדל שלו 128 MiB והוא תוחם בנפרד את מטמון התמונות המפוענחות בארבעה bytes לפיקסל; ממדי 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