ComparePdfSemantics는 페이지 렌더링과 독립적으로 주석 및 AcroForm 위젯 속성을 비교합니다. 외관 픽셀이 같아도 폼 값은 달라질 수 있습니다
페이지 정렬의 TPdfDiffPagePairs 또는 명시적 대응표를 전달하세요. nil은 위치별 짝을 선택하며 명시적 대응표는 두 문서를 각각 정확히 한 번씩 포함해야 합니다. 한쪽이 없으면 -1을 사용합니다
주석은 /NM 이름으로, 폼 위젯은 완전한 필드 이름으로 식별합니다. 식별 범위는 대응된 페이지와 항목 유형입니다
같은 페이지에서 한 필드의 여러 위젯을 포함해 이름이 없거나 중복되면 구체적인 이유와 함께 psckAmbiguous로 보고합니다. 주석 배열 순서로 식별하지 않습니다
지원 프로파일은 문자열, flags, 색상, 불투명도, 테두리, markup, line/vertex/ink 지오메트리, URI action, 필드 값, 선택 항목 라벨과 선택 상태, checkbox/radio 상태를 비교합니다
CompareAppearanceStreams로 주석 외관 스트림 내용도 비교할 수 있습니다. 기본값은 비활성입니다
CompareAnnotations와 CompareForms로 각 유형을 선택합니다. GeometryTolerance의 기본값은 PDF 사용자 공간의 0.001포인트입니다
추가, 삭제, 변경 항목에는 전후 속성과 경계를 포함합니다. BuildSemanticDiffOverlays는 페이지 및 변경 번호를 가진 별도의 전후 사각형을 반환합니다
모든 번호는 0부터 시작하며 경계는 PDF 사용자 공간의 포인트입니다. 비트맵에 그리기 전에 해당 페이지의 회전, crop, viewport 변환을 적용하세요
독립 네이티브 핸들로 페이지를 열어 호출자의 현재 페이지와 폼 포커스를 유지하고 폼 action을 피합니다
위젯이 아닌 필드, 임의 사용자 사전, 첨부 파일, script action, URI 이외 목적지는 대상에서 제외합니다. XFA 비교는 명시적으로 거부합니다
기본 상한은 10,000페이지 짝, 검사 항목 4,096개, 변경 4,096개, 문자열마다 1 MiB, 문자열 합계 16 MiB, 비교 16,777,216회입니다. 상한에 도달하면 불완전한 출력을 거부합니다
Complete는 성공한 전체 비교와 거부된 비교를 구별합니다. 전체 비교에도 명시적으로 모호한 식별이 포함될 수 있으므로 확정된 대응으로 사용하기 전에 AmbiguousCount를 확인하세요
실제 Delphi/FPC Win32/Win64 검증은 대상마다 92 assertions를 포함하며 저장/재열기, 같은 픽셀에서의 값 변경, Unicode 식별, 페이지 이동, 모호성, 상한을 확인합니다
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;