PDFium Delphi Component Docs

Comparação semântica de anotações e formulários

ComparePdfSemantics compara propriedades de anotações e de widgets AcroForm de forma independente da renderização da página; os valores de formulário podem mudar mesmo quando os píxeis da aparência permanecem idênticos

Passe TPdfDiffPagePairs do alinhamento de páginas ou um mapeamento explícito; nil seleciona pares posicionais, e mapeamentos explícitos têm de cobrir os dois documentos exatamente uma vez, usando -1 para o lado em falta

A identidade de anotação usa o seu nome /NM, e a identidade de widget de formulário usa o nome de campo totalmente qualificado; a identidade tem como âmbito a página mapeada e o tipo de item

Nomes em falta e nomes repetidos, incluindo vários widgets de um mesmo campo na mesma página, são comunicados como psckAmbiguous com um motivo explícito; a ordem do array de anotações não determina a identidade

O perfil suportado compara strings, flags, cores, opacidade, bordas, markup, geometria de linha, vértice e tinta, ações URI, valores de campo, rótulos de escolha e opções selecionadas, e estado de checkbox ou radio

CompareAppearanceStreams compara opcionalmente o conteúdo dos streams de aparência das anotações; por predefinição está desativado

CompareAnnotations e CompareForms selecionam os respetivos tipos de item; GeometryTolerance assume por predefinição 0.001 pontos do user space PDF

Itens adicionados, removidos e alterados incluem propriedades e limites de antes/depois; BuildSemanticDiffOverlays devolve retângulos separados de antes/depois com índices de página e de alteração

Todos os índices são de base zero e os limites permanecem no user space PDF, em pontos; aplique a rotação, o crop e a transformação de viewport da página antes de pintar num bitmap

As páginas são carregadas com handles nativos independentes, preservando a página atual e o foco de formulário do chamador e evitando ações de formulário

O perfil exclui campos que não sejam widgets, dicionários personalizados arbitrários, ficheiros incorporados, ações de script e destinos que não sejam URI; a comparação XFA é explicitamente recusada

Os limites predefinidos são 10,000 pares de páginas, 4,096 itens varridos, 4,096 alterações, 1 MiB por string, 16 MiB de strings no total e 16,777,216 comparações; esgotar um orçamento recusa a saída incompleta

Complete distingue uma comparação bem-sucedida e completa de uma comparação recusada; as alterações dela podem incluir identidades explicitamente ambíguas, por isso inspecione AmbiguousCount antes de tratar os resultados como uma correspondência definitiva de itens

A aceitação real em Delphi/FPC Win32/Win64 cobre 92 asserções por alvo, incluindo documentos guardados/reabertos, alterações de valor com píxeis idênticos, identidade Unicode, movimento de páginas, ambiguidade e orçamentos

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

Declarações 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;