PDFium Component valide les limites d'implémentation de ISO 19005-1 Annex C — jetons de nom de 127 octets, 8191 éléments de tableau, 4095 entrées de dictionnaire et 28 niveaux d'imbrication de conteneur — et signale une police TrueType symbolique qui porte une entrée /Encoding. Les deux contrôles tournent sur le chemin de balayage d'octets, donc une application Delphi ou Lazarus obtient le verdict sans charger la DLL PDFium du tout
Ce sont les échecs qui déroutent le plus les gens, car le document paraît fin. Il se rend, il imprime, chaque police est incorporée, l'intention de sortie est présente. Puis un validateur le rejette sur un dictionnaire qui a 4096 entrées, et rien dans le document visible n'explique pourquoi
Que protègent réellement les limites Annex C ?
L interopérabilité avec les implémentations qui précèdent votre générateur. Annex C reporte les limites d'implémentation de la PDF Reference dans chaque partie PDF/A, et les chiffres ne sont pas arbitraires — ils décrivent ce qu'un lecteur conforme était historiquement tenu de gérer. Un fichier qui les dépasse peut s'ouvrir parfaitement dans une visionneuse moderne et échouer dans le lecteur d'archivage sur lequel un système de records s'est standardisé il y a quinze ans, ce qui est précisément le scénario que PDF/A existe pour prévenir
Les quatre limites sont inclusives. Un jeton de nom d'exactement 127 octets valide ; 128 non. Un tableau avec exactement 8191 éléments valide ; 8192 non. PDFium Component épingle les deux côtés de chaque frontière dans sa suite de tests pour cette raison, car un décalage d'une unité dans un contrôle de limite produit le pire genre de validateur : un qui rejette des fichiers conformes et auquel on fait confiance quand même
uses FPdfPdfa;
var
Src: TFileStream;
Res: TPdfAValidationResult;
begin
Src := TFileStream.Create('archive.pdf', fmOpenRead or fmShareDenyWrite);
try
Res := ValidatePdfACompliance(Src);
if pvaiArrayOverLimit in Res.Issues then
Memo1.Lines.Add('An array carries more than 8191 elements');
if pvaiDictOverLimit in Res.Issues then
Memo1.Lines.Add('A dictionary carries more than 4095 entries');
if pvaiNestingOverLimit in Res.Issues then
Memo1.Lines.Add('Containers nest deeper than 28 levels');
if pvaiNameOverLimit in Res.Issues then
Memo1.Lines.Add('A name token is longer than 127 bytes');
finally
Src.Free;
end;
end;
Quels générateurs frappent réellement ces limites ?
Ceux qui construisent la structure par programmation, ce qui est la plupart de la sortie métier. Un formulaire avec plusieurs milliers de champs produit un tableau /Annots ou un tableau AcroForm /Fields qui grandit au-delà de 8191. Une page dont le dictionnaire de ressources accumule une entrée par image générée ou instance de police franchit 4095. Les arborescences de structure profondément générées — un document balisé construit par récursion sur un modèle de données imbriqué — dépassent 28 niveaux sans que personne ne le remarque, car personne ne regarde la profondeur d'imbrication
Les noms longs viennent d'une habitude différente : encoder des données dans des jetons de nom. Un nom de colorant construit depuis un identifiant client, un groupe de contenu optionnel nommé d'après un chemin de fichier complet, un champ de formulaire dont le nom pleinement qualifié concatène six niveaux de hiérarchie. Les noms sont bon marché à générer et faciles à rendre longs, et 127 octets disparaissent plus vite que vous ne le penseriez une fois qu'une étiquette encodée en UTF-8 est en jeu
La réparation est structurelle dans chaque cas. Scinder le tableau, scinder le dictionnaire, aplanir l'imbrication, raccourcir le nom — la recommandation de préflight pour chaque question nomme la limite concrète plutôt que de vous dire que le fichier est invalide. L injection de marqueurs ne peut rien ici : ce ne sont pas des réclamations de métadonnées, c'est la forme du graphe d'objets
Pourquoi une police TrueType symbolique ne doit pas porter /Encoding
Parce que ISO 19005-1 §6.3.7 n'admet que le cmap intégré à la police pour les polices TrueType symboliques, et qu'une entrée /Encoding le contredirait. Une police symbolique mappe les codes aux glyphes en ses propres termes — c'est ce que symbolique signifie. Ajoutez une table d'encodage et il y a maintenant deux réponses à la question « quel glyphe l'octet 0x41 sélectionne-t-il », sans règle dans le fichier disant qui l'emporte. Différents lecteurs le résolvent différemment, et un document qui se rend comme texte dans une visionneuse se rend en dingbats dans une autre
PDFium Component lit l'indicateur symbolique depuis le /FontDescriptor, que le descripteur soit écrit en ligne dans le dictionnaire de police ou référencé indirectement. Une police TrueType non symbolique conserve sa /WinAnsiEncoding ou /MacRomanEncoding exigée sans être signalée, car pour les polices non symboliques l'encodage est exactement ce que la norme demande. Le contrôle se déclenche sur la contradiction, pas sur la présence d'un encodage
if pvaiSymbolicTrueTypeEncoding in Res.Issues then
Memo1.Lines.Add(
'A symbolic TrueType font carries /Encoding; PDF/A admits only its ' +
'built-in cmap (ISO 19005-1 6.3.7)');
La source pratique de ce défaut est le sous-ensemble de police fait par un producteur qui traite chaque police TrueType de la même façon. Les polices Symbol, Wingdings, code-barres et icônes sont les porteuses habituelles — exactement les polices qu'un document commercial utilise pour les cases à cocher, logos et code-barres, et exactement celles que personne ne réexamine quand un document échoue à la validation sur « les polices »
Comment les questions arrivent dans un rapport de préflight
Les quatre limites conteneur sont classées sous structure ; la question d'encodage TrueType symbolique est classée sous contenu. Cette séparation compte quand un rapport va à deux personnes différentes : les constats de structure appartiennent habituellement à quiconque a écrit le générateur, et les constats de contenu habituellement à quiconque a fourni les assets
Chaque question porte une recommandation qui nomme le remède en termes concrets — raccourcir les jetons de nom à 127 octets ou moins, scinder les tableaux afin qu'aucun ne porte plus de 8191 éléments, retirer /Encoding des polices TrueType symboliques. Un rapport qui dit « non conforme PDF/A » lance une investigation. Un rapport qui dit quelle limite a été dépassée et par quoi en termine une
Valider sans la DLL, et pourquoi cela compte ici
Tous les contrôles ci-dessus tournent contre les octets du fichier, donc ils fonctionnent dans un service qui n'a aucun binaire PDFium déployé, dans une étape de construction, ou sur une machine où charger une DLL native est un problème de politique. C'est une ligne de design délibérée dans PDFium Component : les contrôles qui peuvent être répondus depuis la structure sont répondus depuis la structure, et la DLL est réservée pour ceux qui ont réellement besoin d'un moteur de rendu
Pour le flux environnant — exécuter la validation sur un dossier, produire des rapports, et décider quoi faire des constats — voir les visites guidées de la validation préflight PDF/A en Delphi et du CLI de rapport préflight par lots. Pour le choix de profil d'archivage qui se trouve au-dessus de tous ces contrôles, les notes sur la conformité d'archivage PDF/A couvrent quelle partie et quel niveau cibler avant que vous commenciez à réparer des constats
PDFium Component enveloppe le moteur PDFium pour Delphi, C++Builder et Lazarus avec une API VCL de haut niveau et un ensemble de validateurs de conformité qui tournent avec ou sans la DLL — voir la page produit PDFium Component pour les normes et plateformes prises en charge