PDF/E-1 er arkiveringsprofilen til ingeniørdokumenter, og PDFlibPas implementerer den som en author mode, du slår til med SetPDFEMode, plus en bounded preflight, der læser content streams operator for operator. Profilen er ikke PDF/A med en anden etiket: den har sin egen identification namespace, sit eget lifecycle-metadatakrav og én regel, der gør indholdsvalidering strengere end nogen arkiveringsprofil, du har mødt
Ingeniørmæssige deliverables er grunden til, at profilen findes. Et tegningssæt, der skal være læsbart og bevist uændret tyve år fra nu, med en revisionshistorik, der overlever, og med farver, der betyder det samme på plotteren i den anden bygning. De krav producerer en specifikation, hvis forventninger for størstedelens vedkommende ligger uden for sideindholdet, i metadata og farvestyring, hvilket netop er der, hvor en generisk PDF-writer tager fejl
Egen identification, ikke en variation over PDF/A
Det første, der skal sidde rigtigt, er, at PDF/E-1-identification ikke kan produceres ved at tilpasse PDF/A- eller PDF/X-mønsteret. Den bruger en distinkt XMP namespace, http://www.aim.org/pdfe/ns/id/, og versionsværdien skal optræde to steder: som document information entry og som den namespace-kvalificerede XMP-egenskab. At skrive kun XMP-egenskaben ud, eller kun information entry, giver en fil, der bærer intentionen og fejler ved validering
Output intent har en tilsvarende specifik form. PDF/E-1 kræver en indlejret ICC-profil med subtype-identifikatoren ISO_PDFE1, og profilen skal have et komponentantal, der matcher den device color-familie, dokumentet faktisk bruger. Sidstnævnte klausul er det sted, hvor implementationer lydløst tager fejl, for det betyder, at intent'en ikke kan vælges på forhånd og derefter ignoreres
Hvorfor kræver device color en gennemgang af hele dokumentet?
Fordi color spaces gemmer sig i resource dictionaries, som en scanning på sideniveau aldrig når. PDF/E-1 behandler DeviceRGB og DeviceCMYK som gensidigt udelukkende familier for et dokument, så at validere profilen betyder at kende hver eneste device color space, hvad som helst i filen bruger. En form XObject har sine egne resources. Det har et pattern også, og det har et image også. Et tiling pattern inde i en form XObject inde i en side ligger tre niveauer nede, og en validator, der kun tjekker de top-level page resources, vil godkende et dokument, der bruger begge familier
Gennemgangen registrerer derfor color spaces, mens den vandrer gennem pages, forms, images og patterns som én traversal, og først derefter afgør den, om dokumentet er sammenhængende, og om output intent matcher. Samme ræsonnement driver preflight-arkitekturen generelt: delvis traversal producerer false passes, og et false pass på et conformance-tjek er værre end intet tjek, for det registreres som bevis
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 holder lifecycle-metadataen synkroniseret ved hver save.
// Spørg før gemning, om dokumentet ville bestå sin egen gate
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 er en forpligtelse pr. save
PDF/E-1 beder om mere end en dokumentidentifikator. Minimumssættet omfatter media management document identifier, en version identifier, en rendition class, creation time, modification time, metadata time og en title. Det er et ordforråd til revisionsporing, og det findes, fordi en ingeniørmæssig deliverable forventes at blive genudgivet snarere end skrevet én gang
Konsekvensen for en implementation er, at disse felter ikke kan sættes ved dokumentoprettelse. Bliver modification time skrevet, når du slår moden til, og dokumentet redigeres bagefter, er XMP-snapshot og den faktiske dokumenttilstand drevet fra hinanden, og en validator, der sammenligner dem, melder en inkonsistens, ingen havde tænkt sig. Author mode synkroniserer derfor felterne umiddelbart før hver save, så metadataen beskriver de byte, der er ved at blive skrevet, snarere end de byte, der eksisterede, da author mode blev slået til
Det er et generelt princip for conformance-metadata, og det er værd at sige separat fra PDF/E: afledt metadata hører hjemme på save-stien, ikke edit-stien. Ethvert felt beregnet ud fra dokumenttilstand skal recomputeres i det øjeblik, tilstanden fastfryses, ellers er det en cache uden invalidation
Reglen, der gør indholdsvalidering streng
PDF/E-1 tillader ikke, at compatibility section-operatorerne absorberer ukendt indhold. I almindelig PDF indrammer BX og EX en region, hvor en consumer skal ignorere operatorer, den ikke genkender, hvilket er nødudgangen, der lader en producer skrive nyere konstruktioner ud uden at bryde ældre readers. Under PDF/E-1 er den flugt lukket, så enhver operator, preflighten ikke genkender, meldes ubetinget, uanset om den ligger inde i en compatibility section
Effekten på en validator er betydelig. Den kan ikke skippe regioner, den ikke forstår, hvilket betyder, at operand-parseren faktisk skal parse hver operator i hver content stream. Det er der, grænserne kommer ind. Traversal er cappet ved 128 niveauer af nesting, en million objekter og 64 MiB indhold, og de grænser er ikke performance-tuning. En fjendtlig eller blot ødelagt fil kan præsentere en objektgraf med cykler eller en nesting-dybde, der forvandler en rekursiv validator til en stack overflow, og grænserne er det, der forhindrer et valideringspass i at blive en denial-of-service-vektor. Den samme defensive holdning er beskrevet i sikker parsing af upålidelige PDF-filer
// Selvstændig validering af en fil, du ikke selv har produceret,
// uden at indlæse den i en dokumentinstans
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;
Hvad save-gaten reparerer, og hvad den nægter
Gaten deler sit arbejde i to stadier, og opdelingen er en brugbar designidé i sig selv. Først normaliserer den ting, der er trygt reparerbar: annotation print flags, no-zoom- og no-rotate-flaggene på text annotations og appearance-generation-flagget på form dictionary. Det er indstillinger med én korrekt værdi under profilen og intet informationsindhold, så at rette dem lydløst er rigtigt, og at nægte over dem ville være pædanti
Så tjekker den de begrænsninger, der ikke kan repareres uden at ændre, hvad dokumentet betyder: version, identification, encryption, output intent, device color-sammenhæng og tilstedeværelsen af dynamisk form-indhold. Et dokument, der fejler nogen af dem, nægtes, for at opfinde et output intent eller vælge en farvefamilie på forfatterens vegne ville give en fil, der består validering og misrepræsenterer indholdet
At læse diagnostikken tilbage gennem GetPDFEDiagnostics før gemning forvandler den nægtelse til en handlingsorienteret liste frem for en fejlet operation. I en batch-pipeline: kald den på hvert dokument, log blockers pr. fil, og rout fejlene til en kø, et menneske kigger på. Det er langt mere nyttigt end en save, der kaster en exception, for blockers klumper sig normalt sammen: fyrre dokumenter, der fejler på grund af samme manglende output intent, er én fix, ikke fyrre
Valget mellem arkiveringsprofilerne
PDF/E-1 er det rigtige target, når deliverable er ingeniørdokumentation med en revisionslivscyklus, og især når device color-sammenhæng betyder noget, fordi output går til plottere og large-format-printere. PDF/A er det rigtige target, når målet er langsigtet læsbarhed af dokumenter i generel forstand, og det er profilen med den bredeste validator-understøttelse. De to er ikke udskiftelige, og et dokument kan tilfredsstille den ene og fejle den anden
Skal du vælge, så start med, hvem der validerer filen i den fjerne ende. PDF/A-valideringsværktøj er overalt, og den tilsvarende preflight i PDFlibPas er beskrevet i PDF/A- og PDF/UA-preflight. PDF/E-validering er mere specialiseret og er typisk et kontraktmæssigt krav snarere end et default. Skal et eksisterende arkiv bringes op på en profil, det aldrig var skrevet til, er metadata-reparationsstien i konvertering til PDF/A med metadata-reparation mønsteret at følge, og samme form gælder her: identificér, reparer det trygge, nægt resten med en liste
Author mode, den boundede content-preflight og det selvstændige compliance-tjek følger alle med PDFlibPas Delphi PDF-biblioteket, så et dokument kan produceres under profilen og efterfølgende verificeres uafhængigt gennem en separat kodevej, hvilket er den eneste ordning, der er værd at stole på for et conformance-krav