PDF/E-1 je archivační profil pro inženýrské dokumenty a PDFlibPas ho implementuje jako author mode, který zapnete přes SetPDFEMode, plus ohraničený preflight čtoucí content streamy operátor po operátoru. Tenhle profil není PDF/A s jiným štítkem: má vlastní identifikační namespace, vlastní požadavek na lifecycle metadata a jedno pravidlo, které dělá validaci obsahu přísnější než u jakéhokoli archivačního profilu, který jste potkali
Inženýrské výstupy jsou důvod existence toho profilu. Sada výkresů, která musí být za dvacet let čitelná a prokázatelně nezměněná, s historií revizí, která přežije, a s barvami, které znamenají totéž i na plotru v vedlejší budově. Tahle požadavky tvoří specifikaci, jejíž nároky sedí většinou mimo obsah stránek, v metadatech a správě barev, což je přesně tam, kde se generický PDF writer splete
Vlastní identifikace, ne variace na PDF/A
První věcí, kterou je potřeba trefit správně, je to, že identifikaci PDF/E-1 nelze vyrobit úpravou vzoru z PDF/A nebo PDF/X. Používá odlišný XMP namespace, http://www.aim.org/pdfe/ns/id/, a hodnota verze se musí objevit na dvou místech: jako položka document information a jako XMP property kvalifikovaná namespace. Vyslat jen XMP property, nebo jen položku information, produkuje soubor, který sice záměr nese, ale validací neprojde
Output intent má stejně specifickou podobu. PDF/E-1 vyžaduje vložený ICC profil s podtypovým identifikátorem ISO_PDFE1 a profil musí mít počet komponent odpovídající rodině device barev, kterou dokument skutečně používá. Právě ta poslední klauzule je místo, kde se implementace potichu spletou, protože to znamená, že intent nelze vybrat předem a pak ignorovat
Proč potřebuje device barva průchod celým dokumentem?
Protože barevné prostory se schovávají ve slovnících resources, kam sken na úrovni stránky nikdy nedosáhne. PDF/E-1 bere DeviceRGB a DeviceCMYK jako u dokumentu navzájem výlučné rodiny, takže validace profilu znamená znát každou device barevnou prostor, kterou cokoli v souboru používá. Form XObject má vlastní resources. Pattern taky, image taky. Tiling pattern uvnitř form XObjectu uvnitř stránky je tři úrovně hluboko a validátor kontrolující jen resources nejvyšší úrovně stránky pustí dokument používající obě rodiny
Průchod proto registruje barevné prostory při procházení stránek, formulářů, obrázků a patternů jako jediný traversal, a teprve potom rozhodne, zda je dokument koherentní a zda output intent odpovídá. Táž úvaha řídí obecně celou architekturu preflightu: částečný traversal produkuje falešné průchody a falešný průchod u konformační kontroly je horší než žádná kontrola, protože se zaeviduje jako 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');
// Author mode udržuje lifecycle metadata v kroku při každém uložení.
// Před uložením se zeptej, zda by dokument prošel vlastní branou
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;
Lifecycle metadata je povinnost při každém uložení
PDF/E-1 chce víc než identifikátor dokumentu. Minimální sada zahrnuje identifikátor dokumentu media management, identifikátor verze, rendition class, čas vytvoření, čas úpravy, čas metadat a název. To je slovník na sledování revizí a existuje proto, že se od inženýrského výstupu čeká vydávání nových verzí, ne jednorázové napsání
Důsledek pro implementaci je, že tyhle pole nelze nastavit při vytvoření dokumentu. Jestliže se čas úpravy zapíše ve chvíli, kdy zapnete mód, a dokument se potom upraví, XMP snapshot a skutečný stav dokumentu se rozejdou a validátor je porovnávající nahlásí nekonzistenci, kterou nikdo nezamýšlel. Author mode proto synchronizuje pole těsně před každým uložením, takže metadata popisují bajty, které se teprve chystají zapsat, ne bajty, které existovaly, když se mód zapínal
To je obecný princip konformačních metadat a stojí za to ho vyložit zvlášť od PDF/E: odvozená metadata patří na save path, ne na edit path. Jakékoli pole počítané ze stavu dokumentu se musí přepočítat v okamžiku, kdy se stav zmrazí, jinak je to cache bez invalidace
Pravidlo, které dělá validaci obsahu přísnou
PDF/E-1 nedovoluje, aby operátory kompatibilní sekce pohltily neznámý obsah. V obyčejném PDF ohraničují BX a EX region, v němž musí konzument ignorovat operátory, které nepozná, což je escape hatch umožňující produkcentovi vyslat novější konstrukce, aniž rozbije starší čtečky. Pod PDF/E-1 je ta únikovka zavřená, takže každý operátor, který preflight nepozná, se hlásí bezpodmínečně, ať už sedí uvnitř kompatibilní sekce, nebo ne
Na validátor to má výrazný efekt. Nemůže přeskočit regiony, kterým nerozumí, což znamená, že parser operandů musí skutečně sparsovat každý operátor v každém content streamu. Právě tady přicházejí na řadu limity. Traversal je stropovaný na 128 úrovní zanoření, milion objektů a 64 MiB obsahu, a ty limity nejsou ladění výkonu. Nepřátelský, nebo jen rozbitý soubor může předložit graf objektů s cykly nebo zanořením tak hlubokým, že z rekurzivního validátoru udělá stack overflow, a limity jsou to, co brání validačnímu průchodu stát se vektorem denial-of-service. Tentýž defenzivní postoj rozebírá článek bezpečné parsování nedůvěryhodných PDF
// Samostatná validace souboru, který jste nevyrobili, bez načítání
// do instance 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;
Co save brána opraví a co odmítne
Brána dělí svou práci na dvě etapy a tohle rozdělení je samo o sobě použitelný designový nápad. Nejdřív normalizuje věci bezpečně opravitelné: print flagy anotací, flagy no-zoom a no-rotate na textových anotacích a flag generování appearance ve slovníku formuláře. Tohle jsou nastavení s jedinou správnou hodnotou pod profilem a bez obsahu informace, takže jejich tichá oprava je správná a odmítat nad nimi by byla pedantárna
Potom kontroluje omezení, jež nelze opravit, aniž se změní to, co dokument znamená: verzi, identifikaci, šifrování, output intent, koherenci device barev a přítomnost dynamického obsahu formulářů. Dokument, který u jakéhokoli z nich propadne, je odmítnut, protože vymyslet output intent nebo vybrat rodinu barev za autora by vyprodukovalo soubor, který validací projde a obsah deformuje
Přečtení diagnostiky zpět přes GetPDFEDiagnostics před uložením promění tohle odmítnutí v akční seznam místo neúspěšné operace. V batch pipeline ji volejte na každý dokument, logujte blockery per soubor a selhání směrujte do fronty, kterou si člověk projde. To je k užitku mnohem víc než save, který vyhodí výjimku, protože blockery se obvykle shlukují: čtyřicet dokumentů propadajících se stejným chybějícím output intentem je jedna oprava, ne čtyřicet
Volba mezi archivačními profily
PDF/E-1 je správný cíl, když je výstupem inženýrská dokumentace s revizním lifecycle a konkrétně tehdy, když záleží na koherenci device barev, protože výstup jde na plotry a velkoformátové tiskárny. PDF/A je správný cíl, když je cílem dlouhodobá čitelnost dokumentů obecně, a je to profil s nejširší podporou validátorů. Nejsou zaměnitelné a dokument může splnit jeden a propadnout druhém
Když si vybíráte, začněte u toho, kdo soubor na konci cesty validuje. Nástroje na validaci PDF/A jsou všude a odpovídající preflight v PDFlibPas popisuje článek preflight PDF/A a PDF/UA. Validace PDF/E je specializovanější a obvykle jde o smluvní požadavek, ne o výchozí stav. Když musí být stávající archiv dotažen na profil, pro který nikdy nebyl psán, vzorem je cesta opravy metadat v článku konverze na PDF/A s opravou metadat a platí tentýž tvar i tady: identifikuj, oprav, co je bezpečné, zbytek odmítni se seznamem
Author mode, ohraničený preflight obsahu i samostatná compliance kontrola přicházejí s PDFlibPas Delphi PDF knihovnou, takže dokument lze vyrobit pod profilem a následně nezávisle ověřit oddělenou kódovou cestou, což je jediné uspořádání, kterému u konformačního tvrzení stojí za důvěru