添加 FPdfStyledEdit,并提供 IPdfRegexEngine,即可针对原生顶层文本对象规划和执行替换
PlanStyledPdfRegexReplacements 捕获可重现的源快照,按页面和对象顺序连接实际 Unicode 字形,再将匹配映射回稳定对象锚点;不计入提取时额外生成的空格和换行
ExecuteStyledPdfReplacements 修改独立加载的文档前,先验证快照 SHA-256、当前源身份、锚点和互不重叠的区间
源身份基于可重现的序列化,包含规范化时间戳和标识,不以原始文件字节为准;计划保存实际快照字节及其 SHA-256
尽可能复用原生字体、字号、颜色和矩阵;跨对象或跨页替换保留首对象样式,删除后续对象中被消耗的字符,同时保留剩余文本和页面顺序
原生 Unicode 无法重现时,FallbackFontName 明确指定标准 PostScript 后备字体;ForceFallbackFont 可直接请求此路径
后备处理保留绘制顺序、矩阵、渲染模式、填充和描边属性;裁剪、透明、带标记或 tagged 的对象会被拒绝,避免悄悄丢失图形语义
文本宽于源边界时,若矩阵正立且无剪切,可水平缩小;MinHorizontalScale 默认为 0.5,较窄的替换文本保留原矩阵
该工作流支持单行替换和受限水平适配,不遍历嵌套 Form XObjects,不重写 Tagged PDF 语义,也不进行段落重排
拒绝已签名或加密文档及 XFA;取消、过期计划、无效 UTF-16、不支持字体或预算耗尽均保留调用方文档
PreviewOnly 在 PreviewPdf 中返回独立重新打开的结果,不替换调用方文档;只有保存并重新打开后验证了字形提取和页数,成功提交才会替换文档
修改原生对象前,先将所有匹配组装为最终对象文本;只针对原始边界检查一次适配和最小缩放,防止重复匹配累计过度缩小
所有锚定编辑完成后,空替换文本会删除已完全消耗的文本对象;多项替换从后向前执行,保证较早的源偏移仍然有效
默认上限为 256 MiB 文档字节、10,000 页、100,000 个文本对象、16,777,216 个 UTF-16 单元和 100,000 次替换;文本扫描工作预算为 67,108,864 次原生字符访问及 UTF-16 规划复制单元
硬上限保持上述页面、对象、字符和替换限制,允许 512 MiB 文档字节和 1,073,741,824 次扫描访问,并将后备字体名称限制为 1,024 字节
报告包含源和输出 SHA-256、已应用替换/后备/缩放计数,以及每对象原始和最终文本及 PDF 用户空间点边界;页面和对象索引均为从零开始的源索引
替换操作不是安全擦除工作流;敏感内容及相关文档数据的移除应使用专门的擦除 API
Options := TPdfStyledEditOptions.Default; Plan := PlanStyledPdfRegexReplacements(Pdf, Pattern, Replacement, Engine, Options); Options.PreviewOnly := True; if not ExecuteStyledPdfReplacements(Pdf, Plan, Options, PreviewPdf, Report) then raise EPdfProduction.Create(Report.ErrorMessage);
type
TPdfStyledEditOptions= record
MaxDocumentBytes: Integer;
MaxPages, MaxTextObjects, MaxCharacters, MaxReplacements: Integer;
MaxTextScanWork: Int64;
MinHorizontalScale: Double;
FallbackFontName: AnsiString;
ForceFallbackFont: Boolean;
PreviewOnly: Boolean;
CancellationToken: IPdfCancellationToken;
class function Default: TPdfStyledEditOptions; static;
end;
TPdfStyledEditPlan= record
SourceSha256: string;
SourceBytes: TBytes;
Spans: TPdfStyledSpans;
Replacements: TPdfStyledReplacements;
end;
TPdfStyledObjectChange= record
PageIndex, ObjectIndex: Integer;
BeforeText, AfterText: WideString;
BeforeBounds, AfterBounds: TPdfRectangle;
HorizontalScale: Double;
FontFallback: Boolean;
end;
TPdfStyledObjectChanges= array of TPdfStyledObjectChange;
TPdfStyledEditReport= record
Succeeded, Cancelled, PreviewOnly: Boolean;
AppliedReplacementCount, FontFallbackCount, ScaledObjectCount: Integer;
SourceSha256, OutputSha256, ErrorMessage: string;
Changes: TPdfStyledObjectChanges;
end;
function PlanStyledPdfRegexReplacements(Pdf: TPdf;
const Pattern, Replacement: WideString; Engine: IPdfRegexEngine;
const Options: TPdfStyledEditOptions): TPdfStyledEditPlan;
function ExecuteStyledPdfReplacements(Pdf: TPdf;
const Plan: TPdfStyledEditPlan; const Options: TPdfStyledEditOptions;
out PreviewPdf: TBytes; out Report: TPdfStyledEditReport): Boolean;