ComparePdfSemantics confronta proprietà delle annotazioni e dei widget AcroForm indipendentemente dal rendering della pagina; i valori dei form possono cambiare anche a parità di pixel dell'aspetto
Passare TPdfDiffPagePairs dall'allineamento delle pagine o una mappatura esplicita; nil sceglie coppie per posizione e le mappature esplicite devono coprire entrambi i documenti esattamente una volta, usando -1 per il lato mancante
L'identità di un'annotazione usa il nome /NM e quella di un widget il nome completo del campo; l'identità è circoscritta alla pagina mappata e al tipo di elemento
Nomi mancanti o ripetuti, inclusi più widget dello stesso campo sulla stessa pagina, vengono segnalati come psckAmbiguous con un motivo esplicito; l'ordine dell'array delle annotazioni non determina l'identità
Il profilo supportato confronta stringhe, flag, colori, opacità, bordi, markup, geometria di linee, vertici e ink, azioni URI, valori dei campi, etichette di scelta, opzioni selezionate e stato di checkbox o radio
CompareAppearanceStreams confronta opzionalmente il contenuto degli stream di aspetto delle annotazioni; è disabilitato per impostazione predefinita
CompareAnnotations e CompareForms selezionano i rispettivi tipi di elementi; GeometryTolerance vale per impostazione predefinita 0.001 punti nello spazio utente PDF
Elementi aggiunti, rimossi e modificati includono proprietà e limiti prima e dopo; BuildSemanticDiffOverlays restituisce rettangoli prima e dopo separati con indici di pagina e modifica
Tutti gli indici sono a base zero e i limiti restano nello spazio utente PDF, in punti; prima di disegnare su un bitmap applicare rotazione, ritaglio e trasformazione del viewport della pagina interessata
Le pagine vengono caricate con handle nativi indipendenti, mantenendo pagina corrente e focus del form del chiamante ed evitando azioni dei form
Il profilo esclude campi senza widget, dizionari personalizzati arbitrari, file incorporati, azioni script e destinazioni non URI; il confronto XFA è rifiutato esplicitamente
I limiti predefiniti sono 10,000 coppie di pagine, 4,096 elementi esaminati, 4,096 modifiche, 1 MiB per stringa, 16 MiB di stringhe totali e 16,777,216 confronti; esaurire un limite fa rifiutare l'output incompleto
Complete distingue un confronto completo riuscito da uno rifiutato; le modifiche possono includere identità esplicitamente ambigue, quindi controllare AmbiguousCount prima di trattare il risultato come un abbinamento definitivo
L'accettazione reale Delphi/FPC Win32/Win64 copre 92 asserzioni per destinazione, inclusi documenti salvati e riaperti, valori modificati con pixel identici, identità Unicode, spostamenti di pagine, ambiguità e limiti
Options := TPdfSemanticDiffOptions.Default; if not ComparePdfSemantics(BeforePdf, AfterPdf, PagePairs, Options, Report) then raise EPdfError.Create(Report.ErrorMessage); Overlays := BuildSemanticDiffOverlays(Report);
type
TPdfSemanticItemKind = (psikAnnotation, psikFormWidget);
TPdfSemanticChangeKind = (psckAdded, psckRemoved, psckChanged, psckAmbiguous);
TPdfSemanticSide = (pssBefore, pssAfter);
TPdfSemanticProperty = record
Name: string;
Value: WideString;
end;
TPdfSemanticProperties = array of TPdfSemanticProperty;
TPdfSemanticItem = record
Kind: TPdfSemanticItemKind;
Identity: WideString;
PageIndex, AnnotationIndex: Integer;
HasBounds: Boolean;
Bounds: TPdfRectangle;
Properties: TPdfSemanticProperties;
end;
TPdfSemanticPropertyChange = record
Name: string;
HasBefore, HasAfter: Boolean;
BeforeValue, AfterValue: WideString;
end;
TPdfSemanticPropertyChanges = array of TPdfSemanticPropertyChange;
TPdfSemanticChange = record
Kind: TPdfSemanticChangeKind;
ItemKind: TPdfSemanticItemKind;
Identity: WideString;
HasBefore, HasAfter: Boolean;
BeforeItem, AfterItem: TPdfSemanticItem;
Properties: TPdfSemanticPropertyChanges;
AmbiguityReason: string;
end;
TPdfSemanticChanges = array of TPdfSemanticChange;
TPdfSemanticOverlay = record
Side: TPdfSemanticSide;
PageIndex, ChangeIndex: Integer;
Kind: TPdfSemanticChangeKind;
Bounds: TPdfRectangle;
end;
TPdfSemanticOverlays = array of TPdfSemanticOverlay;
TPdfSemanticDiffOptions = record
CompareAnnotations, CompareForms, CompareAppearanceStreams: Boolean;
GeometryTolerance: Double;
MaxPagePairs, MaxItems, MaxChanges, MaxStringBytes: Integer;
MaxTotalStringBytes, MaxComparisons: Int64;
class function Default: TPdfSemanticDiffOptions; static;
end;
TPdfSemanticDiffReport = record
Complete: Boolean;
Changes: TPdfSemanticChanges;
AddedCount, RemovedCount, ChangedCount, AmbiguousCount: Integer;
ComparedItemCount: Integer;
ErrorMessage: string;
end;
// Indices are zero based. Nil PagePairs selects positional pairing. Explicit
// pairs must cover both documents exactly once; -1 denotes an absent side
// Identity is scoped to a mapped page and item kind. Missing names and repeated
// names (including repeated widgets of one field) are reported as ambiguous
// No rendering, focus changes, form actions, or positional identity guessing
// are performed. Pages are opened independently of the caller's current page
// The supported profile covers strings, flags, colors, opacity, borders,
// markup/line/vertex/ink geometry, URI actions, field values/options/checks,
// and optionally appearance streams. Arbitrary dictionaries, embedded files,
// script actions, non-URI destinations, and non-widget fields are not compared
function ComparePdfSemantics(BeforePdf, AfterPdf: TPdf;
const PagePairs: TPdfDiffPagePairs; const Options: TPdfSemanticDiffOptions;
out Report: TPdfSemanticDiffReport): Boolean;
// Bounds remain in PDF user space, in points. Transform with the destination
// page's rotation/crop/viewport rather than treating them as bitmap pixels
function BuildSemanticDiffOverlays(const Report: TPdfSemanticDiffReport):
TPdfSemanticOverlays;