HotPDF esporta e importa le annotazioni PDF come XFDF tramite due funzioni che agiscono sul documento attualmente caricato: ExportLoadedAnnotationsToXFDF e ImportLoadedAnnotationsFromXFDF. XFDF è il formato XML di scambio delle annotazioni standardizzato come ISO 19444-1, e questa coppia consente a un programma Delphi o C++Builder di passare i propri commenti ad Acrobat o a uno strumento di revisione di terze parti e recuperare i risultati contrassegnati, il tutto senza riscrivere il contenuto della pagina su cui si trovano le annotazioni
Immagina le due direzioni risolte da questo approccio. Un revisore apre il report generato in Acrobat, inserisce una freccia rossa su una figura disallineata, cerchia un totale errato e digita una nota a margine, quindi esporta i commenti in un piccolo file XFDF. O il contrario: il tuo programma produce autonomamente i contrassegni e devi inviarli a qualcuno che utilizza uno strumento diverso da HotPDF. In entrambi i casi, le annotazioni viaggiano come XML comprensibile per entrambe le parti e le pagine PDF rimangono identiche byte per byte
Qual è la differenza tra FDF e XFDF?
FDF e XFDF trasportano lo stesso contenuto in due sintassi diverse, e la distinzione è importante nel momento in cui si decide quale file passare a un altro strumento. FDF è il formato Forms Data Format più datato, definito all'interno della specifica PDF stessa: utilizza la sintassi degli oggetti PDF, quindi un file FDF assomiglia a un PDF ridotto e richiede un analizzatore compatibile con il PDF per essere letto. XFDF è l'espressione XML degli stessi dati, standardizzata in modo indipendente come ISO 19444-1, il che significa che qualsiasi libreria XML su qualsiasi piattaforma può aprirla, confrontarla o generarla. Entrambi i formati possono contenere valori di campi modulo in un albero <fields>, regolato dalla clausola 6.3 di ISO 19444-1, e annotazioni in un albero <annots>; HotPDF suddivide queste responsabilità, instradando i dati dei moduli tramite ExportLoadedFormToXFDF e riservando ExportLoadedAnnotationsToXFDF per la parte <annots>. Quando scambi commenti con un servizio web, un server di revisione Java o uno script, XFDF è il formato che evita all'altra parte di dover incorporare un analizzatore PDF
Come si esportano le annotazioni PDF come XFDF in Delphi?
HotPDF esporta le annotazioni scorrendo ogni pagina del documento caricato, emettendo un elemento XFDF per ogni annotazione supportata e restituendo il numero di annotazioni scritte. Carica prima il PDF, quindi chiama ExportLoadedAnnotationsToXFDF con un percorso di destinazione. Il risultato intero è il numero di annotazioni serializzate; un risultato pari o inferiore a zero indica che nulla è stato esportato e nessun file è stato scritto, il che segnala che il documento non conteneva annotazioni di un sottotipo supportato
var
Pdf: THotPDF;
Written: Integer;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile('report-reviewed.pdf', '') > 0 then
begin
// Scrive un elemento XFDF per ogni annotazione supportata su ogni pagina
Written := Pdf.ExportLoadedAnnotationsToXFDF('comments.xfdf');
if Written <= 0 then
ShowMessage('No supported annotations were found');
end;
finally
Pdf.Free;
end;
end;
L'XFDF che viene generato è XML semplice e leggibile. HotPDF scrive una radice <xfdf> nello spazio dei nomi ISO 19444-1, un contenitore <annots> e un elemento figlio per ciascuna annotazione con il relativo indice di pagina a base 0, colore e geometria come attributi o elementi figli. Una linea con riempimento giallo e punta a freccia aperta, situata accanto a un poligono riempito, viene serializzata in questo modo
<?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>
In che modo i sottotipi di annotazione si mappano sugli elementi XFDF
Ciascun sottotipo di annotazione si mappa su uno specifico elemento ISO 19444-1 con la propria convenzione geometrica, e HotPDF segue queste strutture anziché inventarne di proprie. Le annotazioni di tipo linea contengono un attributo start e uno end che contengono le due coppie di coordinate dei punti finali, prese direttamente dall'array L dell'annotazione, mentre gli stili di fine linea LE diventano attributi head e tail. Le annotazioni poligono e polilineao spostano il loro elenco di punti in un elemento figlio <vertices> come coppie x,y separate da punti e virgola, non come attributo, poiché un lettore che si aspetta l'elemento figlio scarterà silenziosamente i punti nascosti altrove. Le annotazioni a inchiostro (ink), che possono contenere diversi tratti separati, racchiudono un elemento <inklist> con un elemento figlio <gesture> per ogni tratto, in modo che una firma a più tratti sopravviva al percorso come gesti distinti anziché come un'unica massa unita
Il testo formattato (rich text), il colore e lo stile del bordo sopravvivono insieme alla geometria. Il corpo in rich text di una nota viene scritto come elemento figlio <contents-richtext>; il riempimento interno che il PDF memorizza nell'array IC, la pittura all'interno di un cerchio, quadrato, poligono o punta di freccia di una linea e il riempimento di una casella di redazione, si presentano come un attributo interior-color in formato #RRGGBB; la larghezza del bordo, il tratteggio e l'effetto bordo sfumato si mappano sugli attributi width, dashes, style e intensity, in modo che un richiamo con bordo sfumato appaia ancora tale all'estremità finale. HotPDF preserva anche la finestra popup associata a un'annotazione di markup, importando la geometria figlia del popup e il suo stato aperto o chiuso nel dizionario Popup dell'annotazione, e trasporta gli stati aperti e di revisione delle annotazioni di testo, così un documento revisionato mantiene non solo le sue forme ma anche i metadati del flusso di lavoro su cui fanno affidamento i revisori
Importare l'XFDF in un documento caricato
HotPDF importa l'XFDF analizzando l'XML, creando una nuova annotazione per ogni elemento tramite NewLoadedAnnotation, collegandola alla pagina indicata dall'elemento e restituendo il numero di annotazioni aggiunte. Il flusso di lavoro è simmetrico rispetto all'esportazione: carica il PDF di base, chiama ImportLoadedAnnotationsFromXFDF con il file del revisore, quindi salva il documento caricato per rendere persistenti le nuove marcature. Se il file è mancante o l'XML non viene analizzato, la funzione restituisce zero e il documento caricato non viene toccato
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;
Poiché ogni elemento XFDF specifica il proprio indice di pagina, le annotazioni arrivano sulle pagine per cui sono state create anche quando si importano diversi file in sequenza, il che rende sicuro raccogliere i commenti di più revisori sullo stesso documento caricato prima di un unico salvataggio. L'esempio seguente unisce le annotazioni di due revisori in un'unica copia. Per la creazione e la modifica degli oggetti annotazione nel codice anziché per lo scambio come file, vedi come HotPDF crea e modifica gli oggetti annotazione PDF direttamente da 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;
Cosa completa correttamente il ciclo e cosa no
HotPDF completa il ciclo dei sottotipi di annotazione che trovano collocazione in ISO 19444-1, e salta deliberatamente i restanti per evitare di emettere qualcosa che un lettore potrebbe interpretare in modo errato. L'insieme supportato comprende i tipi di markup che dominano il lavoro di revisione reale: note di testo, testo libero, linea, quadrado, cerchio, poligono, polilinea, i quattro tipi di markup del testo (evidenziazione, sottolineatura, barrato e ondulato), timbro, tratto penna e accento circonflesso, oltre ad allegato di file, suono, redazione e collegamento, per un totale di diciotto sottotipi. Un'annotazione il cui sottotipo non rientra in questo elenco viene tralasciata all'esportazione e, poiché viene saltata anziché scritta vuota, non incrementa il conteggio restituito dalla funzione
Il rich text è l'avvertimento onesto. HotPDF conserva il corpo di <contents-richtext> in modo che il testo stilizzato e il contenuto semplice compiano il viaggio, ma l'XFDF trasporta il testo e il markup dello stile del commento, non un appearance stream renderizzato, quindi l'applicazione ricevente ridisegna il popup con i propri font e layout anziché riproduco i pixel esatti di HotPDF. Considera il round-trip come fedele al contenuto e all'intento, non al rendering sullo schermo al livello del pixel. Se il tuo contenuto stilizzato si trova nei dati del modulo XFA anziché nei flussi di annotazione, le regole differiscono, e la sezione su come HotPDF gestisce XFA exData, rich text e collegamenti ipertestuali copre questo percorso separato
La gestione a livello di carattere è più rigorosa di quanto sembri, ed è esattamente ciò che desideri. HotPDF applica le regole di escaping della clausola 5.8.2 di ISO 19444-1 quando scrive il testo, codificando i caratteri significativi per l'XML e i byte di controllo in modo che un commento contenente una e commerciale, una parentesi angolare o un'interruzione di riga generi un XML ben formato che qualsiasi analizzatore conforme accetta, e inverte le stesse regole all'importazione. Ecco perché una nota incollata da un foglio di calcolo, punteggiatura inclusa, ritorna intatta anziché corrompere il file
Lo scambio di annotazioni è una parte di ciò che fa l'API per i documenti caricati, e si compone con il resto: importa l'XFDF di un revisore, regola le pagine o modifica i metadati del documento, appiattisci o riassegna le autorizzazioni al file, quindi esporta un nuovo XFDF per il ciclo successivo. Tutto questo viene fornito con HotPDF Component standard per Delphi e C++Builder, il cui riferimento documenta la copertura completa del sottotipo di annotazione e le funzioni XFDF dei dati modulo associate