跳到正文

ADR-0005:混合内容与基础表格 ​

2026-10-14 更新:本文保留初始决策背景。富文本、字体组缺字策略、分页控制、分节、合并表格与中文表单的扩展边界见 ADR-0007。

  • 日期:2026-10-14
  • 状态:已采纳,已实现基础范围;阶段三尚未全部完成。
  • 关联:ADR-0004、表格 API

背景 ​

段落分页已建立测量、页面分配、来源与绘制的职责边界。表格需要保持段落/表格混合顺序,并复用已有文本排版;单独保存无序表格列表会丢失文档顺序,也无法解释跨页来源。

决策 ​

  1. 增加封闭的 Block 和 LayoutFragment 类型,分别包含段落/表格及对应片段。Document.blocks() 与 LayoutPage.elements() 保存完整顺序,模型仍只依赖 JDK。当前封闭集合与尚未实现的外部组件扩展机制分开。
  2. 保留原段落构造入口及段落过滤视图。统一来源使用原始块索引;表格行列使用从 0 开始的索引,单元格文字保留局部 UTF-16 范围。此变更不承诺反射或二进制全面兼容。
  3. 首批只支持矩形纯文本单元格、固定/比例列宽、全表统一内边距及单元格字号、行距、对齐。表格至少有一行正文,不支持合并、嵌套、行拆页或横向分页。
  4. 固定列先扣除,比例列共享剩余宽度。所有单元格按净宽只换行一次,行高取最高单元格加上下内边距。行顶对齐,不自动缩小或裁切。
  5. 整行跨页,全部表头与至少一个正文行一起放置。续页复用已测量表头并标记重复。表头加任一正文行不能放入新页时立即失败,每个表格片段必须消费正文行。
  6. 保留原四参数预算入口,将历史 maxParagraphs 扩为顶层块预算;增加每表行列和全文单元格预算。生成行预算包含重复表头,原文码点只计一次。失败保留块、页、行、列、原文位置及原因。
  7. DocumentPainter 消费最终几何,绘制黑色正文、浅灰表头和内部细网格。PDF 后端不增加表格专用逻辑,不重新决定断行、行高或分页。不增加模块、依赖、字体或其他外部资源。

考虑的替代方案 ​

方案取舍
另建段落与表格列表API 改动少,但无法保存混合顺序及统一来源
一次布局一页并重新计算表头减少暂存数据,但重复塑形,难以保持来源和测量一致
自动拆分超高行可容纳更多输入,但需要明确单元格同步拆分、边框和来源契约,超出首批范围
把表格交给 PDFBox后端可直接画表,但破坏格式隔离和输出前验证能力

影响与兼容性 ​

布局仍保存完整不可变快照,并非流式写盘。表格会在分页前暂存全部单元格布局,受结构预算约束。后续内容驱动列宽、合并与组件化需要独立契约,不作为当前保证。

纯段落代码和几何保持原行为。处理混合文档的调用方必须使用完整块/片段入口;原段落索引在混合文档中代表块索引。原异常段落访问器作为块访问器别名保留。完整迁移规则见表格 API。

验证方式 ​

覆盖模型快照、矩形校验、列宽与内边距、最高单元格行高、多行表头、原始行唯一性、混合内容顺序、超高行及时失败、浮点边界、预算与行列错误上下文。

PDF 集成测试验证中英文行顺序、表头重复、元数据和字体。可执行示例由独立 Poppler 和 pypdf 解析、提取并逐页渲染检查。结果见表格验收。

后续 ADR-0006 开放 Block、新增组件片段并实现组件 SPI;本记录中的表格列宽、行高、来源及整行分页规则继续有效。