Odborný článok

PDF/E-1: inžinierske dokumenty v Delphi s PDFlibPas

PDF/E-1 je archívny profil pre inžinierske dokumenty a PDFlibPas ho implementuje ako autorov režim, ktorý zapnete cez SetPDFEMode, plus ohraničený preflight, ktorý číta content streamy operátor po operátore. Tento profil nie je PDF/A s iným štítkom: má vlastný identifikačný namespace, vlastnú požiadavku na metadáta životného cyklu a jedno pravidlo, ktoré robí validáciu obsahu prísnejšou než v ktoromkoľvek archívnom profile, aký ste doteraz stretli

Inžinierske výstupy sú dôvod, prečo tento profil existuje. Súprava výkresov, ktorá musí byť o dvadsať rokov čitateľná a dokázateľne nezmenená, s históriou revízií, ktorá prežije, a s farbou, ktorá znamená to isté na plotri v inej budove. Tieto požiadavky tvoria špecifikáciu, ktorej nároky ležia väčšinou mimo obsahu strany, v metadátach a správe farieb, a presne tam ich generický PDF writer pokazí

Vlastná identifikácia, nie variácia na PDF/A

Prvá vec, ktorú treba urobiť správne, je uvedomiť si, že identifikáciu PDF/E-1 nemožno vyrobiť úpravou vzoru PDF/A či PDF/X. Používa osobitý XMP namespace, http://www.aim.org/pdfe/ns/id/, a hodnota verzie sa musí objaviť na dvoch miestach: ako položka informácií dokumentu a ako XMP vlastnosť kvalifikovaná namespaceom. Vyprodukovať len XMP vlastnosť alebo len položku informácií znamená vyrobiť súbor, ktorý nesie úmysel a validáciou neprejde

Output intent má rovnako špecifický tvar. PDF/E-1 vyžaduje vložený ICC profil s podtypovým identifikátorom ISO_PDFE1 a profil musí mať počet komponentov sediaci s rodinou device farieb, ktorú dokument skutočne používa. Posledná doložka je miesto, kde implementácie poticho zlyhávajú, lebo znamená, že intent nemožno vybrať dopredu a potom ignorovať

Prečo potrebuje device farba prechod celým dokumentom?

Pretože farebné priestory sa skrývajú v resource slovníkoch, kam sken na úrovni strany nikdy nezabehne. PDF/E-1 berie DeviceRGB a DeviceCMYK ako pre dokument vzájomne sa vylučujúce rodiny, takže validácia profilu znamená poznať každý device farebný priestor, ktorý čokoľvek v súbore používa. Form XObject má vlastné resources. Rovnako pattern a rovnako obrázok. Tiling pattern vo form XObjecte vo vnútri strany je tri úrovne hlboko a validátor, ktorý kontroluje len resources strany najvyššej úrovne, prepustí dokument používajúci obe rodiny

Tento prechod preto registruje farebné priestory pri jedinom prechode cez strany, formy, obrázky a patterny a až potom rozhodne, či je dokument koherentný a či output intent sedí. Rovnaké uvažovanie poháňa aj architektúru preflightu celkovo: čiastočný prechod produkuje falošné úspechy a falošný úspech pri kontrole zhody je horší než žiadna kontrola, pretože sa zaznamená ako dôkaz

var
  Lib: TPDFlib;
  Diag: WideString;
begin
  Lib := TPDFlib.Create(nil);
  try
    Lib.LoadFromFile('assembly-drawings.pdf');

    if Lib.SetPDFEMode(1) = 0 then
      raise Exception.Create('PDF/E author mode was refused');

    // Autorov režim drží metadáta životného cyklu v kroku pri každom uložení.
    // Pred uložením sa opýtajte, či by dokument prešiel vlastnou bránou
    if not Lib.PDFEReadyForSave then
    begin
      Diag := Lib.GetPDFEDiagnostics;
      Writeln('PDF/E blockers: ', Diag);
      Exit;
    end;

    Lib.SaveToFile('assembly-drawings-pdfe.pdf');
  finally
    Lib.Free;
  end;
end;

Metadáta životného cyklu sú povinnosť pri každom uložení

PDF/E-1 chce viac než identifikátor dokumentu. Minimálna sada zahŕňa identifikátor dokumentu media management, identifikátor verzie, rendition class, čas vytvorenia, čas zmeny, čas metadát a názov. To je slovník na sledovanie revízií a existuje preto, že sa od inžinierskeho výstupu očakáva vydávanie nových verzií, nie jednorazové napísanie

Dôsledok pre implementáciu je ten, že tieto polia nemožno nastaviť pri vytvorení dokumentu. Ak sa čas zmeny zapíše v momente, keď zapnete režim, a dokument sa potom ešte edituje, XMP snapshot a skutočný stav dokumentu sa rozídu a validátor ich porovnávajúci nahlási nekonzistenciu, ktorú nikto nezamýšľal. Autorov režim preto synchronizuje polia tesne pred každým uložením, takže metadáta opisujú bajty, ktoré sa chystajú zapísať, nie bajty, ktoré existovali v momente zapnutia režimu

To je všeobecný princíp pre metadáta zhody a stojí za to ho vysloviť oddelene od PDF/E: odvodené metadáta patria na cestu ukladania, nie na cestu editovania. Každé pole počítané zo stavu dokumentu sa musí prepočítať v momente, keď sa stav zamrazí, inak je to cache bez invalidácie

Diagram PDFlibPas PDF/E-1 prechodu device farieb celým dokumentom, ktorý obchádza resource slovníky strán, form XObjectov, tiling patternov a obrázkov a zbiera rodiny DeviceRGB a DeviceCMYK pred posúdením koherentnosti, vedľa polí metadát životného cyklu, ktoré autorov režim resynchronizuje tesne pred každým uložením, aby XMP snapshot sedel s bajtmi, ktoré sa chystajú na zápis
Farebnú koherentnosť možno posúdiť až po jednom prechode, ktorý zachytí každý resource slovník, a odvodené metadáta životného cyklu sa prepočítavajú v momente zamrazenia stavu dokumentu, nie pri zapnutí režimu

Pravidlo, ktoré robí validáciu obsahu prísnou

PDF/E-1 nedovoľuje operátorom kompatibilnej sekcie pohltiť neznámy obsah. V bežnom PDF ohraničujú BX a EX oblasť, v ktorej musí konzument ignorovať operátory, ktoré nepozná, a to je únikový východ vďaka ktorému môže producent vypúšťať novšie konštrukty bez rozbitia starších čítačiek. Pod PDF/E-1 je tento východ zatvorený, takže akýkoľvek operátor, ktorý preflight nepozná, sa hlási bezpodmienečne, či už sedí v kompatibilnej sekcii alebo nie

Dôsledok pre validátor je značný. Nemôže preskočiť oblasti, ktorým nerozumie, čo znamená, že parser operandov musí naozaj preanalyzovať každý operátor v každom content streame. Presne tu nastupujú hranice. Prechod má strop 128 úrovní vnorenia, milión objektov a 64 MiB obsahu a tieto limity nie sú ladenie výkonu. Nepriateľský alebo len poškodený súbor môže predložiť graf objektov s cyklami alebo hĺbkou vnorenia, ktorá z rekurzívneho validátora spraví stack overflow, a limity sú to, čo bráni tomu, aby sa validačný prechod nestal denial-of-service vektorom. Rovnaký defenzívny postoj popisuje článok bezpečné parsovanie nedôveryhodných PDF

// Samostatná validácia súboru, ktorý ste nevyprodukovali, bez načítania
// do inštancie dokumentu
var
  Issues: TStringList;
  Stream: TFileStream;
  I: Integer;
begin
  Issues := TStringList.Create;
  Stream := TFileStream.Create('incoming.pdf', fmOpenRead or fmShareDenyWrite);
  try
    if CheckCompliancePDFE(Stream, '', 0, Issues) = 0 then
      for I := 0 to Issues.Count - 1 do
        Writeln('PDF/E: ', Issues[I]);
  finally
    Stream.Free;
    Issues.Free;
  end;
end;

Čo brána pri ukladaní opraví a čo odmietne

Brána delí svoju prácu na dve etapy a toto delenie je samo osebe použiteľný návrhový nápad. Najprv normalizuje veci, ktoré sa dajú bezpečne opraviť: tlačové príznaky anotácií, príznaky no-zoom a no-rotate na textových anotáciách a príznak generovania podoby vo slovníku formulára. Sú to nastavenia s jedinou správnou hodnotou podľa profilu a bez informačného obsahu, takže ich tichá oprava je správna a odmietanie nad nimi by bolo pedantstvo

Potom skontroluje obmedzenia, ktoré sa nedajú opraviť bez zmeny významu dokumentu: verziu, identifikáciu, šifrovanie, output intent, koherentnosť device farieb a prítomnosť dynamického obsahu formulárov. Dokument zlyhajúci na ktoromkoľvek z nich sa odmietne, pretože vymyslieť output intent alebo vybrať farebnú rodinu za autora by vyrobilo súbor, ktorý validáciou prejde a obsah nesprávne reprezentuje

Diagram brány pri ukladaní PDF/E-1 v PDFlibPas pre Delphi ukazujúci ohraničený preflight, ktorý skenuje každý operátor content streamov pod stropmi 128 úrovní vnorenia, milióna objektov a 64 MiB, ticho opraví tlačové, zoom a rotate príznaky anotácií, odmietne nesprávnu verziu, identifikáciu, šifrovanie, output intent, device farby alebo dynamický obsah formulárov a hlási blokery cez GetPDFEDiagnostics
Brána ticho opravuje len to, čo nesie žiadnu informáciu, odmieta každé obmedzenie, ktoré by oprava skreslila, a mení odmietnutie na zoznam blokerov cez GetPDFEDiagnostics skôr, než sa jediný bajt dostane na disk

Prečítanie diagnostiky cez GetPDFEDiagnostics pred uložením mení to odmietnutie na list akcií, nie na zlyhanú operáciu. V dávkovom pipeline volajte ho na každom dokumente, logujte blokery po súboroch a smerujte zlyhania do fronty, ktorú pozerá človek. To je oveľa užitočnejšie než uloženie, ktoré hodí výnimku, pretože blokery sa zvyčajne zhlukujú: štyridsať dokumentov zlyhávajúcich na tom istom chýbajúcom output intenti je jedna oprava, nie štyridsať

Voľba medzi archívnymi profilmi

PDF/E-1 je správny cieľ, keď výstupom je inžinierska dokumentácia s revíznym životným cyklom, a hlavne vtedy, keď záleží na koherentnosti device farieb, pretože výstup ide na plotre a veľkoformátové tlačiarne. PDF/A je správny cieľ, keď je cieľom dlhodobá čitateľnosť dokumentov všeobecne, a je to profil s najširšou podporou validátorov. Tieto dva nie sú zameniteľné a dokument môže uspokojiť jeden a zlyhať na druhom

Rozhodovací diagram PDFlibPas porovnávajúci archívne profily PDF/E-1 a PDF/A pre Delphi: PDF/E-1 pre inžinierske výstupy s revíznym životným cyklom, farbou na plotre a zmluvnou validáciou vo vlastnom XMP namespaceu s output intentom ISO_PDFE1, PDF/A pre všeobecnú dlhodobú čitateľnosť s najširšou podporou validátorov
Začnite od toho, kto súbor validuje na druhom konci: profily vyžadujú odlišnú identifikáciu, metadáta a farebné garancie a dokument môže uspokojiť jeden profil a zlyhať na druhom

Ak si vyberáte, začnite od toho, kto súbor validuje na druhom konci. Nástroje na validáciu PDF/A sú všade a zodpovedajúci preflight v PDFlibPas popisuje článok preflight PDF/A a PDF/UA. Validácia PDF/E je špecializovanejšia a zvyčajne je zmluvnou požiadavkou, nie predvoleným nastavením. Keď musí existujúci archív dotiahnuť na profil, pre ktorý nebol nikdy písaný, cesta opravy metadát v článku konverzia na PDF/A s opravou metadát je vzor, ktorý treba nasledovať, a rovnaký tvar platí aj tu: identifikovať, opraviť to, čo je bezpečné, odmietnuť zvyšok so zoznamom

Autorov režim, ohraničený preflight obsahu aj samostatná kontrola zhody prichádzajú s PDFlibPas Delphi PDF knižnicou, takže dokument možno vyrobiť pod profilom a následne nezávisle overiť cez oddelenú kódovú cestu, a to je jediné usporiadanie, ktorému sa pri tvrdení o zhode dá veriť