PPT字体颜色为什么改了却没报:主题色与RGB的三组对照实验
在做PPT修订审阅时,“文字内容相同”并不意味着“文字呈现相同”。标题由蓝色变为红色,可能是品牌模板切换,也可能是强调方式变化。如果差异工具只保存显式RGB,使用主题色的文档就容易留下盲区。
这次我用PPT-diff的固定提交 db6c75892650854abf663c91b66ead486fde1299 做了一个很小的实验:一页空白幻灯片、一个名字唯一的文本框、一个run,保持文字、位置、大小与段落结构相同,只更改字体颜色的设置方式。所有输入都是脚本新建的测试文件,没有读取业务PPT,也没有修改上游代码。
先控制住和问题无关的因素
字体检测问题很容易和run拆分、形状配对或页面匹配混在一起。为此,我没有使用复杂模板、组合形状或多个相同名字的文本框,也没有在字符串中间单独加粗。测试文字固定为“Theme color verification”,每份文档只有一个文本run。
环境是Windows、Python 3.12.14和python-pptx 1.0.2。测试分成三组:同一主题色自比较;从主题色accent1换成accent2;从显式RGB 4F81BD换成C0504D。后一组使用与模板中两种主题色相同的基础RGB值,以检查工具是否完全不支持颜色检测。
结果是表示方式不同,检测能力也不同
| 对照 | font_changes | 观察 |
|---|---|---|
| accent1与自身 | 0 | 没有字体修改 |
| accent1改为accent2 | 0 | 主题字体颜色修改未被报告 |
| 显式4F81BD改为C0504D | 1 | 正常报告颜色差异 |
这里的font_changes是工具摘要中“存在字体变化的页面数”,不是文档内变化字符的个数。两组主题色比较的页面状态均为moved,这是仓库已经记录的另一项页面状态问题;本次不能因此宣称整页报告完全没有输出。具体缺失的是字体颜色差异。
我另外打开合成PPTX里的XML进行核对。旧版run包含schemeClr,引用值为accent1;新版对应值为accent2。同一模板的theme1.xml中,accent1是4F81BD,accent2是C0504D。因此,这不是两个主题引用恰好对应同一RGB的情况。文件比较前后的SHA256也保持一致,解析过程没有把合成输入改写。
主题引用不是一个直接写下的RGB
python-pptx的官方文档分别给出了font.color.theme_color和font.color.rgb两种设置方法。前者保留对主题的引用,后者直接设置RGB;直接写RGB的文字不会随主题色变化而同步改变。这种差别对编辑器有用,对差异检测也同样重要。
下面的示例仅生成两份临时文件,适合在测试目录中验证,不需要已有PPT或PowerPoint进程:
from pathlib import Path
import tempfile
from pptx import Presentation
from pptx.enum.dml import MSO_THEME_COLOR
from pptx.util import Inches
work = Path(tempfile.mkdtemp(prefix="theme-color-demo-"))
for name, color in (("old", MSO_THEME_COLOR.ACCENT_1),
("new", MSO_THEME_COLOR.ACCENT_2)):
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6])
box = slide.shapes.add_textbox(Inches(1), Inches(1), Inches(5), Inches(1))
box.name = "OneUniqueTextBox"
run = box.text_frame.paragraphs[0].add_run()
run.text = "Theme color verification"
run.font.color.theme_color = color
prs.save(work / (name + ".pptx"))
在被测解析器中,字体提取函数尝试读取font.color.rgb,并用一个try/except忽略异常。主题色不是这种显式RGB表示,读取失败后,数据对象的font_color_hex没有值;序列化又省略None字段。结果是两份字体信息都只剩相同的text字段。比较器收到的数据已经丢失差别,再准确的相等判断也无法恢复它。
修复时先区分“相同”和“未知”
一种可执行的改进方向,是为颜色保存有类型的描述:未直接指定、显式RGB、主题引用,以及解析失败。主题引用可以记录引用名称和原始变换信息。先把accent1到accent2的变化如实报告,就比把两次读取失败都视为没有颜色更可靠。
但这还不是完整的最终渲染色解析。假设主题引用仍然是accent1,主题调色板却变了,单纯比较引用名称也会漏掉变化。母版继承、颜色映射和亮度变换同样需要单独处理。暂不支持的路径应显示“未解析”,不能用一个固定颜色占位后宣称一致。
如果实现要解析最终颜色,测试就应该沿着“run引用→对应主题→颜色变换”的路径检查每个阶段,而不是只检查最终报告是否生成成功。本次没有验证所有这些路径,也没有运行PowerPoint像素渲染,结论限定在直接设置的主题字体颜色。
用控制组给验收结果留证据
回归测试可以先保留本次三组输入,再补充主题调色板改变、亮度改变、无直接颜色、主题色与显式RGB混用等情况。每组应同时保留输入XML、解析后的结构和最终摘要,才能区分“源文件没写进去”“解析丢了字段”和“比较器没使用字段”。
对使用差异工具的人,这次实验也给出一个实际提醒:看到字体变化为0时,先确认工具支持文档所用的颜色表示。对工具作者,异常处理的重点不只是让程序继续运行,还要把“无法取得值”留在输出中,避免用户把未知结果当作已经核验的一致结果。
参考:python-pptx官方《Working with text》中的字符格式部分,以及《DrawingML objects》中ColorFormat的类型、RGB和主题色属性说明。本文实验代码和输入均为本次合成;没有把尚未测试的继承或渲染行为当作实测结论。
- 点赞
- 收藏
- 关注作者
评论(0)