Import de pages HTML5

THPDFHTMLImporter.RenderHTML5 convertit un balisage HTML5 tolérant et des CSS d'impression en contenu PDF paginé tout en conservant le chemin compact hérité RenderHTML

Les longueurs CSS et les Margin, BaseFontSize, ListIndent et BlockSpacing de l’importeur sont en points, si bien que les deux moteurs de rendu produisent la même page quelle que soit la valeur de THotPDF.Resolution ; votre propre dessin avant et après l’import continue d’utiliser le 1/Resolution de pouce

Déclaration

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;

Contrat de profil

HTML5ProfileVersion retourne 1 et HTML5ProfileMilestones signale l'analyse et la cascade, la mise en page paginée, les tableaux et formulaires, ainsi que les ressources bornées

Paragraphes mesurés et direction

Les paragraphes se replient en utilisant les avances mesurées de la police courante, y compris changements de police, runs gras et italiques, letter spacing, word spacing, sauts de ligne explicites et frontières de caractères est-asiatiques ; l’alignement et la décoration s’appliquent séparément à chaque ligne résultante

direction: ltr, direction: rtl et l’attribut HTML dir sélectionnent la direction du paragraphe ; dir="auto" utilise la direction Unicode du premier caractère fort

Sous Windows, les runs bidirectionnels sont résolus avec Uniscribe et réordonnés au-delà des frontières de style, tandis que le moteur de texte PDF existant gère le façonnage des glyphes dans chaque run ; la direction du document, les préférences du viewer et l’état du texte de page enregistré sont restaurés après la ligne

Les substitutions de direction en ligne, bdi et bdo utilisent actuellement l’ordre du paragraphe et produisent un diagnostic hdkLayoutFallback ; unicode-bidi est hors de ce profil, et le façonnage des scripts suit toujours la configuration de façonnage du document

Fragmentation des paragraphes

widows et orphans sont des entiers positifs hérités, tous deux à 2 par défaut ; la pagination utilise les line boxes mesurées plutôt qu’un nombre estimé de caractères

L’importeur déplace un paragraphe ou ajuste sa coupure pour laisser le nombre minimum de lignes demandé avant et après un saut de page ; break-inside: avoid garde un paragraphe entier lorsqu’il tient sur une page neuve

Lorsqu’une page ne peut pas honorer la contrainte demandée, le rendu progresse en relâchant la contrainte et en enregistrant hdkPaginationConstraint ; chaque fragment de page reçoit son propre fond et sa propre bordure

Césure facultative

hyphens: none supprime les coupes discrétionnaires, et le hyphens: manual par défaut utilise U+00AD ou ­ ; un trait d’union visible n’est émis que lorsque la coupe sélectionnée est utilisée

hyphens: auto appelle en plus OnHyphenate avec le mot et la valeur HTML lang héritée ; sans callback, il conserve les coupes manuelles et signale un repli de mise en page, car aucun dictionnaire de langue n’est embarqué

Les positions de coupe comptent des unités de code UTF-16 depuis le début du mot ; les positions invalides, hors plage, coupant une paire de substitution ou coupant un signe diacritique de base sont ignorées

THPDFHTMLHyphenationEvent = procedure(
  Sender: TObject;
  const WordText, Language: WideString;
  var BreakPositions: TArray<Integer>
) of object;

Boîtes flex et grid bornées

display: flex prend en charge row, row-reverse, column et column-reverse ; les enfants d’une rangée utilisent des largeurs explicites ou partagent la largeur restante, et des valeurs flex-grow positives pondèrent l’espace supplémentaire

Les rangées prennent en charge justify-content start, end, center, space-between, space-around et space-evenly, plus les alignements d’axe transversal start, end, center et stretch ; le flux en colonne prend en charge la disposition verticale naturelle et émet un diagnostic pour une distribution en hauteur fixe ou un alignement transversal non pris en charge

display: grid prend en charge les pistes de colonnes en longueur fixe positive et en fr, y compris repeat(n, tracks) borné avec jusqu’à 64 colonnes ; les cellules sont placées dans l’ordre de la source, en remplissant une rangée à la fois

grid-column: span N et grid-column-end: span N permettent à un enfant d’occuper des pistes consécutives et leurs goutières ; un élément qui ne tient pas dans la rangée courante passe à la rangée suivante, et des spans supérieurs au nombre de pistes produisent un repli de mise en page

flex-wrap: wrap démarre une nouvelle ligne lorsque la largeur explicite et la goutière de l’élément suivant ne tiennent pas ; chaque ligne applique indépendamment flex-grow et justify-content, tandis que row-reverse et RTL inversent les positions à l’intérieur de chaque ligne sans déplacer d’éléments entre les lignes

gap accepte une ou deux longueurs, avec des substitutions indépendantes row-gap et column-gap ; les rangées parallèles restent sur une seule page et sont vérifiées avant le rendu

Les enfants parallèles prennent en charge les blocs de texte avec style en ligne, les conteneurs de blocs ordinaires récursivement imbriqués avec padding, bordures et fonds, les conteneurs flex et grid imbriqués, les images, et les contrôles de formulaire statiques ou natifs

Les images utilisent les octets fournis par callback ou en URI de données, conservent leur rapport hauteur/largeur intrinsèque en l’absence de hauteur spécifiée et sont décodées une seule fois par nœud DOM ; le preflight et le repli réutilisent la même image en cache sans consommer une autre demande de ressource

Toutes les boîtes enfants sont mesurées avant que toute rangée parallèle ne soit peinte, si bien qu’un contenu non pris en charge ou trop grand retombe sur le flux vertical de page sans répéter les rangées déjà peintes ; la planification imbriquée est bornée à 64 niveaux et consomme le budget d’opérations de mise en page existant

Les enfants enveloppants sans largeur explicite occupent une ligne complète ; les tableaux et listes à l’intérieur d’enfants parallèles, flex-basis et shrink, wrap-reverse, le dimensionnement intrinsèque des pistes, les pistes de rangées et spans de grid, et le placement grid explicite restent hors de ce profil et produisent des diagnostics observables

Diagnostics CSS non pris en charge

Diagnostics expose des enregistrements contenant Kind, Subject, Value et MessageText ; OnDiagnostic reçoit la même information pendant le rendu

Les propriétés inconnues, valeurs non prises en charge, sélecteurs non pris en charge et at-rules non pris en charge sont ignorés avec un diagnostic, y compris les déclarations de règles de stylesheet autrement inutilisées ; les pseudo-sélecteurs sont ignorés plutôt que traités comme des sélecteurs de type ordinaires

StrictCSS, désactivé par défaut, lève EHPDFHTMLUnsupportedCSS à chaque diagnostic ; du contenu antérieur peut déjà avoir été émis, les appelants exigeant un import tout-ou-rien doivent donc utiliser un document séparé

MaxDiagnostics vaut 256 par défaut et borne les enregistrements retenus ; DiagnosticCount et la livraison par callback restent observables après atteinte de la limite de stockage, et une limite non positive désactive le stockage des enregistrements

Ressources bornées

Les feuilles de style, images et polices @font-face externes sont désactivées sauf si OnResource fournit leurs octets, de sorte que l'import HTML n'ouvre jamais un fichier ou une connexion réseau implicitement

@font-face prend en charge une source url(...) unique, format('truetype') ou format('opentype') facultatif, un alias de famille, un style normal ou italique, et un poids normal, bold, 400 ou 700 ; font-display accepte les politiques standard car l’import hors ligne charge les ressources de façon synchrone

Les polices doivent être des ressources sfnt TrueType ou OpenType incorporables avec un nom de famille Windows ASCII d’au plus 31 caractères ; WOFF, collections de polices, local(...), descripteurs variables et listes de sources produisent des diagnostics

Les polices acceptées sont enregistrées en privé dans la mémoire du processus sous Windows et restent la propriété du document jusqu’à sa destruction, si bien que libérer l’importeur avant EndDoc n’invalide pas l’incorporation différée des polices

Les ressources data: et les résultats de rappel partagent les limites MaxResources, MaxResourceBytes et MaxTotalResourceBytes

MaxDecodedImageBytes vaut 128 Mio par défaut et borne indépendamment le cache d’images décodées à quatre octets par pixel ; les dimensions BMP et PNG sont vérifiées avant décodage, et chaque image acceptée est vérifiée avant d’être retenue

MaxDOMNodes, MaxCSSRules et MaxLayoutOperations bornent indépendamment l'analyse, la construction de la cascade et le travail de mise en page

THPDFHTMLResourceEvent = procedure(
  Sender: TObject;
  const URI: WideString;
  ResourceKind: THPDFHTMLResourceKind;
  var Data: TBytes;
  var ContentType: string;
  var Handled: Boolean
) of object;

Statistiques

THPDFHTMLImportStatistics signale la version du profil, les nœuds analysés, les règles CSS, les opérations de mise en page, les sauts de page, les tableaux, les contrôles de formulaire, les demandes de ressources, les chargements acceptés et rejetés, les octets de ressources acceptés, les lignes de texte mesurées, les lignes césurées, les diagnostics, les conteneurs flex et les conteneurs grid

OnLineLayout reçoit, après émission du texte PDF effectif, les index de page et de ligne de paragraphe de la ligne à partir de zéro, l’origine, la largeur et la hauteur mesurées, le texte logique, la direction et l’indicateur de césure

Chaque appel RenderHTML5 réinitialise l'enregistrement de statistiques, et les violations de budget déclenchent EHPDFHTMLImportBudget

Exemple

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;

Voir aussi : THPDFPage.TextOutHTML, DOM de mise en page déclarative, Prise en charge AcroForm