Une archive gouvernementale a un jour rejeté tout un dépôt de 1 400 factures générées par le système de facturation Delphi d'un client. Chaque fichier s'ouvrait parfaitement dans tous les lecteurs testés par le client ; veraPDF les rejetait tous pour une seule raison identique : un OutputIntent manquant. Cet incident résume la leçon centrale du travail PDF conforme aux standards : la justesse visuelle ne prouve rien, car PDF/A, PDF/X et PDF/UA contraignent la structure interne du fichier, pas son apparence. HotPDF, bibliothèque PDF VCL native de losLab, intègre ces contraintes dans la génération afin que la conformité soit configurée avant l'existence de la première page plutôt que réparée après coup.
Trois standards ISO, trois promesses différentes
PDF/A (ISO 19005) promet qu'un fichier se rendra encore de façon identique dans des décennies, d'où son exigence d'auto-contenance complète : toutes les polices intégrées, chaque couleur indépendante du périphérique via un OutputIntent, métadonnées XMP complètes, et interdiction de tout ce dont le comportement dépend de l'environnement, y compris chiffrement et JavaScript. PDF/X (ISO 15930) promet un échange aveugle entre un designer et un imprimeur ; ses règles concernent donc la couleur et la géométrie : conditions d'impression caractérisées, clé /Trapped obligatoire, géométries trim et bleed définies, et dans la variante X-1a aucune transparence active. PDF/UA (ISO 14289) promet que les technologies d'assistance peuvent lire le document, ce qui en fait une exigence sur la structure logique : arbre de balises complet, ordre de lecture correct, langue du document déclarée et alternatives textuelles pour les contenus non textuels.
Ces promesses tirent dans des directions différentes. Un formulaire interactif convient à PDF/UA et se combine impossible avec les restrictions dynamiques du profil d'archivage ; un master d'impression exclusivement CMYK est précisément mauvais pour des utilisateurs de lecteurs d'écran qui ne voient jamais la couleur. Décidez par canal de sortie quel standard gouverne, au lieu de poursuivre un fichier unique censé tout satisfaire.
PDF/A dans HotPDF : l'OutputIntent est le cœur du sujet
Le rejet d'archive ci-dessus tenait à une structure manquante, celle que les générateurs oublient le plus souvent parce que rien de visible n'en dépend. ISO 19005 exige un OutputIntent : un profil ICC intégré qui donne aux couleurs de périphérique un sens non ambigu. HotPDF en fait une entrée explicite :
var
Pdf: THotPDF;
ICC: TFileStream;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'invoice-archival.pdf';
Pdf.PDFACompliance := 'B'; // level B: visual fidelity
Pdf.Lang := 'en-US';
Pdf.StandardFontEmulation := False; // embed real fonts, no Base-14 emulation
ICC := TFileStream.Create('sRGB.icc', fmOpenRead);
try
Pdf.AddPDFAOutputIntent('sRGB IEC61966-2.1', '', ICC, 3, 'DeviceRGB');
finally
ICC.Free;
end;
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(50, 760, 0, 'Archival invoice body');
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Trois détails de configuration décident du succès ou de l'échec. StandardFontEmulation doit être désactivé, car les polices Base-14 émulées ne sont par définition pas intégrées, et l'intégration est non négociable sous ISO 19005. Le chiffrement doit rester désactivé ; ne combinez pas PDFACompliance avec ActivateProtection, car un fichier d'archive chiffré est une contradiction que le validateur détectera. Enfin, le nombre de composants passé à AddPDFAOutputIntent doit correspondre au profil : 3 pour un profil RGB comme sRGB IEC61966-2.1. HotPDF suit l'usage DeviceRGB et DeviceCMYK pendant la génération par rapport à l'intention déclarée ; un remplissage CMYK dans un document à intention RGB devient donc un problème de validation plutôt qu'une incohérence silencieuse.
Traitez le profil ICC lui-même comme un artefact de déploiement versionné, pas comme un fichier que quelqu'un a copié un jour sur le serveur de build. Les octets du profil sont intégrés à chaque document généré ; un profil corrompu ou tronqué contamine donc tout un lot à la fois, et l'échec n'apparaît qu'à la validation. Livrez le profil avec votre installateur, consignez son checksum dans le log d'exécution, et chargez-le par le modèle TFileStream ci-dessus afin qu'un fichier manquant échoue bruyamment à la génération plutôt que silencieusement à la porte de l'archive.
PDF/X pour l'impression : Trapped, CMYK et profil de presse
Les masters d'impression inversent l'histoire des couleurs : la presse veut du CMYK caractérisé, et le standard exige que vous indiquiez si le trapping a été appliqué. La clé /Trapped est obligatoire même lorsque la réponse honnête est que vous ne savez pas :
Pdf.PDFXCompliance := 'X-1a';
Pdf.Trapped := 'Unknown'; // mandatory key under ISO 15930
ICC := TFileStream.Create('FOGRA39.icc', fmOpenRead);
try
Pdf.AddPDFXOutputIntent('FOGRA39 (ISO 12647-2:2004)', '', ICC, 4, 'DeviceCMYK');
finally
ICC.Free;
end;
Pdf.BeginDoc;
// draw with CMYK-safe colors, no transparency, no encryption
Pdf.EndDoc;
Notez que le nombre de composants passe à 4 pour le profil de presse CMYK. X-1a exclut en outre la transparence active ; revoyez donc tout code de dessin qui superpose des éléments translucides, car ce qu'un lecteur composite à l'écran est précisément ce qu'un RIP refuse de deviner. Si votre imprimeur vous fournit une autre caractérisation, remplacez le profil et l'identifiant mais conservez la structure identique.
PDF/UA : la structure se génère, elle ne se greffe pas
L'accessibilité est le standard que les équipes tentent le plus souvent d'ajouter à la fin, et celui où le rétrofit échoue le plus durement, car l'arbre de balises doit refléter l'ordre logique dans lequel le contenu a été créé. Dans HotPDF, définir PDFUACompliance active la sortie balisée, et l'API de structure relie chaque appel de dessin à son rôle sémantique :
Pdf.PDFUACompliance := True; // auto-enables tagged PDF
Pdf.Lang := 'en-US'; // set explicitly; empty falls back to 'en'
Pdf.BeginDoc;
Root := Pdf.AddStructureElement(sstDocument, nil);
H1 := Pdf.EmitTaggedHeading(1, Root, 50, 700, 'Quarterly Report');
Para := Pdf.BeginTaggedContent('P', Root);
Pdf.CurrentPage.TextOut(50, 650, 0, 'Revenue grew in all regions.');
Pdf.EndTaggedContent;
Pdf.EndDoc;
Le motif d'erreur à surveiller est le contenu dessiné hors de toute paire BeginTaggedContent/EndTaggedContent : il se rend normalement et reste invisible à un lecteur d'écran, le pire type d'échec car aucun testeur voyant ne le remarquera. Si vos modèles utilisent des noms de rôles de structure personnalisés, mappez-les sur l'ensemble standard avec AddStructRoleMap('MyHead', 'H1') afin que les lecteurs conformes sachent les interpréter. ISO 14289 exige aussi une langue déclarée ; HotPDF substitue 'en' lorsque Lang est vide, filet de sécurité et non excuse pour ne pas définir la vraie langue du document.
Vérification : faites confiance au validateur, pas au lecteur
L'histoire des factures a une morale simple : intégrez la vérification au chemin de publication avec des outils qui contrôlent la structure, pas le rendu. Pour les revendications PDF/A et PDF/UA, veraPDF est le validateur ouvert de référence : il signale les échecs par clause ISO, rendant sa sortie directement exploitable par rapport à la configuration ci-dessus. Pour PDF/X, les profils Preflight d'Adobe Acrobat restent le contrôle pratique, car les conditions de presse relèvent autant de l'intention couleur que de la syntaxe. Dans le générateur, HotPDF réconcilie les flags de fonctions avec la version PDF configurée au moment de l'enregistrement, en dégradant silencieusement ce que la version ne peut pas exprimer, par exemple AES-256 sous PDF 1.7, tandis que les portes de conformité dans EndDoc lèvent franchement sur les contradictions dures comme PDFACompliance avec chiffrement. Aucun contrôle ne remplace le validateur externe ; ensemble, ils empêchent les configurations impossibles de l'atteindre.
Versionnez toute la configuration de conformité ensemble : version HotPDF, révision du modèle, checksum du profil ICC et version du validateur qui a validé. La conformité dérive quand l'un d'eux change sous les autres, et les audits les plus douloureux que nous ayons vus sont ceux où personne ne pouvait dire quelle combinaison avait produit un fichier d'archive vieux de cinq ans. Un enregistrement de configuration par lot ferme définitivement cette question.
Exécutez le validateur sur une sortie de production réelle, pas sur un échantillon construit à la main. Les échecs importants viennent des données : un logo client qui arrive en CMYK alors que l'intention dit RGB, une révision de modèle qui introduit une police non intégrée, un nouveau chemin de code qui dessine du texte non balisé. Gardez un fichier connu en échec pour chaque incident passé comme entrée de régression, et votre porte de conformité reste honnête. Pour le côté rendu de ces pipelines, voyez notre article sur la sortie de rapports, les polices et les images avec HotPDF, et pour câbler les validateurs dans un build, l'article compagnon sur l'automatisation des contrôles preflight PDF.
FAQ
Un PDF peut-il être conforme PDF/A et PDF/X en même temps ?
Parfois, mais le jeu de contraintes en vaut rarement la peine : le profil d'archivage veut une couleur indépendante du périphérique et des métadonnées complètes ; le profil d'impression veut du CMYK caractérisé et des déclarations de trapping. Générez par canal depuis les mêmes données source au lieu de forcer un fichier à servir les deux.
Pourquoi veraPDF rejette-t-il un fichier qui s'ouvre parfaitement partout ?
Les lecteurs sont volontairement tolérants ; les validateurs sont volontairement stricts. OutputIntents manquants, polices non intégrées et métadonnées XMP absentes n'affectent jamais le rendu ; seul un validateur structurel les signalera.
Les factures doivent-elles utiliser PDF/A niveau A ou niveau B ?
Le niveau B garantit la reproduction visuelle et correspond à ce que la plupart des archives demandent pour les documents métier numérisés ou générés. Le niveau A ajoute les exigences de structure balisée, ramenant en pratique la charge PDF/UA ; c'est le bon choix lorsque les obligations d'accessibilité s'appliquent à l'archive elle-même.
Pour aller plus loin
Les propriétés de conformité, output intents et API de balisage de cet article font partie du HotPDF Component pour Delphi et C++Builder ; la page produit renvoie à la référence complète de chaque appel utilisé ici.