ComparePdfSemantics vergleicht Annotationen und AcroForm-Widgets unabhängig vom Seitenrendering; Formularwerte können sich bei identischen Darstellungspixeln ändern
Übergeben Sie TPdfDiffPagePairs aus der Seitenausrichtung oder eine explizite Zuordnung; nil verwendet Positionspaare; explizite Zuordnungen müssen beide Dokumente genau einmal abdecken, mit -1 für eine fehlende Seite
Die Identität einer Annotation folgt ihrem /NM-Namen, die eines Widgets dem vollständig qualifizierten Feldnamen; sie gilt innerhalb der zugeordneten Seite und Elementart
Fehlende und wiederholte Namen, auch mehrere Widgets eines Felds auf derselben Seite, werden mit expliziter Begründung als psckAmbiguous gemeldet; die Reihenfolge im Annotationenarray bestimmt keine Identität
Das unterstützte Profil vergleicht Strings, Flags, Farben, Deckkraft, Rahmen, Markierungen, Linien-, Vertex- und Freihandgeometrie, URI-Aktionen, Feldwerte, Auswahllabels und Optionen sowie Checkbox- und Radiobuttonzustände
CompareAppearanceStreams vergleicht optional den Inhalt von Annotationsdarstellungsstreams; standardmäßig deaktiviert
CompareAnnotations und CompareForms wählen die Elementarten; GeometryTolerance beträgt standardmäßig 0.001 Punkte im PDF-Benutzerraum
Hinzugefügte, entfernte und geänderte Elemente enthalten Eigenschaften und Grenzen davor/danach; BuildSemanticDiffOverlays liefert separate Vorher-/Nachherrechtecke mit Seiten- und Änderungsindizes
Alle Indizes beginnen bei null, Grenzen bleiben in PDF-Benutzerraumpunkten; wenden Sie Seitenrotation, Beschnitt und Viewporttransformation an, bevor Sie in ein Bitmap zeichnen
Seiten werden mit unabhängigen nativen Handles geladen, erhalten aktuelle Seite und Formularfokus des Aufrufers und lösen keine Formularaktionen aus
Das Profil umfasst keine Felder ohne Widget, beliebigen eigenen Dictionaries, eingebetteten Dateien, Skriptaktionen oder Nicht-URI-Ziele; XFA-Vergleich wird explizit abgelehnt
Standardlimits sind 10,000 Seitenpaare, 4,096 untersuchte Elemente, 4,096 Änderungen, 1 MiB pro String, 16 MiB Strings insgesamt und 16,777,216 Vergleiche; ein erschöpftes Budget verwirft unvollständige Ergebnisse
Complete unterscheidet einen vollständigen erfolgreichen Vergleich von einem abgelehnten; Änderungen können explizit mehrdeutige Identitäten enthalten, prüfen Sie daher AmbiguousCount vor einer endgültigen Elementzuordnung
Die reale Delphi/FPC-Win32/Win64-Abnahme umfasst 92 Assertions pro Ziel, darunter gespeicherte/wiedergeöffnete Dokumente, Wertänderungen bei identischen Pixeln, Unicode-Identität, Seitenverschiebung, Mehrdeutigkeit und Budgets
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;