Technický článek

Výstup PDF/A, PDF/X a PDF/UA v Delphi: Průvodce HotPDF

PDF/A, PDF/X a PDF/UA jsou tři odlišné standardy řešící tři odlišné problémy: dlouhodobou archivaci, výměnu pro tisk a přístupnost. Nejsou to tři zaškrtávací políčka na jednom formuláři shody, a nejčastější chyba je zacházet s nimi, jako by byly. Soubor může být bezchybný PDF/A a k ničemu pro tiskárnu; dokonalý tiskový master může být nečitelný pro čtečku obrazovky. Ještě horší je, že všechny tři jsou omezení vnitřní struktury souboru, ne toho, jak vypadá. Dokument, který se čistě otevře v každém prohlížeči, který máte, může přesto na první pokus neprojít validací, a obvykle to tak i dopadne

HotPDF, nativní VCL knihovna pro PDF od losLab, zachází se shodou jako s něčím, co deklarujete dřív, než existuje první stránka. Nastavíte vlastnost shody, připojíte struktury, které standard vyžaduje, a knihovna při ukládání odmítá konfigurace, které profilu odporují. To je lepší model, než soubor vygenerovat a doufat, že to post-processor dodatečně dorovná, protože většinu toho, co tyto standardy vyžadují, nelze přidat dodatečně

Tři standardy ISO, tři odlišné sliby

PDF/A (ISO 19005) je o čase. Slibuje, že se soubor bude vykreslovat identicky i o desetiletí později, takže vyžaduje úplnou soběstačnost: každý font vložený, každá barva se zařízení nezávislým významem přes OutputIntent, kompletní metadata XMP a zákaz čehokoli, jehož chování závisí na prostředí. Šifrování a JavaScript jsou mimo hru, protože nikdo nemůže zaručit, že dešifrovací nástroj nebo skriptovací engine budou existovat v roce 2050

PDF/X (ISO 15930) je o barvě na papíře. Existuje proto, aby designér mohl předat soubor tiskárně, aniž by o tom kdokoli z nich musel diskutovat, což znamená charakterizované tiskové podmínky, povinný klíč /Trapped, definovanou geometrii ořezu a spadávky, a ve variantě X-1a žádnou živou průhlednost, u které by RIP musel hádat. PDF/UA (ISO 14289) je o tom, kdo si výsledek dokáže přečíst. Asistivní technologie potřebuje kompletní strom tagů, rozumné pořadí čtení, deklarovaný jazyk dokumentu a textové alternativy pro cokoli, co není text

Protože všechny tři táhnou různým směrem, volte řídicí standard podle výstupního kanálu, místo abyste honili jeden soubor, který uspokojí všechny tři. Tiskový master jen v CMYK je přesně to špatné, co předat uživateli čtečky obrazovky, který barvu nikdy nevidí, a uzamčení dynamického chování archivního profilu se sráží s čímkoli interaktivním. Generujte podle kanálu ze stejných zdrojových dat a celému konfliktu se vyhnete

HotPDF generuje soubory PDF/A, PDF/X a PDF/UA na výstupní kanál z jednoho zdrojového dokumentu v Delphi, každý ISO standard drží jiný strukturální slib
PDF/A, PDF/X a PDF/UA tahají každé jiným směrem, takže HotPDF generuje z téhož zdroje jeden soubor na výstupní kanál

PDF/A: OutputIntent je ta část, na kterou všichni zapomínají

Pokud soubor PDF/A neprojde validací, OutputIntent je první věc ke kontrole. Je to struktura, kterou generátory přeskakují nejčastěji, právě proto, že na ní nic viditelného nezávisí. ISO 19005 jeden vyžaduje: vložený profil ICC, který přesně určuje, co barvy zařízení v dokumentu vlastně znamenají. HotPDF z tohoto profilu dělá explicitní vstup, ne dodatečný nápad:

var
  Pdf: THotPDF;
  ICC: TFileStream;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := 'invoice-archival.pdf';
    Pdf.PDFACompliance := 'B';            // úroveň B: vizuální věrnost
    Pdf.Lang := 'en-US';
    Pdf.StandardFontEmulation := False;   // vloží skutečné fonty, žádná emulace Base-14
    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;

Pár detailů tady rozhoduje mezi úspěchem a selháním. StandardFontEmulation musí být vypnuté: emulované fonty Base-14 se nevkládají a vkládání je podle ISO 19005 nesmlouvavé. Šifrování musí zůstat vypnuté, takže nikdy nekombinujte PDFACompliance s ActivateProtection; šifrovaný archivní soubor je rozpor, který validátor okamžitě odhalí. Počet komponent v AddPDFAOutputIntent musí odpovídat profilu, což je 3 pro RGB profil jako sRGB IEC61966-2.1 a 4 pro CMYK. HotPDF při zápisu sleduje použití DeviceRGB a DeviceCMYK proti deklarovanému záměru, takže zbloudilá výplň CMYK v dokumentu se záměrem RGB se promění v nahlášený problém místo tichého

Jedna věc, kterou stojí za to říct o profilu ICC: zacházejte s ním jako s verzovaným nasazovaným artefaktem, ne jako se souborem, který někdo kdysi hodil na build server. Jeho bajty jsou vložené do každého dokumentu, který vygenerujete, takže useknutý nebo poškozený profil potichu otráví celou dávku, a zjistíte to až ve chvíli validace. Dodávejte jej se svým instalátorem, zaznamenávejte jeho kontrolní součet do protokolu běhu a načítejte jej přes vzor TFileStream ukázaný výše, aby chybějící soubor hlasitě selhal už při generování, ne tiše až u archivní brány

PDF/X pro tisk: Trapped, CMYK a tiskový profil

Tiskové mastery obrací příběh barev naruby. Tiskárna chce charakterizované CMYK a standard vás nutí uvést, zda byl aplikován trapping, i když čestná odpověď je, že to nevíte. Klíč /Trapped je povinný bez ohledu na to:

Pdf.PDFXCompliance := 'X-1a';
Pdf.Trapped := 'Unknown';        // povinný klíč podle 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;
// kreslete barvami bezpečnými pro CMYK, bez průhlednosti, bez šifrování
Pdf.EndDoc;

Počet komponent je teď 4 pro tiskový profil CMYK. X-1a navíc zakazuje živou průhlednost, takže proaudujte jakýkoli kreslicí kód, který vrství průsvitné prvky; cokoli prohlížeč na obrazovce zkompozituje, je přesně to, co RIP odmítne interpretovat. Když vám tiskárna pošle jinou charakterizaci, vyměňte bajty profilu a řetězec identifikátoru, ale okolní strukturu nechte na pokoji

PDF/UA: struktura se generuje, nikdy se nedodává dodatečně

Přístupnost je standard, který se týmy nejčastěji snaží přišroubovat na konec, a tento přístup trestá tvrději než u druhých dvou. Strom tagů musí zrcadlit pořadí, ve kterém byl obsah logicky vytvořen, což je informace, kterou už jednoduše nemáte ve chvíli, kdy je soubor zapsaný. Nastavení PDFUACompliance zapne otagovaný výstup a strukturní API za chodu naváže každé kreslicí volání na jeho sémantickou roli:

HotPDF staví strom tagů PDF/UA živě, jakmile se každé kreslicí volání Delphi provede, a text vydaný mimo BeginTaggedContent a EndTaggedContent zůstává neviditelný pro čtečky obrazovky
Strom tagů se zapisuje během kreslení a text mimo tagovaný pár se vykreslí hezky, ale zůstává neviditelný pro čtečky obrazovky
Pdf.PDFUACompliance := True;     // automaticky zapne tagged PDF
Pdf.Lang := 'en-US';             // nastavte explicitně; prázdné spadne zpět na '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;

Selhání, na které si dát pozor, je text nakreslený mimo jakoukoli dvojici BeginTaggedContent/EndTaggedContent. Vykreslí se bezchybně a zůstane neviditelný pro čtečku obrazovky, takže to žádný vidící testér nikdy neodhalí; chyba se dostane do produkce a vyplave až ve chvíli, kdy na mezeru narazí skutečný uživatel asistivní technologie. Když vaše šablony nesou vlastní názvy strukturních rolí, namapujte je na standardní sadu přes AddStructRoleMap('MyHead', 'H1'), aby konformní čtečky věděly, co znamenají. ISO 14289 také vyžaduje deklarovaný jazyk. HotPDF spadne zpět na 'en', když je Lang prázdné, ale to je záchranná síť, ne důvod nechat skutečný jazyk dokumentu nenastavený

Ověření: důvěřujte validátoru, ne prohlížeči

Prohlížeč, který váš soubor otevře, nedokazuje o shodě vůbec nic, takže ověřování patří do release cesty s nástroji, které kontrolují strukturu, ne vykreslování. Pro PDF/A a PDF/UA je veraPDF referenčně kvalitní otevřený validátor; hlásí selhání podle klauzule ISO, což se dá přímo namapovat zpět na konfiguraci výše. Pro PDF/X jsou stále praktickou kontrolou profily Preflight v Adobe Acrobatu, protože shoda pro tisk je stejně tak o barevném záměru jako o syntaxi

Generátor odvádí svou vlastní část této práce. Při ukládání HotPDF sladí příznaky funkcí s nakonfigurovanou verzí PDF a potichu sníží úroveň toho, co daná verze nedokáže vyjádřit, například AES-256 spadne na AES-128 pod PDF 1.7. Brány shody v EndDoc jdou dál a rovnou vyhodí výjimku u tvrdých rozporů, jako je požadavek na PDFACompliance spolu se šifrováním. Ani jedno z toho nenahrazuje externí validátor. Jen zabraňují tomu, aby se k němu nemožné konfigurace vůbec kdy dostaly

Brány souladu HotPDF v EndDoc chytí nemožné konfigurace, než veraPDF validuje PDF/A a PDF/UA a Acrobat Preflight validuje PDF/X v release cestě Delphi
HotPDF odmítá rozporné konfigurace u EndDoc a skutečnou shodu rozhodují nezávislé validátory

Jeden návyk se vyplácí opakovaně: verzujte celé nastavení shody jako jeden celek. Vydání HotPDF, revizi šablony, kontrolní součet profilu ICC, build validátoru, který dal razítko. Shoda se rozjíždí ve chvíli, kdy se pod ostatními změní byť jen jedna z těchto věcí, a nejošklivější audity jsou ty, kde nikdo nedokáže rekonstruovat, jaká kombinace vyprodukovala pětiletý archivní soubor. Jeden konfigurační záznam na dávku to vyřeší jednou provždy

Nakonec spouštějte validátor na skutečném produkčním výstupu, nikdy na úhledném ručně sestaveném vzorku. Selhání, která nejvíc bolí, pocházejí z dat, která nikdo nečekal: zákaznické logo, které přijde jako CMYK, zatímco záměr říká RGB, úprava šablony, do které se vloudí nevložený font, nová cesta kódu, která kreslí text mimo strom tagů. Uchovávejte po jednom známě vadném souboru z každého minulého incidentu jako regresní vstup a brána shody zůstane poctivá i s odstupem času. Pro vykreslovací stranu těchto pipeline viz náš článek o výstupu reportů, fontech a obrázcích v HotPDF; pro zapojení validátorů do buildu je tu doprovodný text o automatizaci kontrol PDF preflight

Vlastnosti shody, output intenty a tagovací API použité v těchto příkladech jsou součástí HotPDF Delphi Component pro Delphi a C++Builder; produktová stránka odkazuje na úplnou referenci pro každé zde ukázané volání