Tehnički članak

Uvoz i izvoz PDF anotacija kao XFDF u Delphi-ju

HotPDF izvozi i uvozi PDF anotacije kao XFDF preko dve funkcije koje deluju na trenutno učitani dokument, ExportLoadedAnnotationsToXFDF i ImportLoadedAnnotationsFromXFDF. XFDF je XML format za razmenu anotacija standardizovan kao ISO 19444-1, a ovaj par omogućava programu u Delphi-ju ili C++Builder-u da preda svoje komentare Acrobat-u ili alatu za pregled treće strane i vrati označene rezultate nazad, bez menjanja sadržaja stranice na kojoj se anotacije nalaze

Zamislite dva smera koja ovo rešava. Recenzent otvara vaš generisani izveštaj u Acrobat-u, postavlja crvenu strelicu na loše poravnatu sliku, zaokružuje pogrešan ukupni zbir i upisuje belešku na margini, a zatim izvozi komentare u malu XFDF datoteku. Ili obrnuto: vaš program sam proizvodi oznake i morate ih poslati nekome čiji alat nije HotPDF. U oba slučaja anotacije putuju kao XML koji obe strane razumeju, a PDF stranice ostaju bajt-za-bajt ono što su i bile

Koja je razlika između FDF i XFDF-a?

FDF i XFDF prenose isti sadržaj u dve različite sintakse, a ta razlika postaje važna onog trenutka kada odlučite koju datoteku ćete predati drugom alatu. FDF is stariji format podataka obrazaca (Forms Data Format) definisan unutar same PDF specifikacije: koristi sintaksu PDF objekata, pa FDF datoteka izgleda kao ogoljeni PDF i zahteva parser koji razume PDF za čitanje. XFDF je XML izraz tih istih podataka, standardizovan nezavisno kao ISO 19444-1, što znači da bilo koja XML biblioteka na bilo kojoj platformi može da ga otvori, uporedi (diff) ili generiše. Oba formata mogu prenositi vrednosti polja obrasca u stablu <fields>, što reguliše član 6.3 standarda ISO 19444-1, kao i anotacije u stablu <annots>; HotPDF deli ove odgovornosti, usmeravajući podatke obrasca kroz ExportLoadedFormToXFDF i rezervišući ExportLoadedAnnotationsToXFDF za stranu <annots>. Kada razmenjujete komentare sa veb servisom, Java serverom za pregled ili skriptom, XFDF je format koji ne primorava drugu stranu da ugrađuje PDF parser

Kako izvesti PDF anotacije kao XFDF u Delphi-ju?

HotPDF izvozi anotacije tako što prolazi kroz svaku stranicu učitanog dokumenta, emitujući jedan XFDF element za svaku podržanu anotaciju i vraćajući broj upisanih anotacija. Prvo učitajte PDF, a zatim pozovite ExportLoadedAnnotationsToXFDF sa ciljnom putanjom. Rezultat celog broja je broj serijalizovanih anotacija; rezultat nula ili ispod nule znači da ništa nije izvezeno i da datoteka nije upisana, što vam je znak da dokument nije sadržao anotacije podržanog podtipa

var
  Pdf: THotPDF;
  Written: Integer;
begin
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile('report-reviewed.pdf', '') > 0 then
    begin
      // Write one XFDF element per supported annotation on every page
      Written := Pdf.ExportLoadedAnnotationsToXFDF('comments.xfdf');
      if Written <= 0 then
        ShowMessage('No supported annotations were found');
    end;
  finally
    Pdf.Free;
  end;
end;

XFDF koji se dobija je običan, čitljiv XML. HotPDF piše koren <xfdf> u imenskom prostoru ISO 19444-1, kontejner <annots> i po jedno dete za svaku anotaciju sa njenim indeksom stranice zasnovanim na nuli, bojom i geometrijom kao atributima ili pod-elementima. Linija sa žutim punjenjem i otvorenom strelicom na vrhu, koja se nalazi pored popunjenog poligona, serijalizuje se ovako

<?xml version="1.0" encoding="UTF-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/">
  <annots>
    <line page="0" start="72,700" end="220,700"
          color="#FF0000" interior-color="#FFFF00"
          head="OpenArrow" tail="None">
      <contents-richtext>Baseline looks off</contents-richtext>
    </line>
    <polygon page="0" color="#0000FF" interior-color="#CCE5FF">
      <vertices>72,120;180,120;180,200;72,200</vertices>
    </polygon>
  </annots>
</xfdf>

Kako se podtipovi anotacija preslikavaju na XFDF elemente

Svaki podtip anotacije se preslikava na specifičan ISO 19444-1 element sa sopstvenom konvencijom o geometriji, i HotPDF prati te strukture umesto da izmišlja sopstvene. Linijske anotacije (Line annotations) nose atribute start i end koji drže dva para koordinata krajnjih tačaka, uzetih direktno iz niza L anotacije, dok stilovi završetka linije LE postaju atributi head and tail. Poligonske i polilinijske anotacije pomeraju svoju listu tačaka u pod-element <vertices> kao x,y parove odvojene tačka-zarezom, a ne kao atribut, jer će čitač koji očekuje pod-element tiho odbaciti tačke skrivene na bilo kom drugom mestu. Ink anotacije (crteži mastilom), koje mogu da sadrže nekoliko zasebnih poteza, gnezde element <inklist> sa jednim <gesture> pod-elementom po potezu, tako da potpis sa više poteza preživljava prenos kao zasebni potezi, a ne kao jedna spojena mrlja

Bogat tekst, boja i stilovi ivica opstaju zajedno sa geometrijom. Telo sa bogatim tekstom u belešci se zapisuje kao <contents-richtext> pod-element; unutrašnje punjenje koje PDF čuva u nizu IC, boja unutar kruga, kvadrata, poligona ili strelice linije, kao i punjenje okvira za redakciju, prenose se kao atribut interior-color u obliku #RRGGBB; a širina ivice, obrazac crtica i efekat oblačne ivice (cloudy border) preslikavaju se u atribute width, dashes, style i intensity, tako da oblačić sa oblačnim konturama i dalje izgleda oblačno na drugom kraju. HotPDF takođe čuva iskačući prozor (popup window) priložen uz anotaciju markupa, uvozeći geometriju pod-elementa popupa i njegovo otvoreno ili zatvoreno stanje u rečnik Popup anotacije, i prenosi stanja otvorenosti i pregleda tekstualne anotacije, tako da pregledani dokument zadržava ne samo svoje oblike već i metapodatke radnog toka na koje se recenzenti oslanjaju

Uvoz XFDF-a nazad u učitani dokument

HotPDF uvozi XFDF tako što parsira XML, kreira novu anotaciju za svaki element kroz NewLoadedAnnotation, povezuje je sa stranicom koju element navodi i vraća broj dodatih anotacija. Radni tok je simetričan sa izvozom: učitajte osnovni PDF, pozovite ImportLoadedAnnotationsFromXFDF sa datotekom recenzenta, a zatim sačuvajte učitani dokument da biste sačuvali nove oznake. Ako datoteka nedostaje ili XML ne može da se parsira, funkcija vraća nulu i učitani dokument ostaje netaknut

var
  Pdf: THotPDF;
  Added: Integer;
begin
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile('report.pdf', '') > 0 then
    begin
      Added := Pdf.ImportLoadedAnnotationsFromXFDF('comments.xfdf');
      if Added > 0 then
        Pdf.SaveLoadedDocument('report-annotated.pdf');
    end;
  finally
    Pdf.Free;
  end;
end;

Pošto svaki XFDF element imenuje sopstveni indeks stranice, anotacije sleću na stranice za koje su kreirane čak i kada uvozite nekoliko datoteka u nizu, što omogućava bezbedno sakupljanje komentara od više recenzenata u isti učitani dokument pre jednog čuvanja. Primer ispod spaja komentare dva recenzenta u jednu spojenu kopiju. Za kreiranje i uređivanje samih objekata anotacija u kodu umesto njihove razmene u vidu datoteka, pogledajte kako HotPDF kreira i menja objekte PDF anotacija direktno iz Delphi-ju

var
  Pdf: THotPDF;
  Total, I: Integer;
  Files: array[0..1] of string;
begin
  Files[0] := 'alice-comments.xfdf';
  Files[1] := 'bob-comments.xfdf';
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile('master.pdf', '') > 0 then
    begin
      Total := 0;
      for I := Low(Files) to High(Files) do
        Inc(Total, Pdf.ImportLoadedAnnotationsFromXFDF(Files[I]));
      if Total > 0 then
        Pdf.SaveLoadedDocument('master-merged.pdf');
    end;
  finally
    Pdf.Free;
  end;
end;

Šta se uspešno prenosi u oba smera (round-trip), a šta ne

HotPDF uspešno prenosi u oba smera one podtipove anotacija kojima standard ISO 19444-1 pruža podršku, i namerno preskače ostale umesto da emituje nešto što bi čitač mogao pogrešno protumačiti. Podržani skup obuhvata tipove oznaka koji dominiraju u stvarnom radu na pregledu: tekstualne beleške, slobodan tekst, liniju, kvadrat, krug, poligon, poliliniju, četiri tipa markiranja teksta (isticanje, podvlačenje, precrtavanje i talasasta linija), pečat, mastilo i katicu (caret), plus prilog datoteke, zvuk, redakciju i vezu, ukupno osamnaest podtipova. Anotacija čiji podtip pada van ove liste preskače se pri izvozu, a pošto se preskače umesto da bude upisana prazna, ona ne uvećava broj koji funkcija vraća

Bogat tekst je iskrena napomena. HotPDF čuva telo <contents-richtext> tako da stilizovani tekst i običan sadržaj prelaze put, ali XFDF prenosi tekst komentara i oznake stila, a ne renderovani tok izgleda, tako da aplikacija koja prima podatke ponovo iscrtava iskačući prozor sa sopstvenim fontovima i rasporedom umesto da reprodukuje tačne piksele HotPDF-a. Tretirajte ovaj prenos u oba smera kao veran sadržaju i nameri, a ne vizuelnom renderovanju na ekranu do nivoa piksela. Ako vaš stilizovani sadržaj živi u XFA podacima obrasca umesto u tokovima anotacija, pravila se razlikuju, a članak o tome kako HotPDF rukuje XFA exData podacima, bogatim tekstom i hipervezama pokriva tu posebnu putanju

Rukovanje na nivou karaktera je strože nego što izgleda, što je upravo ono što želite. HotPDF primenjuje pravila eskejpovanja iz člana 5.8.2 standarda ISO 19444-1 kada piše tekst, kodirajući XML-značajne karaktere i kontrolne bajtove tako da komentar koji sadrži ampersend (&), ugaonu zagradu ili prelom reda proizvodi ispravno formatiran XML koji prihvata svaki usklađeni parser, i poništava ista pravila pri uvozu. Zato se beleška preuzeta iz tabele, sa svom interpunkcijom, vraća netaknuta umesto da ošteti datoteku

Annotation exchange is one slice of what the loaded-document API does, and it composes with the rest: import a reviewer's XFDF, adjust the pages or uredite metapodatke dokumenta, flatten or re-permission the file, then export a fresh XFDF for the next round. All of it ships in the standard HotPDF Component for Delphi and C++Builder, čija referenca dokumentuje potpunu pokrivenost podtipova anotacija i prateće funkcije za XFDF podatke obrazaca