Tehnički članak

Ograničenja implementacije PDF/A i provjere kodiranja fonta

PDFium Component provjerava ograničenja implementacije iz ISO 19005-1 Annex C, 127-bajtne tokene imena, 8191 elemenata polja, 4095 unosa rječnika i 28 razina ugniježđenja spremnika, te prijavljuje simbolički TrueType font koji nosi unos /Encoding. Obje provjere rade na putu pregleda bajtova, pa Delphi ili Lazarus aplikacija dobiva presudu bez učitavanja PDFium DLL-a uopće

To su neuspjesi koji zbunjuju ljude najviše, jer dokument izgleda u redu. Renderira se, ispisuje, svaki je font ugrađen, namjera izlaza je prisutna. Zatim ga validator odbacuje zbog rječnika koji ima 4096 unosa, a ništa u vidljivom dokumentu ne objašnjava zašto

Što ograničenja iz Annex C zapravo štite?

Interoperabilnost s implementacijama koje prethode vašem generatoru. Annex C prenosi ograničenja implementacije PDF Reference u svaki dio PDF/A, a brojevi nisu proizvoljni: oni opisuju što je sukladni čitač povijesno bio obavezan obraditi. Datoteka koja ih prekoračuje možda se savršeno otvara u modernom pregledniku, a pada u arhivskom čitaču na koji se sustav zapisa standardizirao prije petnaest godina, što je upravo scenarij koji PDF/A postoji da spriječi

Četiri ograničenja su uključiva. Token imena od točno 127 bajtova prolazi; 128 ne prolazi. Polje s točno 8191 elementom prolazi; 8192 ne prolazi. PDFium Component učvršćuje obje strane svake granice u svom probnom skupu iz tog razloga, jer greška za jedan u provjeri ograničenja proizvodi najgoru vrstu validatora: onu koja odbacuje sukladne datoteke, a joj se ionako vjeruje

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 doista pogađaju ta ograničenja?

Oni koji strukturu izgrađuju programski, što je većina poslovnog izlaza. Obrazac s nekoliko tisuća polja proizvodi polje /Annots ili polje AcroForm /Fields koje raste preko 8191. Stranica čiji rječnik resursa nakuplja jedan unos po generiranoj slici ili primjerku fonta prelazi 4095. Duboko generirana stabla strukture, označeni dokument izgrađen rekurzijom preko ugniježđenog modela podataka, prolaze preko 28 razina a da itko to ne primijeti, jer nitko ne gleda dubinu ugniježđenja

Duga imena dolaze iz drukčije navike: kodiranja podataka u tokene imena. Ime nositelja boje izgrađeno iz identifikatora kupca, grupa neobaveznog sadržaja imenovana po punoj putanji datoteke, polje obrasca čije potpuno kvalificirano ime spaja šest razina hijerarhije. Imena su jeftina za generiranje i lako ih je učiniti dugima, a 127 bajtova nestaje brže nego što biste očekivali jednom kad je uključena UTF-8 kodirana oznaka

Popravak je u svakom slučaju strukturalan. Podijelite polje, podijelite rječnik, spljoštite ugniježđenje, skratite ime; preporuka preleta za svaki problem imenuje konkretno ograničenje umjesto da vam kaže da je datoteka nevaljana. Ubrizgavanje oznaka ovdje ne može pomoći: to nisu zahtjevi metapodataka, to je oblik grafa objekata

Zašto simbolički TrueType font ne smije nositi /Encoding

Zato što ISO 19005-1 §6.3.7 prima samo ugrađeni cmap fonta za simboličke TrueType fontove, a unos /Encoding bi mu proturječio. Simbolički font preslikava kodove na glifove prema vlastitim pravilima, i to je što simboličko znači. Dodajte tablicu kodiranja i sada postoje dva odgovora na pitanje koji glif bira bajt 0x41, bez pravila u datoteci koje kaže koji pobjeđuje. Različiti čitači razrješuju to različito, pa dokument koji se u jednom pregledniku renderira kao tekst u drugom postaje ukrasni simboli

PDFium Component čita simboličku oznaku iz /FontDescriptor, bilo da je deskriptor zapisan ugrađeno u rječniku fonta ili neizravno referenciran. Nesimbolički TrueType font zadržava svoje obavezno /WinAnsiEncoding ili /MacRomanEncoding bez da bude označen, jer za nesimboličke fontove kodiranje jest upravo ono što standard traži. Provjera se aktivira na proturječju, a ne na prisutnosti 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 jest podskupljenje fonta koje obavlja producent koji tretira svaki TrueType font jednako. Symbol, Wingdings, fontovi barkoda i ikonski fontovi uobičajeni su nositelji, upravo fontovi koje poslovni dokument koristi za potvrdne okvire, logotipove i barkodove, i upravo oni koje nitko ne preispituje kad dokument padne na provjeri valjanosti zbog fontova

Kako se problemi pojavljuju u izvješću preleta

Četiri ograničenja spremnika klasificirana su pod strukturu; problem kodiranja simboličkog TrueType fonta klasificiran je pod sadržaj. Ta podjela je važna kad izvješće ide dvijema različitim osobama: nalazi strukture obično pripadaju onom tko je napisao generator, a nalazi sadržaja obično onom tko je isporučio imovinu

Svaki problem nosi preporuku koja imenuje lijek u konkretnim terminima, skratite tokene imena na 127 bajtova ili manje, podijelite polja tako da nijedno ne nosi više od 8191 elementa, uklonite /Encoding iz simboličkih TrueType fontova. Izvješće koje kaže nije sukladno s PDF/A započinje istragu. Izvješće koje kaže koje je ograničenje prekoračeno i za koliko završava istu

Provjera bez DLL-a i zašto to ovdje vrijedi

Sve gore navedene provjere rade protiv bajtova datoteke, pa rade u servisu koji nema raspoređen PDFium binarni kod, u koraku izgradnje ili na stroju gdje je učitavanje izvornog DLL-a politički problem. To je namjerna dizajnerska linija u PDFium Componentu: provjere koje se mogu odgovoriti iz strukture odgovaraju se iz strukture, a DLL je rezerviran za one kojima doista treba motor za renderiranje

Za okružujući cjevovod, pokretanje provjere preko mape, proizvodnja izvješća i odluka što učiniti s nalazima, pogledajte prikaze provjere preleta valjanosti PDF/A u Delphiju i serijskog CLI-ja izvješća preleta. Za izbor arhivskog profila koji sjedi iznad svih ovih provjera, bilješke o arhivskoj sukladnosti PDF/A pokrivaju koji dio i razinu ciljati prije nego što počnete popravljati nalaze

PDFium Component omata PDFium motor za Delphi, C++Builder i Lazarus s visokorazinskim VCL API-jem i skupom validatora sukladnosti koji rade s DLL-om ili bez njega. Pogledajte stranicu proizvoda PDFium Component za podržane standarde i platforme