PDFium Delphi Component Docs

Comparación semántica de anotaciones y formularios

ComparePdfSemantics compara propiedades de anotaciones y widgets AcroForm independientemente del renderizado de páginas; los valores de formulario pueden cambiar aunque los píxeles de apariencia sean idénticos

Pase TPdfDiffPagePairs obtenido de la alineación de páginas o un mapeo explícito; nil selecciona pares por posición, y los mapeos explícitos deben cubrir ambos documentos exactamente una vez, usando -1 para el lado ausente

La identidad de una anotación usa su nombre /NM, y la de un widget de formulario usa el nombre completo del campo; la identidad se limita a la página mapeada y al tipo de elemento

Los nombres ausentes o repetidos, incluidos varios widgets del mismo campo en una página, se informan como psckAmbiguous con una razón explícita; el orden del arreglo de anotaciones no determina la identidad

El perfil compatible compara cadenas, flags, colores, opacidad, bordes, markup, geometría de líneas, vértices y tinta, acciones URI, valores de campo, etiquetas y opciones seleccionadas, y el estado de casillas o botones de opción

CompareAppearanceStreams permite comparar el contenido de los flujos de apariencia de anotaciones; está deshabilitado de forma predeterminada

CompareAnnotations y CompareForms seleccionan los respectivos tipos de elemento; GeometryTolerance tiene un valor predeterminado de 0.001 puntos del espacio de usuario PDF

Los elementos agregados, eliminados y modificados incluyen propiedades y límites anteriores y posteriores; BuildSemanticDiffOverlays devuelve rectángulos separados de antes y después, con índices de página y cambio

Todos los índices tienen base cero y los límites siguen en puntos del espacio de usuario PDF; antes de dibujarlos en un bitmap, aplique la rotación de página, el recorte y la transformación del viewport correspondientes

Las páginas se cargan con handles nativos independientes, conservando la página actual y el foco de formulario del llamador, y evitando acciones de formulario

El perfil excluye campos sin widget, diccionarios personalizados arbitrarios, archivos incrustados, acciones de script y destinos que no sean URI; la comparación XFA se rechaza explícitamente

Los límites predeterminados son 10,000 pares de páginas, 4,096 elementos examinados, 4,096 cambios, 1 MiB por cadena, 16 MiB de cadenas en total y 16,777,216 comparaciones; agotar un límite rechaza la salida incompleta

Complete distingue una comparación completa exitosa de una rechazada; los cambios pueden incluir identidades explícitamente ambiguas, por lo que hay que revisar AmbiguousCount antes de considerar el resultado una correspondencia definitiva entre elementos

La aceptación real con Delphi/FPC en Win32/Win64 cubre 92 aserciones por destino, incluidos documentos guardados y reabiertos, cambios de valor con píxeles idénticos, identidad Unicode, movimiento de páginas, ambigüedad y límites

Options := TPdfSemanticDiffOptions.Default;
if not ComparePdfSemantics(BeforePdf, AfterPdf, PagePairs, Options, Report) then
  raise EPdfError.Create(Report.ErrorMessage);
Overlays := BuildSemanticDiffOverlays(Report);

Declaraciones públicas

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;