XFA (XML Forms Architecture) je zastario (deprecated). ISO 32000-1 ga nosi u §12.7 uz napomenu da je uklonjen iz PDF 2.0, a moderni preglednici jedan po jedan napuštaju svoje XFA mehanizme. Ništa od toga nije ispraznilo arhive. Vladini ulazni obrasci, zahtjevi za osiguranje, i bankovni izvodi pisani su kao XFA tijekom dobrog dijela od dva desetljeća, i te datoteke i danas još uvijek pristižu u sandučiće i cjevovode dokumenata. Kada ih preglednik koji ih je nekada renderirao prestane prikazivati, obrazac se pretvara u praznu stranicu s rezerviranim mjestom na kojem piše "molimo otvorite u nekom drugom čitaču". Trajno rješenje jest izravnavanje (flatten) XFA formata u onaj klasični statični PDF sadržaj kakvog baš svaki od svih onih čitača onda zna iscrtati
Najteži dio kod samog tog pa cijelog izravnavanja i nisu ta polja. Tekstualna polja kao ni potvrdni okviri prilično se tu uredno znaju preslikati kod i na svake dodijeljene tu AcroForm widget elemente. Onaj puno teži u cijeloj tu toj priči po tom navedenome odjeljak tu pak u svem bogati je taj dodani neki oblikovan obogaćeni tekst tu kojega taj naš ovdje sa onom samo za baš u onaj dodijeljen po jednom samo njoj crtaćem po u na zadan element unutra pri pohranjen XFA tu na o čuva, a iz to po sa o <exData contentType="text/html"> a na o bloku po u a. Taj blok je HTML podskup s ugrađenim stiliziranjem, i, često, sidrima. Njegovo postavljanje na stranicu znači reproduciranje stiliziranog teksta i žive hiperveze, a hiperveze su gdje većina implementacija tiho odustaje
Kako XFA obogaćeni tekst zapravo izgleda
Tijelo exData je mali isječak XHTML-a. Odlomak je <p>; oblikovanim stiliziranim rasponom znakova je <span> sa svojim vlastitim ugrađenim CSS-om za težinu, držanje, boju, i veličinu; i hiperveza je <a href="..."> koja omotava svoj vidljivi tekst. Jedina linija može sadržavati nekoliko raspona u nizu, svaki različitog stila, i jedan od njih može biti sidro. Stil nije dekoracija koja se može odbaciti. Klauzula prikazana podebljano i crveno zato što je pravno upozorenje mora ostati podebljana i crvena nakon izravnavanja, ili izravnani dokument pogrešno predstavlja original
Dakle, mehanizam za izravnavanje ne može tretirati blok kao jedan niz (string). Mora proći ugrađenom strukturom, razriješiti efektivni stil svakog niza slojevanjem ugrađenog CSS-a rasponovog preko osnovnog fonta crtaćeg elementa, i položiti nizove jedan nakon drugog duž linije. HotPDF modelira svaki od ovih položenih fragmenata kao interni TXFARichRun zapis. Zapis nosi tekst niza, njegov razriješeni stil, njegov izmjereni okvir, i, za sidro, Href na koji on pokazuje
Polaganje nizova s lijeva na desno
Pozicioniranje je točno tu gdje bogati tekst prestaje biti problem parsiranja i postaje problem tipografije (sloga). Nizovi dijele liniju, tako da svaki niz počinje gdje je prethodni završio. Nema oznaka koje bilježe te pozicije; moraju biti izmjerene. Interna rutina mehanizma LayoutRichText mjeri svaki niz istim metrikama fonta koje će ga kasnije naslikati, zatim postavlja horizontalni pomak niza na tekući zbroj svih prethodnih širina nizova. Niz jedan počinje na izvorištu crtaćeg okvira, niz dva počinje na širini niza jedan, niz tri na kombiniranoj širini prva dva, i tako dalje duž linije
To je razlog zašto je poravnanje fonta za mjerenje toliko važno. Prolaz za raspored mjeri pomake; zasebni prolaz za renderiranje crta glifove. Ako se ova dva prolaza ne slažu oko fonta, okviri koje je raspored izračunao neće sjesti ispod glifova koje render slika. HotPDF ih drži u koraku preslikavanjem razriješenog stila svakog niza na specifikaciju fonta, kroz interni pomoćni kod RunStyleToFontSpec, koji odgovara vlastitim zadanim postavkama renderera Arial od 10 točaka. Izmjereni pomak i nacrtani tekst tada se slažu, i izračunat okvir istinski pokriva znakove koje čitatelj vidi
// Conceptual shape of one laid-out run. The engine builds an array of these
// internally; you never construct them yourself, but the fields explain how a
// link's hit box is derived from measured geometry rather than from text.
type
TRichRunInfo = record
Dx, Dy : Double; // top-left, relative to the draw-box origin
W, H : Double; // measured run box (width from the layout pass)
Text : AnsiString; // the run's visible characters
Href : AnsiString; // URI target for an <a> run, '' otherwise
end;
Od sidrenog niza do PDF Link anotacije
Hiperveza u gotovom PDF-u nije dio sadržaja same te stranice. To je sasvim odvojeni objekt, takozvana Link anotacija, pobliže opisana u ISO 32000-1 §12.5.6.5. Ta ista anotacija ima jedan u sebe poslan zapis za /Rect koji potom definira onaj jedan baš takav klikabilni pravokutnik direktno na samoj stranici, i akciju koja se aktivira kada se na pravokutnik klikne. Za vanjsku vezu akcija je URI akcija: /S /URI s ciljnom adresom kao nizom /URI. Vidljivi tekst ispod je običan sadržaj stranice; anotacija je nevidljiva vruća zona položena preko njega
Putanja izravnavanja sasvim točno prati ovaj model. Kad niz nosi Href, HotPDF prvo crta stilizirani tekst, zatim gradi Link anotaciju preko okvira niza. Javna ulazna točka za tu anotaciju je metoda stranice AddURILink, koja stvara objekt /Type /Annot /Subtype /Link s akcijom /URI i vraća rječnik anotacije. Njegov pravokutnik je izmjereni okvir niza, preveden iz lokalnih koordinata elementa za crtanje u koordinate stranice. Rezultat je veza koja slijeće precizno na tekst sidra i nigdje drugdje
// The same public API the flatten path uses for each anchor run. It produces
// an ISO 32000-1 12.5.6.5 Link annotation: /Subtype /Link with a /URI action
// over the given rectangle. The optional description fills /Contents so a
// screen reader can announce the target.
var
LinkRect: TRect;
Annot: THPDFDictionaryObject;
begin
LinkRect := Rect(72, 690, 268, 706); // page-space hit box for the run
Annot := Pdf.CurrentPage.AddURILink(LinkRect,
'https://www.example.gov/appeal', 'File an appeal online');
end;
Zašto okvir mora ležati na izmjerenoj širini
Primamljivo je zamisliti lociranje veze pretraživanjem stranice za njezinim vidljivim tekstom i crtanjem pravokutnika oko svega što se pronađe. To ne funkcionira, a razlog tome fundamentalno leži u tome kako je izravnani tekst pohranjen. Stilizirani nizovi naslikani su ugrađenim fontovima podskupova. Font podskupa ponovno numerira glifove koje zadržava, tako da tok sadržaja stranice sadrži heksadecimalne CID kodove, a ne originalne kodove znakova. Bajtovi na stranici nisu slova koja čovjek čita, i oni nisu pretraživi kao tekst. Pretraživanje za natpisom sidra ne pronalazi ništa, zato što taj natpis ne postoji kao doslovni tekst nigdje u toku
Jedino pouzdano sidro za pravokutnik je geometrija koju je prolaz za raspored već generirao. Pomak i izmjerena širina svakog niza su izračunati dok se linija slijevala, prije nego što je bilo koji glif ponovno numeriran, i oni opisuju gdje će se tekst fizički pojaviti. HotPDF stoga uzima pravokutnik veze izravno iz postavljenog okvira niza, umjesto iz bilo kojeg tekstualnog pretraživanja. Budući da je mjerenje koristilo font za renderiranje, okvir je ispravan bez obzira na podskupove. Geometrija preživljava kodiranje; tekst ne. To je cijeli argument za pozicioniranje izmjerenom širinom, i to je razlog zašto program za izravnavanje koji pokušava naknadno ugraditi veze putem tekstualnog pretraživanja proizvodi "hit" zone koje plutaju ili nestaju
Pokretanje konverzije iz vašeg koda
Za PDF koji već sadrži XFA paket, ulazna točka je FlattenLoadedXFA. Učitajte dokument, pozovite metodu, i spremite rezultat. Parametar Editable odlučuje što se događa s poljima obrasca: proslijedite True kako biste ih zadržali kao popunjive AcroForm widgete, ili False kako biste označili svaki widget kao read-only da izlaz bude zamrznuti zapis. Blokovi za crtanje bogatog teksta, sa stiliziranim nizovima i anotacijama veza, su generirani u svakom slučaju. Funkcija vraća broj widgeta koje je emitirala
var
Pdf: THotPDF;
Emitted, i: Integer;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.LoadFromFile('xfa_appeal_form.pdf');
// True keeps fields fillable; False freezes them read-only.
Emitted := Pdf.FlattenLoadedXFA(True);
// Anything the engine could not map is reported, not raised.
for i := 0 to Pdf.XFAFlattenWarnings.Count - 1 do
Writeln('XFA warning: ', Pdf.XFAFlattenWarnings[i]);
Pdf.SaveLoadedDocument('appeal_form_flat.pdf');
Writeln('Widgets emitted: ', Emitted);
finally
Pdf.Free;
end;
end;
Uvijek pročitajte XFAFlattenWarnings nakon poziva. Lista se briše na početku svakog izravnavanja i akumulira liniju za svaki element koji je mehanizam odbio renderirati: nepodržanu vrstu polja, sliku za crtanje koja se ne dekodira, exData blok bez upotrebljivih raspona. Ništa od toga ne izbacuje iznimku, pa je prazna lista upozorenja vaš dokaz da se sve preslikalo, a neprazna vam točno govori koje originale trebate pregledati. Kada držite sirovi XFA kao XDP bajtove umjesto učitanog PDF-a, bratska metoda ApplyXFAAsAcroForm uzima te bajtove izravno i dijeli istu putanju koda i isto ponašanje upozorenja. Komplementarna metoda AddXFAPacket ide drugim putem, ugrađujući XFA paket u dokument koji gradite
Potvrđivanje rezultata u čitaču
Otvorite izravnanu datoteku u Acrobatu, ili u bilo kojem trenutnom pregledniku, i provjerite dvije stvari. Prvo, taj bogati tekst se renderirao s netaknutim svojim stilom: podebljani nizovi su i dalje podebljani, oni u boji i dalje nose svoju tu boju, a rasponi sjede u pravom redoslijedu unutar na tu samoj liniji, umjesto da se preklapaju ili pak ispadaju iz svog okvira. Drugo, te su hiperveze žive. Zadržite pokazivač miša iznad sidra i statusna traka bi trebala pokazati ciljnu adresu; kliknite na nju i URI akcija bi je trebala otvoriti. Koristite inspektor anotacija u pregledniku kako biste potvrdili da je svaka prava /Link anotacija čiji /Rect grli tekst sidra, sjedeći preko sadržaja koji je sada običan naslikan glif umjesto renderiranog XFA obrasca. Ta kombinacija, stilizirani statični tekst plus prave Link anotacije na pravim pravokutnicima, je ono što čini izravnani dokument da nadživi XFA mehanizme koje više ne treba
Izravnavanje samih tih tu za u i polja, tekstualnih okvira, potvrdnih okvira, i listi izbora koje okružuju ovaj bogati tekst, pokriveno je u našem vodiču o izravnavanju XFA obrazaca u AcroForm widgete. Za širu priču o izgradnji i postavljanju Link anotacija ručno, izvan onih koje putanja za izravnavanje generira, pogledajte rad s PDF anotacijama u HotPDF-u. Oboje se oslanja na isti model anotacija i obrazaca koji dolazi uz HotPDF komponentu za Delphi i C++Builder