摘要
本文档记录了 PPTX 保真度问题,该问题最初看起来像是布局错误,
但实际上是由不完整的字体和文本样式解析引起的。
可见的症状是多个幻灯片上的文本块,尤其是幻灯片 4 的"SKILLS"区域,
与 PowerPoint 不匹配:
- 窄标签换行方式不同
- 标题徽章的大小和粗细不同
- 即使文本框坐标正确,某些文本在视觉上也会发生偏移
根本原因不是硬编码的幻灯片几何形状。真正的问题是
office2pdf 没有像 PowerPoint 那样解析 PPTX 文本样式。
问题
PowerPoint 文本格式不仅仅由直接的 run 属性决定。
对于文本框,有效的样式可能来自多个 OOXML 层级:
a:rPr中的直接 run 属性a:pPr中的段落属性a:lstStyle中的文本主体默认值a:defPPr中的默认段落属性a:lvlNpPr中特定级别的段落属性a:defRPr中的默认 run 属性- 主题字体引用,如
+mj-lt/+mn-lt
在修复之前,PPTX 解析器主要使用直接的 a:rPr 和 run 上直接的
a:latin 值。这是不完整的。
结果如下:
- 缺少直接字体设置的 run 丢失了继承的字体族、大小、颜色和粗细
- 使用
lstStyle默认值的文本框渲染的样式比 PowerPoint 弱 - 由于有效的字体度量错误,换行出现差异
在回退选择方面还存在第二个问题:
- 回退顺序过于激进地优先考虑"字体源排名"
- 这导致 Office 管理的字体(如
Malgun Gothic)的优先级高于
Pretendard的度量首选替代列表 - 在这台机器上,这比使用
Apple SD Gothic Neo产生的换行效果更差
为什么 PowerPoint 看起来正确
受影响的演示文稿不仅仅依赖主题字体。它在幻灯片 XML 中包含显式的
字体信息,如 Pretendard、Pretendard SemiBold 及相关变体。
PowerPoint 应用:
- 直接的 run 格式
- 继承的
lstStyle默认值 - 跨
latin、ea和cs的脚本感知字体解析 - 当确切字体不可用时的本地回退行为
office2pdf 缺少了部分继承链,因此生成的 PDF 出现了差异,
尽管原始 PPTX 在 PowerPoint 中渲染正确。
修复方案
1. 解析文本主体样式继承
在 PPTX 解析器中添加了文本主体默认模型,使文本框能够从
a:lstStyle 继承样式。
实现:
- 引入
PptxTextBodyStyleDefaults - 引入
PptxTextLevelStyle - 解析
a:lstStyle、a:defPPr、a:lvlNpPr和嵌套的a:defRPr - 在应用直接的段落/run 覆盖之前,合并继承的段落和 run 样式
- 从
a:latin、a:ea和a:cs应用字体,而不仅仅是直接的a:latin
这使得文本框的行为更接近 PowerPoint 的有效样式模型。
2. 保留度量回退顺序
对于 Pretendard 等已知字体族的回退选择,现在优先保留替换表中
与度量兼容的顺序,仅将源排名用作次要的判定因素。
这意味着:
- 首选的替代字体族顺序是稳定的
- Office 管理的字体不再仅仅因为是从 Office 路径发现而自动优先于
更好的度量匹配项 - 实际的演示文稿现在回退到
Apple SD Gothic Neo而不是Malgun Gothic
涉及的文件
crates/office2pdf/src/parser/pptx.rscrates/office2pdf/src/render/font_subst.rscrates/office2pdf/src/render/typst_gen.rs
验证
修复通过三种方式进行了验证:
- 对
lstStyle默认 run 继承进行单元测试 - 在 Office/系统字体混合环境下对回退顺序进行单元测试
- 重新转换实际的 PPTX 演示文稿并进行手动视觉检查
修复后的观察结果:
- 幻灯片 4 的"SKILLS"标签不再像之前那样换行
- 徽章/标题样式更接近 PowerPoint
- 重新生成的 PDF 为
Pretendard回退嵌入了Apple SD Gothic Neo变体,
而不是Malgun Gothic
剩余已知差距与文本继承无关:
- 幻灯片 17 仍然会警告不支持的
hdphoto1.wdp
关键经验
当 PPTX 渲染不匹配看起来像文本框位置问题时,不要首先假设坐标错误。
在 PowerPoint 中,不正确的字体解析通常会变成布局问题:
- 不同的字体族
- 不同的粗细
- 不同的继承大小
- 不同的行距
即使文本框几何形状正确,这些差异也会改变换行和视觉对齐。