跳到正文

ADR-0009:公共复杂文本、模板与受控导出 ​

  • 状态:已采纳
  • 日期:2026-10-14

静态 CFF 正文默认输出的决定已由 ADR-0101更新:普通字形支持原生 PDF 嵌入,复杂塑形/显式轮廓保持原路径。下文保留本阶段原始决定。

背景 ​

复杂脚本原来只能使用显式 OpenTypeText,普通语义段落、单元格和固定页区拒绝组合字符及双向文字。业务调用缺少模板数据绑定和执行控制;PDF 尚无归档、加密与外部签名入口。

决策 ​

默认 ParagraphLayouter 自适应选择原有简单路径或 JDK OpenType 路径。普通简单文字保留既有度量;需要塑形的文字和 CFF 字体在文本模块完成换行、双向运行、字形轮廓和来源映射。TextOutline 仅使用项目类型与不可变坐标集合;AWT 类型不进入布局结果。TextLine.atBaseline() 在分页时保留轮廓。显式注入 SimpleTextShaper 仍执行其严格契约。

绘制层把预定轮廓转换为路径,保留一次整行逻辑文字。PDF 的普通字形串使用 TJ 及定位修正,避免逐字独立文字对象与 ActualText 交错。此修复有 PDFium 样例证据,不代表全部阅读器的选择、搜索与无障碍能力。

字体集合必须显式选取成员,提取并重新计算 sfnt 校验,再走统一验证。静态 CFF 正文通过轮廓输出;可编辑 PDF 字段继续要求 TrueType。示例字体的许可、来源和哈希单独登记。

DocumentTemplate 位于 JDK-only 模型模块,只接受不可变模板节点和可快照的数据树。变量仅为点路径;条件要求布尔值;循环和集合表格受访问次数、深度、块、行、文字预算约束。不执行反射、脚本或网络访问。

ExecutionContext 使用同步调用范围内的 ThreadLocal 传递控制。它不启动线程,始终在 finally 恢复上层范围;嵌套任务同时观察外层取消和截止时间。检查点覆盖布局、文字换行、页输出和借用流写入。自定义组件和签名器须协作取消,调用期间不能强制抢占。原子文件入口先写同目录临时文件,成功后要求原子替换;不静默降级成非原子复制。

PDF 配置与外部 CMS 签名封装在 PDF 后端,公共签名不暴露 PDFBox。PDF/A-2b 首批仅支持显式 RGB ICC、嵌入字体的静态文档;拒绝交互及加密。签名回调接收准确 ByteRange 流,返回完整 detached CMS;证书链、私钥、可信时间戳及长期验证由调用方管理。

替代方案与验证 ​

继续仅用显式组件会使语义段落、页区和脚注缺少相同的文本能力。新增外部塑形器会扩大运行依赖,本批采用 JDK 路径并保留已验证的简单文字度量。显式逐层传递执行参数会改动全部组件 SPI,因此采用严格同步范围,禁止把其隐式传播到后台任务。

JUnit 验证来源、几何、边界、取消和失败保留文件;Poppler/PDFium 验证渲染;veraPDF 验证最终归档文件;OpenSSL 验证 CMS 完整性及篡改失败。证据见本地验收。

影响与限制 ​

新增中立轮廓会增加复杂文字的内存开销,仍受文字、行、路径预算控制。PDF 临时文件缓存只转移后端流缓冲,完整 Layout IR 和 Display List 仍在内存中。

本批没有引入 Java 运行依赖或额外模块。PDF/A 使用 veraPDF 独立验收,签名使用 OpenSSL 验证完整性及篡改失败;验证工具不进入制品。完整 PDF/UA 标签树、竖排、可变字体、行内图像、动态行内域、多浮动区与完整 DOCX 资源映射继续独立推进,见能力矩阵。