Teknisk artikel

PDF/A, PDF/X og PDF/UA-output i Delphi: en HotPDF-guide

PDF/A, PDF/X og PDF/UA er tre forskellige standarder, der løser tre forskellige problemer: langtidsarkivering, udveksling til tryk og tilgængelighed. De er ikke tre afkrydsningsfelter på én compliance-formular, og den mest almindelige fejl er at behandle dem, som om de var. En fil kan være fejlfri PDF/A og ubrugelig for et trykkeri; en perfekt trykmaster kan være ulæselig for en skærmlæser. Værre endnu er alle tre begrænsninger på filens interne struktur, ikke på hvordan den ser ud. Et dokument, der åbner rent i hver eneste viser, du selv har, kan stadig fejle validering ved første forsøg, og det gør det som regel

HotPDF, losLabs native VCL PDF-bibliotek, behandler konformitet som noget, man erklærer, før den første side overhovedet findes. Man sætter en compliance-egenskab, tilføjer de strukturer, standarden kræver, og biblioteket afviser konfigurationer, der modsiger profilen, ved gemning. Det er en bedre model end at generere en fil og håbe, at en efterbehandler kan eftermontere det, fordi det meste af, hvad disse standarder kræver, ikke kan tilføjes bagefter

Tre ISO-standarder, tre forskellige løfter

PDF/A (ISO 19005) handler om tid. Den lover, at en fil stadig vil gengives identisk om årtier, så den kræver fuldstændig selvforsyning: hver skrifttype indlejret, hver farve givet en enhedsuafhængig betydning gennem en OutputIntent, fuld XMP-metadata og et forbud mod alt, hvis adfærd afhænger af miljøet. Kryptering og JavaScript er ude, fordi ingen kan garantere, at dekrypteringen eller script-motoren eksisterer i 2050

PDF/X (ISO 15930) handler om farve på papir. Den findes, så en designer kan overrække en fil til et trykkeri, ingen af dem behøver at diskutere, hvilket betyder karakteriserede trykforhold, en obligatorisk /Trapped-nøgle, definerede beskærings- og udfaldsgeometrier, og i X-1a-varianten ingen live-gennemsigtighed for RIP'en at gætte på. PDF/UA (ISO 14289) handler om, hvem der kan læse resultatet. Hjælpeteknologi har brug for et komplet tag-træ, en fornuftig læserækkefølge, et erklæret dokumentsprog og tekstalternativer for alt, der ikke er tekst

Fordi de tre trækker i forskellige retninger, så vælg den styrende standard per outputkanal frem for at jagte én fil, der tilfredsstiller dem alle. En rent CMYK-baseret trykmaster er præcis det forkerte at give en skærmlæserbruger, som aldrig ser farve, og arkivprofilens lockdown på dynamisk adfærd kolliderer med alt interaktivt. Generér per kanal fra de samme kildedata, og man undgår hele konflikten

HotPDF genererer PDF/A-, PDF/X- og PDF/UA-filer pr. outputkanal fra ét kildedokument i Delphi, hvor hver ISO-standard holder et andet strukturelt løfte
PDF/A, PDF/X og PDF/UA trækker i hver sin retning, så HotPDF genererer én fil pr. outputkanal ud fra samme kilde

PDF/A: OutputIntent er den del, alle glemmer

Fejler en PDF/A-fil validering, er OutputIntent det første, man skal tjekke. Det er den struktur, generatorer springer over hyppigst, netop fordi intet synligt afhænger af den. ISO 19005 kræver én: en indlejret ICC-profil, der fastlægger, hvad dokumentets enhedsfarver rent faktisk betyder. HotPDF gør den profil til et eksplicit input frem for en eftertanke:

var
  Pdf: THotPDF;
  ICC: TFileStream;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := 'invoice-archival.pdf';
    Pdf.PDFACompliance := 'B';            // niveau B: visuel troskab
    Pdf.Lang := 'en-US';
    Pdf.StandardFontEmulation := False;   // indlejr rigtige skrifttyper, ingen Base-14-emulering
    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;

Nogle få detaljer afgør bestået eller ikke-bestået her. StandardFontEmulation skal være slået fra: emulerede Base-14-skrifttyper indlejres ikke, og indlejring er ikke til forhandling under ISO 19005. Kryptering skal forblive deaktiveret, så kombinér aldrig PDFACompliance med ActivateProtection; en krypteret arkivfil er en selvmodsigelse, validatoren fanger med det samme. Komponentantallet i AddPDFAOutputIntent skal matche profilen, hvilket er 3 for en RGB-profil som sRGB IEC61966-2.1 og 4 for CMYK. HotPDF sporer brugen af DeviceRGB og DeviceCMYK mod den erklærede intent, mens den skriver, så en forvildet CMYK-fyldning i et RGB-intent-dokument bliver til et rapporteret problem frem for et stille et

Én ting er værd at sige om ICC-profilen: behandl den som en versioneret deployment-artefakt, ikke en fil, nogen engang smed på build-serveren. Dens bytes indlejres i hvert dokument, man genererer, så en afkortet eller korrupt profil forgifter stille en hel batch, og man opdager det først ved valideringstidspunktet. Send den med din installer, registrér dens checksum i kørselsloggen, og indlæs den via TFileStream-mønstret vist ovenfor, så en manglende fil fejler højlydt under generering i stedet for stille ved arkivporten

PDF/X til tryk: Trapped, CMYK og trykprofilen

Trykmastere vender farvefortællingen på hovedet. Trykkeriet vil have karakteriseret CMYK, og standarden tvinger dig til at angive, om trapping er blevet anvendt, selv når det ærlige svar er, at man ikke aner det. /Trapped-nøglen er obligatorisk uanset hvad:

Pdf.PDFXCompliance := 'X-1a';
Pdf.Trapped := 'Unknown';        // obligatorisk nøgle 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;
// tegn med CMYK-sikre farver, ingen gennemsigtighed, ingen kryptering
Pdf.EndDoc;

Komponentantallet er nu 4 for CMYK-trykprofilen. X-1a forbyder også live-gennemsigtighed, så gennemgå enhver tegnekode, der lægger gennemsigtige elementer i lag; hvad end en viser komponerer på skærmen, er præcis det, en RIP vil nægte at fortolke. Når dit trykkeri sender en anden karakterisering, så udskift profilbytene og identifikator-strengen, men lad den omgivende struktur være i fred

PDF/UA: struktur genereres, eftermonteres aldrig

Tilgængelighed er den standard, teams oftest forsøger at bolte på til sidst, og den straffer den tilgang hårdere end de to andre. Tag-træet skal afspejle den rækkefølge, indholdet logisk blev skabt i, hvilket er information, man ganske enkelt ikke længere har, når filen er skrevet. At sætte PDFUACompliance slår tagged output til, og structure-API'et binder hvert tegnekald til sin semantiske rolle undervejs:

HotPDF bygger PDF/UA-tagtræet live, efterhånden som hvert Delphi-tegnekald udføres, og tekst udsendt uden for BeginTaggedContent og EndTaggedContent forbliver usynlig for skærmlæsere
Tag-træet skrives, mens du tegner, og tekst uden for et tagget par renderer fint, men forbliver usynlig for skærmlæsere
Pdf.PDFUACompliance := True;     // aktiverer automatisk tagged PDF
Pdf.Lang := 'en-US';             // sæt eksplicit; tom falder tilbage til '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;

Den fejl, man skal holde øje med, er tekst tegnet uden for et BeginTaggedContent/EndTaggedContent-par. Den gengives perfekt og forbliver usynlig for en skærmlæser, så ingen seende tester nogensinde fanger den; fejlen bliver sendt og dukker først op, når en faktisk bruger af hjælpeteknologi rammer hullet. Når dine skabeloner bærer brugerdefinerede struktur-rollenavne, så map dem over på det standardiserede sæt med AddStructRoleMap('MyHead', 'H1'), så konforme læsere ved, hvad de betyder. ISO 14289 kræver også et erklæret sprog. HotPDF falder tilbage til 'en', når Lang er tom, men det er et sikkerhedsnet, ikke en grund til at lade det reelle dokumentsprog stå usat

Verifikation: stol på validatoren, ikke viseren

En viser, der åbner din fil, beviser intet om konformitet, så verifikation hører hjemme i release-flowet med værktøjer, der tjekker struktur frem for gengivelse. For PDF/A og PDF/UA er veraPDF referenceklassens åbne validator; den rapporterer fejl efter ISO-paragraf, hvilket kortlægger direkte tilbage til konfigurationen ovenfor. For PDF/X er Adobe Acrobats Preflight-profiler stadig det praktiske tjek, fordi trykkonformitet handler lige så meget om farveintent som syntaks

Generatoren gør sin egen del af dette. Ved gemning afstemmer HotPDF feature-flagene mod den konfigurerede PDF-version og nedgraderer stille det, versionen ikke kan udtrykke, såsom AES-256, der falder tilbage til AES-128 under PDF 1.7. Compliance-portene i EndDoc går videre og rejser en undtagelse direkte ved hårde modsigelser, som at bede om PDFACompliance sammen med kryptering. Ingen af disse erstatter den eksterne validator. De forhindrer blot umulige konfigurationer i nogensinde at nå den

HotPDF complianceporte i EndDoc fanger umulige konfigurationer, før veraPDF validerer PDF/A og PDF/UA, og Acrobat Preflight validerer PDF/X i en Delphi release-sti
HotPDF nægter modstridende konfigurationer ved EndDoc, og uafhængige validatorer afgør reel overensstemmelse

Én vane betaler sig igen og igen: versionér hele compliance-opsætningen som én enhed. HotPDF-udgivelsen, skabelonrevisionen, ICC-profilens checksum, den validator-build, der godkendte det. Konformitet driver, i det øjeblik en enkelt af dem ændres under de andre, og de grimmeste audits er dem, hvor ingen kan rekonstruere, hvilken kombination der producerede en fem år gammel arkivfil. Én konfigurationsregistrering per batch afgør det for altid

Til sidst, kør validatoren på reelt produktionsoutput, aldrig på et pænt håndbygget eksempel. De fejl, der bider, kommer fra data, ingen forudså: et kundelogo, der ankommer som CMYK, mens intenten siger RGB, en skabelonjustering, der lusker en uindlejret skrifttype med, en ny kodesti, der tegner tekst uden for tag-træet. Behold én kendt-dårlig fil fra hver tidligere hændelse som et regressionsinput, og compliance-porten forbliver ærlig over tid. For gengivelsessiden af disse pipelines, se vores artikel om rapportoutput, skrifttyper og billeder med HotPDF; for at koble validatorer ind i en build er der et følgestykke om at automatisere PDF-preflight-tjek

Compliance-egenskaberne, output intents og tagging-API'et, der bruges i disse eksempler, leveres med HotPDF Delphi Component til Delphi og C++Builder; produktsiden linker til den fulde reference for hvert kald vist her