AcroForm 关系缓存

HotPDF 维护一个文档本地的双向索引,覆盖终端 AcroForm 字段、限定字段名、widget 批注、widget 序号和页面位置

查找行为

首次构建后,字段索引和限定名称查找使用直接数组和不区分大小写的开放寻址名称映射

父字段可以提供继承的 /FT、/Ff 和 /Opt 条目而不必是终端字段;group.a 和 group.b 等命名的子字段仍保持为各自独立的已索引字段

无论字段与 widget 共用一个字典还是各自使用字典,命名的子字段都会与未命名的 widget 子字段区分开

GetLoadedFormFieldWidgetPageIndex 将一个 widget 序号解析为其页面,而 GetLoadedFormFieldIndexForAnnotation 将页面批注映射回其字段和 widget 序号

批注数组成员关系优先于 widget 的 /P 条目,对于格式错误的重复成员关系,按文档顺序第一个匹配的页面生效

从 /AcroForm /Fields 中省略的 widget 会作为孤立项建立索引用于诊断,但不会作为合成表单字段暴露

构建与变更

缓存通过一次字段树遍历和一次页面批注遍历惰性构建

已加载字段的创建会增量扩展有效缓存,而字段删除、重命名、widget 移动、批注删除、合并注册、XFA 字段合并和页面表变更会在对象图改变前使缓存失效

下一次关系查询会从当前对象图重建,包括 /P 条目缺失的 widget

删除一个末端子字段会同时删除其控件和字段树条目,兄弟字段及其继承设置保留不动

通过原始对象 API 更改 AcroForm、字段、widget、页面 /Annots、/Parent、/Kids 或 /P 字典之后,请调用 InvalidateLoadedFormRelationshipCache

性能与所有权

名称映射和对象映射把加载因子保持在二分之一以下,热查找可提供预期的常数时间性能

回归门会构建 10,000 个已加载字段,证明线性遍历遥测,并要求在 Win32 和 Win64 上重复名称查找至少比冷构建加查找快 100 倍

缓存存储非拥有的对象指针,已加载文档对象图的访问仍由调用方串行化

另请参阅: GetLoadedFormFieldWidgetPageIndex, GetLoadedFormFieldIndexForAnnotation, InvalidateLoadedFormRelationshipCache, GetLoadedFormRelationshipCacheStatistics