PDFium komponenta za Delphi i Lazarus razmjenjuje podatke obrazaca i anotacije putem XFDF-a, XML formata za razmjenu definiranog specifikacijom ISO 19444-1. Funkcija TPdf.ExportXFDF serijalizira svaku vrijednost polja obrasca i svaku podržanu anotaciju u učitanom dokumentu u XFDF datoteku ili TStream; TPdf.ImportXFDF čita XFDF dokument natrag, ponovno stvarajući anotacije na njihovim stranicama i primjenjujući vrijednosti polja. To jedno povratno putovanje pokriva dva tijeka rada koja svaka aplikacija za dokumente s vremenom zatreba: recenzent označava PDF u Acrobatu i šalje vam komentare na spajanje, ili pravilo o sukladnosti nalaže da podaci obrasca must živjeti u zasebnoj datoteci prikladnoj za uspoređivanje (diff) i reviziju, umjesto da budu zapečeni u samom PDF-u
Podržava li PDFium uvoz i izvoz XFDF-a?
Sama PDFium knjižnica to ne podržava. Izvorno C API uopće nema XFDF ili FDF funkcije — ništa u njegovim javnim zaglavljima ne čita niti piše bilo koji od tih formata, tako da vas nikakva količina omotavanja (wrappinga) ne može dovesti do toga. Komponenta PDFium stoga implementira cijeli XFDF mehanizam u Pascalu, u namjenskoj jedinici koja gradi i raščlanjuje XML izravno na vrhu postojećeg podatkovnog modela TPdf anotacija i polja obrazaca. Pisac emitira XML ručno, a čitač je ručno napisani parser sa stanjem (state-machine), pa ova značajka ne dodaje ovisnost o Delphi XMLDoc-u ili FPC DOM jedinicama i ponaša se identično u Delphiju i Lazarusu
Taj je dizajnerski izbor važan kada procjenjujete alternative. Ako ste pozivali sirove FPDF_* funkcije iz Pascala, XFDF je zid: ta mogućnost jednostavno ne postoji u DLL-u. Komponenta prelazi taj zid tretirajući XFDF kao čisti problem serijalizacije — prikupi vrijednosti polja i zapise anotacija koje omotač već zna pročitati, zapiši ih kao standardni XML i preokreni postupak pri uvozu
Što sadrži XFDF datoteka?
ISO 19444-1 definira XFDF kao XML prikaz FDF-a, a njegov se teret (payload) dijeli na dva bloka najviše razine. Element <fields> nosi hijerarhijska imena polja obrasca i njihove vrijednosti — sve što je korisnik upisao, odabrao ili označio u AcroFormu. Element <annots> nosi anotacije: TPdf.ExportXFDF emitira 18 podvrsta — tekst, isticanje (highlight), podcrtano, precrtano, valovito podcrtano (squiggly), linija, krug, kvadrat, kursor (caret), poligon, polilinija, pečat (stamp), tinta (ink), slobodan tekst, privitak datoteke, zvuk, poveznica i redigiranje. Widget anotacije namjerno su odsutne iz elementa <annots> jer njihovi podaci putuju u <fields>, a podvrste interne za preglednik kao što je skočni prozor (Popup) nisu dio rječnika XFDF-a
Kako bi povratno putovanje bilo vjerno, zapis TPdfAnnotation proširen je metapodacima koje XFDF očekuje: Name (jedinstveni identifikator NM), Subject, ModificationDate, CreationDate, Icon, Opacity, krajnje točke linije, vrhovi poligona i polilinije te staze gesti tinte. Svako novo polje uparuje se s logičkom (boolean) oznakom Has*, tako da se kôd koji je gradio anotacije na starijim verzijama nastavlja prevoditi i proizvoditi iste rječnike — nepostavljeno polje se nikada ne zapisuje. Ako već stvarate anotacije programski, isti zapis koji koristite za anotacije označavanja teksta s četverokutnim točkama (quad points) sada nosi sve što je potrebno za XFDF
Kako izvesti podatke obrazaca i anotacije u XFDF?
Jedan poziv obrađuje cijeli dokument. Učitajte PDF s omogućenim popunjavanjem obrazaca, pozovite ExportXFDF i komponenta prolazi kroz svaku stranicu, prikuplja vrijednosti polja i anotacije te zapisuje XML. Vraćena vrijednost je broj zapisanih UTF-8 bajtova, što služi kao jednostavna provjera ispravnosti u dnevnicima
var
Pdf: TPdf;
Bytes: Integer;
begin
Pdf := TPdf.Create(Self);
Pdf.FormFill := True; // needed so field values are live
Pdf.FileName := 'expense-report.pdf';
Pdf.Active := True;
Bytes := Pdf.ExportXFDF('expense-report.xfdf');
ShowMessage(Format('%d bytes of XFDF written', [Bytes]));
end;
Oba smjera imaju preopterećenje (overload) s TStream, tako da vas ništa ne tjera na korištenje privremene datoteke na disku. Izvoz u TMemoryStream je prirodan oblik kada je XFDF namijenjen HTTP odgovoru, bazi podataka (blob) ili potpisanoj arhivi
var
Buffer: TMemoryStream;
begin
Buffer := TMemoryStream.Create;
try
Pdf.ExportXFDF(Buffer); // same XML, no file involved
Buffer.Position := 0;
// hand the stream to a web response, blob column, or zip entry
finally
Buffer.Free;
end;
end;
Kako ImportXFDF spaja komentare natrag u dokument?
Uvozna strana je mjesto gdje se tijek rada recenzenta zatvara. Kolega označava ugovor u Acrobatu, izvozi komentare kao XFDF i šalje vam nekoliko kilobajta XML-a umjesto druge kopije PDF-a. Funkcija TPdf.ImportXFDF raščlanjuje tu datoteku, stvara svaku anotaciju na stranici koju imenuje njezin atribut page i upisuje vrijednosti polja u odgovarajuće widget anotacije. Funkcija vraća kombinirani broj primijenjenih polja i anotacija, tako da korisničko sučelje može potvrditi točno koliko ih je stiglo
var
Applied: Integer;
begin
Applied := Pdf.ImportXFDF('review-comments.xfdf');
StatusBar.SimpleText :=
Format('%d fields and annotations merged', [Applied]);
end;
Parser je ručno napisani skener oznaka izgrađen za tolerantnost, a ne strogoću: nepoznati se elementi preskaču, instrukcije za obradu, deklaracije DOCTYPE i komentari se zanemaruju, nepriznati nazivi zastavica se odbacuju, a vrijednosti atributa se dekodiraju kroz puni skup XML entiteta i numeričkih referenci znakova, uključujući UTF-16 surogatne parove. XFDF koji je proizveo Acrobat, web preglednik ili neki drugi alat spaja se bez poteškoća. Jednom kada su anotacije u dokumentu, ciklus pregleda nastavlja se s mehanizmom za odgovore i status opisanom u izgradnji tijeka rada za pregled anotacija s PDFium komponentom, a uvezene vrijednosti polja sudjeluju u uobičajenoj logici redoslijeda tabulatora pokrivenoj u navigaciji poljima obrasca
Zašto su decimalni separatori važni za XFDF?
Svaka anotacija u XFDF-u je pozicionirana koordinatnim nizovima — rect="70.5,540,200,560" i slično — a ISO 19444-1 zahtijeva točku kao decimalni separator. Delphi-jevo zadano oblikovanje brojeva s pomičnim zarezom (float) prati lokalitet sustava Windows, pa na njemačkom ili francuskom sustavu jednostavan FloatToStr pretvara 70.5 u 70,5, što kvari popis koordinata odvojenih zarezima u smeće koje drugi procesori odbijaju ili pogrešno čitaju. Komponenta PDFium normalizira svaki broj koji zapiše: decimalni separator lokaliteta prepisuje se u točku, a prateće nule se uklanjaju, pa je izvezena datoteka identična u bajtovima bez obzira je li proizvedena na en-US ili de-DE računalu. Ako ste ikada otklanjali pogreške u PDF alatu koji je radio u uredu, a zakazao kod europskog korisnika, susreli ste se s ovom klasom pogrešaka — dobro je znati da komponenta to rješava umjesto vas
Koje su granice povratnog putovanja?
Dvije granice vrijedi jasno navesti. Prvo, XFDF prenosi podatke o anotacijama, a ne njihov iscrtani izgled (appearance streams) koji nije dio formata, pa primateljski preglednik ponovno generira izgled svake anotacije iz njezinih svojstava. Isticanje (highlight) ili kvadrat iscrtat će se ispravno posvuda; pečat s prilagođenim izgledom vratit će se na ono što ciljni preglednik crta za taj naziv pečata. Drugo, osnovni PDFium API ima postavljače (setters) za tekstualne nizove, ali nema ih za brojeve anotacija ili geometriju staze, pa su Opacity, krajnje točke linije, vrhovi i gesti tinte namijenjeni samo za izvoz: komponenta ih vjerno čuva pri pisanju XFDF-a, ali ih ne može upisati natrag u PDF pri uvozu. Vrijednosti polja, sadržaji, boje, pravokutnici, četverokutne točke (quad points), datumi i metapodaci o identitetu prenose se u oba smjera
Za praktičan početak, uzorak XfdfLab isporučuje se u demonstracijskim skupovima za Delphi, C++Builder i Lazarus te povezuje oba poziva s gumbima nad bilo kojim PDF-om koji otvorite. Podrška za XFDF uključena je u trenutno izdanje PDFium komponente, uz API-je za anotacije i obrasce na kojima se temelji