表单计算依赖图

HotPDF 在已加载 AcroForm 的计算字段之上构建依赖图,因此值变更只会重算传递读取该值的计算,且重算顺序保证每个重算值对消费它的计算立即可见

图构建

THotPDF.BuildLoadedFormCalculationGraph 返回由调用方持有的快照。每个字段成为一个节点;每个注册到 /CO 的 Calculate 脚本都由 HPDFExtractSafeJavaScriptFieldReferences 静态分析,它读取安全子集脚本触及的字段名:AFSimple_Calculate("OP", ["a","b"]) 的带引号参数和 getField("x") 访问的带引号名称;字符串字面量会被跳过,因此文字性提及不会被当作引用

THPDFFormCalcGraph.ResolveLinks 将这些名称解析为 source → dependent 边,并用拓扑排序排列目标。处于依赖环上的字段改为保持 /CO 文档顺序,与完整重算的单遍语义一致;已更改的字段从不会重新计算自己的脚本,因此环不会来回震荡,用户写入的值总是获胜。未匹配任何字段的源名称通过 UnresolvedFieldNameCount 报告且不产生边,与运行时解析器的行为一致

增量重算

RecalculateLoadedFormFieldsIncremental 只求值给定变更字段的受影响闭包。通过 SetFormFieldValue 和 SetLoadedFormFieldValueByName 的写入累积脏集合;无参重载从该集合重算,因此 FDF 或 XFDF 导入后接一次增量遍历即可刷新每个依赖计算而不触碰无关计算。两个重载以及完整 RecalculateLoadedFormFields 遍历之后都会消费脏集合

PDF.LoadFromFile('Order.pdf');
PDF.SetLoadedFormFieldValueByName('qty', '3');
PDF.SetLoadedFormFieldValueByName('price', '19.5');
// Recomputes subtotal and total only, chained in one pass
PDF.RecalculateLoadedFormFieldsIncremental(['qty', 'price']);

图检查

该图暴露每个字段的计算状态(GetNode)、完整求值序列(AllTargets)、受影响闭包(AffectedTargets)、位于环上的目标数(CyclicTargetCount)以及未解析的源名称,因此工具可以预览一次编辑将精确触发哪些计算