Tehnički članak

Ograničenja implementacije PDF/A i provere kodiranja fonta

PDFium Component validira ograničenja implementacije ISO 19005-1 Annex C — imenski tokeni od 127 bajtova, 8191 element niza, 4095 unosa rečnika i 28 nivoa gnježđenja kontejnera — i prijavljuje simbolični TrueType font koji nosi /Encoding unos. Obe provere rade na putanji skeniranja bajtova, tako da Delphi ili Lazarus aplikacija dobija verdikt bez učitavanja PDFium DLL-a uopšte

Ovo su neuspesi koji najviše zbunjuju ljude, jer dokument izgleda u redu. Renderuje se, štampa, svaki font je ugrađen, namera izlaza je prisutna. Onda validator odbacuje fajl zbog rečnika koji ima 4096 unosa, a ništa u vidljivom dokumentu ne objašnjava zašto

Šta Annex C ograničenja zapravo štite?

Interoperabilnost sa implementacijama koje prethode vašem generatoru. Annex C prenosi ograničenja implementacije iz PDF Reference u svaki PDF/A deo, i brojevi nisu proizvoljni — oni opisuju šta je usaglašen čitalac istorijski bio obavezan da podrži. Fajl koji ih prekoračuje može se savršeno otvoriti u modernom pregledaču i pasti u arhivskom čitaču na kom je sistem zapisa standardizovan pre petnaest godina, što je upravo scenario koji PDF/A postoji da spreči

Četiri ograničenja su inkluzivna. Imenski token od tačno 127 bajtova prolazi; 128 ne prolazi. Niz sa tačno 8191 elementom prolazi; 8192 ne prolazi. PDFium Component učvršćuje obe strane svake granice u svom testiranom skupu iz tog razloga, jer greška od-jedan u proveri ograničenja proizvodi najgoru vrstu validatora: onaj koji odbacuje usaglašene fajlove i kome se ionako veruje

uses FPdfPdfa;

var
  Src: TFileStream;
  Res: TPdfAValidationResult;
begin
  Src := TFileStream.Create('archive.pdf', fmOpenRead or fmShareDenyWrite);
  try
    Res := ValidatePdfACompliance(Src);
    if pvaiArrayOverLimit in Res.Issues then
      Memo1.Lines.Add('An array carries more than 8191 elements');
    if pvaiDictOverLimit in Res.Issues then
      Memo1.Lines.Add('A dictionary carries more than 4095 entries');
    if pvaiNestingOverLimit in Res.Issues then
      Memo1.Lines.Add('Containers nest deeper than 28 levels');
    if pvaiNameOverLimit in Res.Issues then
      Memo1.Lines.Add('A name token is longer than 127 bytes');
  finally
    Src.Free;
  end;
end;

Koji generatori zapravo pogađaju ova ograničenja?

Oni koji grade strukturu programski, što je većina poslovnog izlaza. Formular sa nekoliko hiljada polja proizvodi /Annots niz ili AcroForm /Fields niz koji raste preko 8191. Stranica čiji rečnik resursa akumulira jedan unos po generisanoj slici ili instanci fonta prelazi 4095. Duboko generisana stabla strukture — označeni dokument izgrađen rekurzijom preko ugnježdenog modela podataka — prelaze 28 nivoa a da niko ne primeti, jer niko ne gleda dubinu gnježđenja

Dugačka imena dolaze iz drugačije navike: kodiranja podataka u imenske tokene. Ime koloranta izgrađeno iz identifikatora klijenta, grupa opcionog sadržaja imenovana po punoj putanji fajla, polje formulara čije potpuno kvalifikovano ime nadovezuje šest nivoa hijerarhije. Imena su jeftina za generisanje i lako ih je napraviti dugim, a 127 bajtova nestaje brže nego što biste očekivali jednom kad je uključena UTF-8 kodirana oznaka

Popravka je strukturna u svakom slučaju. Podelite niz, podelite rečnik, spljoštite gnježđenje, skratite ime — preflight preporuka za svaki problem imenuje konkretno ograničenje umesto da vam kaže da je fajl neispravan. Injektovanje markera ovde ne može pomoći: ovo nisu tvrdnje metapodataka, to je oblik grafikona objekata

Zašto simbolični TrueType font ne sme nositi /Encoding

Zato što ISO 19005-1 §6.3.7 prima samo ugrađeni cmap fonta za simbolične TrueType fontove, a /Encoding unos bi mu protivrečio. Simbolični font mapira kodove u glifove po svojim sopstvenim pravilima — to je ono što simbolično znači. Dodajte tabelu kodiranja i sada postoje dva odgovora na pitanje «koji glif bira bajt 0x41», bez pravila u fajlu koja kažu ko pobeđuje. Različiti čitači razrešavaju to različito, i dokument koji se renderuje kao tekst u jednom pregledaču renderuje se kao dingbats u drugom

PDFium Component čita simboličnu zastavicu iz /FontDescriptor, bilo da je deskriptor napisan inline u rečniku fonta ili referenciran indirektno. Nesimbolični TrueType font zadržava svoje obavezno /WinAnsiEncoding ili /MacRomanEncoding bez da bude označen, jer za nesimbolične fontove kodiranje jeste upravo ono što standard traži. Provera se aktivira na kontradikciji, a ne na prisustvu kodiranja

if pvaiSymbolicTrueTypeEncoding in Res.Issues then
  Memo1.Lines.Add(
    'A symbolic TrueType font carries /Encoding; PDF/A admits only its ' +
    'built-in cmap (ISO 19005-1 6.3.7)');

Praktični izvor ovog defekta jeste podskupovanje fontova koje radi producent koji tretira svaki TrueType font na isti način. Symbol, Wingdings, fontovi za barkod i fontovi za ikone su uobičajeni nosioci — upravo fontovi koje poslovni dokument koristi za potvrdne kućice, logotipe i barkodove, i upravo oni koje niko ne preispita kad dokument padne na validaciji zbog «fontova»

Kako problemi pristižu u preflight izveštaj

Četiri ograničenja kontejnera se klasifikuju pod strukturu; problem kodiranja simboličnog TrueType-a se klasifikuje pod sadržaj. Ta podela je važna kad izveštaj ide dvema različitim ljudima: nalazi strukture obično pripadaju onome ko je napisao generator, a nalazi sadržaja obično onome ko je isporučio materijale

Svaki problem nosi preporuku koja imenuje lek u konkretnim terminima — skratite imenske tokene na 127 bajtova ili manje, podelite nizove tako da nijedan ne nosi više od 8191 elementa, uklonite /Encoding iz simboličnih TrueType fontova. Izveštaj koji kaže «nije PDF/A usaglašen» započinje istragu. Izveštaj koji kaže koje je ograničenje prekoračeno i sa čim završava jednu

Validacija bez DLL-a, i zašto to ovde važi

Sve gore navedene provere rade protiv bajtova fajla, tako da rade u servisu koji nema primenjen PDFium binarni fajl, u koraku gradnje, ili na mašini gde je učitavanje nativnog DLL-a problem politike. To je namerna dizajnerska linija u PDFium Component-u: provere koje se mogu odgovoriti iz strukture odgovaraju se iz strukture, a DLL se rezerviše za one kojima iskreno treba motor za renderovanje

Za okolni tok rada — pokretanje validacije preko fascikle, proizvođenje izveštaja i odlučivanje šta raditi sa nalazima — pogledajte prolaze kroz PDF/A preflight validaciju u Delphi i CLI za paketni preflight izveštaj. Za izbor arhivskog profila koji sedi iznad svih ovih provera, beleške o PDF/A arhivskoj usaglašenosti pokrivaju koji deo i nivo ciljati pre nego što počnete da popravljate nalaze

PDFium Component obavija PDFium motor za Delphi, C++Builder i Lazarus sa visokonivoiskim VCL API-jem i skupom validatora usaglašenosti koji rade sa ili bez DLL-a — pogledajte stranicu PDFium Component proizvoda za podržane standarde i platforme