Articol tehnic

Importul și exportul adnotărilor PDF ca XFDF în Delphi

HotPDF exportă și importă adnotările PDF ca XFDF prin intermediul a două funcții care acționează asupra documentului încărcat în prezent: ExportLoadedAnnotationsToXFDF și ImportLoadedAnnotationsFromXFDF. XFDF este formatul XML de schimb de adnotări standardizat ca ISO 19444-1, iar această pereche permite unui program Delphi sau C++Builder să transmită comentariile sale către Acrobat sau un instrument de revizuire terț și să primească înapoi rezultatele marcate, fără a rescrie conținutul paginii pe care se află adnotările

Imaginați-vă cele două direcții pe care le rezolvă acest mecanism. Un recenzent deschide raportul generat de dvs. în Acrobat, plasează o săgeată roșie pe o figură nealiniată, încercuiește un total greșit și scrie o notă pe marjă, apoi exportă comentariile într-un fișier XFDF mic. Sau invers: programul dvs. produce marcajele în sine, iar dvs. trebuie să le trimiteți cuiva care folosește alt instrument decât HotPDF. În ambele cazuri, adnotările circulă ca un XML pe care ambele părți îl înțeleg, iar paginile PDF rămân identice la nivel de octet

Care este diferența dintre FDF și XFDF?

FDF și XFDF conțin aceleași date în două sintaxe diferite, iar distincția contează în momentul în care decideți ce fișier să trimiteți unui alt instrument. FDF este vechiul format Forms Data Format definit în cadrul specificației PDF în sine: utilizează sintaxa de obiecte PDF, așa că un fișier FDF arată ca un PDF simplificat și are nevoie de un parser compatibil PDF pentru a fi citit. XFDF este forma XML a acelorași date, standardizată independent ca ISO 19444-1, ceea ce înseamnă că orice bibliotecă XML de pe orice platformă o poate deschide, compara sau genera. Ambele formate pot transporta valorile câmpurilor de formular într-un arbore <fields>, reglementat de clauza 6.3 din ISO 19444-1, și adnotările într-un arbore <annots>; HotPDF separă aceste responsabilități, direcționând datele de formular prin ExportLoadedFormToXFDF și rezervând ExportLoadedAnnotationsToXFDF pentru zona <annots>. Când schimbați comentarii cu un serviciu web, un server de revizuire Java sau un script, XFDF este formatul care nu obligă cealaltă parte să integreze un parser PDF

Cum se exportă adnotările PDF ca XFDF în Delphi?

HotPDF exportă adnotările parcurgând fiecare pagină a documentului încărcat, emițând un element XFDF pentru fiecare adnotare acceptată și returnând numărul de adnotări scrise. Încărcați mai întâi PDF-ul, apoi apelați ExportLoadedAnnotationsToXFDF cu o cale țintă. Rezultatul de tip întreg reprezintă numărul de adnotări serializate; un rezultat mai mic sau egal cu zero înseamnă că nu s-a exportat nimic și nu s-a scris niciun fișier, semnalând că documentul nu conține adnotări de subtip acceptat

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;

Cum se mapează subtipurile de adnotări la elementele XFDF

Fiecare subtip de adnotare se mapează pe un element specific ISO 19444-1 cu propria convenție de geometrie, iar HotPDF urmează acele structuri în loc să inventeze unele proprii. Adnotările de tip linie (line) conțin atributele start și end care stochează cele două perechi de coordonate ale punctelor terminale, preluate direct din tabloul L al adnotării, în timp ce stilurile de capăt de linie LE devin atributele head și tail. Adnotările de tip poligon (polygon) și polilinie (polyline) mută lista lor de puncte într-un element copil <vertices> ca perechi x,y separate prin punct și virgulă, nu ca un atribut, deoarece un cititor care se așteaptă la elementul copil va ignora punctele ascunse în altă parte. Adnotările de tip cerneală (ink), care pot conține mai multe linii separate, includ un element <inklist> cu un element copil <gesture> pentru fiecare linie, astfel încât o semnătură formată din mai multe mișcări supraviețuiește ca gesturi distincte, nu ca o singură pată unitară

Formatarea textului, culorile și stilul marginilor supraviețuiesc alături de geometrie. Corpul textului formatat al unei note este scris ca element copil <contents-richtext>; umplerea interioară pe care PDF-ul o stochează în tabloul IC, culoarea din interiorul unui cerc, pătrat, poligon sau capăt de săgeată și umplerea unei casete de redactare apar ca atribut interior-color în format #RRGGBB; iar lățimea marginii, modelul de linii întrerupte și efectul de margine noroasă (cloudy) se mapează pe atributele width, dashes, style și intensity, astfel încât un nor de text se va citi în continuare ca fiind noros la celălalt capăt. HotPDF păstrează de asemenea fereastra pop-up atașată la o adnotare de marcaj, importând geometria copilului pop-up și starea sa deschisă sau închisă în dicționarul Popup al adnotării, și transferă stările de deschidere și revizuire ale adnotărilor text, astfel încât un document revizuit își păstrează nu doar formele, ci și metadatele de workflow pe care se bazează recenzenții

Importul XFDF înapoi într-un document încărcat

HotPDF importă XFDF prin analizarea XML-ului, creând o adnotare nouă pentru fiecare element prin NewLoadedAnnotation, atașând-o al pagina pe care o indică elementul și returnând numărul de adnotări adăugate. Fluxul de lucru este simetric cu cel de export: încărcați PDF-ul de bază, apelați ImportLoadedAnnotationsFromXFDF cu fișierul recenzentului, apoi salvați documentul încărcat pentru a stoca noile marcaje. Dacă fișierul lipsește sau XML-ul nu poate fi analizat, funcția returnează zero, iar documentul încărcat rămâne nemodificat

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;

Deoarece fiecare element XFDF indică propriul indice de pagină, adnotările ajung exact pe paginile pe care au fost create, chiar și atunci când importați mai multe fișiere în secvență, permițând colectarea în siguranță a comentariilor de la mai mulți recenzenți pe același document încărcat înainte de salvare. Exemplul de mai jos combină marcajele a doi recenzenți într-o singură copie comună. Pentru construirea și editarea obiectelor de adnotare direct din cod, în loc de schimbul prin fișiere, consultați modul în care HotPDF creează și editează obiecte de adnotare PDF direct din Delphi

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;

Ce se transferă curat în ambele sensuri (round-trip) și ce nu

HotPDF transferă în ambele sensuri subtipurile de adnotări acceptate de ISO 19444-1 și le omite în mod deliberat pe celelalte, în loc să genereze elemente pe care un cititor le-ar interpreta greșit. Setul acceptat cuprinde tipurile de marcaje care domină activitatea reală de revizuire: note text, text liber, linii, pătrate, cercuri, poligoane, polilinii, cele patru tipuri de marcaj text (evidențiere, subliniere, tăiere și linie ondulată), ștampile, cerneală și caret, plus atașamente de fișiere, sunet, redactare și linkuri — în total optsprezece subtipuri. O adnotare al cărei subtip se află în afara acestei liste este ignorată la export și, fiind omisă în loc să fie scrisă goală, nu mărește numărul returnat de funcție

Textul formatat este o limitare onestă. HotPDF păstrează corpul <contents-richtext>, astfel încât textul stilizat și conținutul simplu fac călătoria, dar XFDF transportă textul și stilul comentariului, nu un flux de aspect (appearance stream) deja randat, astfel încât aplicația receptoare redesenează pop-up-ul cu propriile sale fonturi și așezări în pagină, în loc să reproducă pixelii exacți ai HotPDF. Tratați acest transfer ca fiind fidel conținutului și intenției, nu randării pixel cu pixel de pe ecran. Dacă conținutul dvs. stilizat se află în datele de formular XFA în loc de fluxurile de adnotări, regulile diferă, iar articolul despre modul în care HotPDF gestionează XFA exData, textul formatat și hyperlinkurile acoperă această cale separată

Gestionarea la nivel de caracter este mai strictă decât pare, ceea ce este exact ceea ce vă doriți. HotPDF aplică regulile de escapare din clauza 5.8.2 din ISO 19444-1 atunci când scrie text, codificând caracterele semnificative în XML și octeții de control, astfel încât un comentariu ce conține un ampersand, o paranteză unghiulară sau o întrerupere de linie produce un XML bine formatat pe care orice parser conform îl acceptă, inversând aceleași reguli la import. Acesta este motivul pentru care o notă copiată dintr-o foaie de calcul, cu toată punctuația ei, revine intactă în loc să corupă fișierul

Schimbul de adnotări reprezintă doar o parte din ceea ce face API-ul pentru documente încărcate și se integrează perfect cu restul funcțiilor: importați fișierul XFDF al unui recenzent, ajustați paginile sau editați metadatele documentului, aplatizați sau reconfigurați permisiunile fișierului, apoi exportați un XFDF nou pentru runda următoare. Toate acestea sunt livrate în pachetul standard HotPDF Component pentru Delphi și C++Builder, a cărei documentație descrie acoperirea completă a subtipurilor de adnotări și funcțiile XFDF însoțitoare pentru datele de formular