PDF编辑的复杂性:文字隐藏于绘图指令中
改一个单词,看似简单的操作,却是PDF编辑器中最为繁琐的过程。一位开发者投入数月时间创建PDF编辑工具,但最终却发现,大部分时间都在处理文本替换问题。他的最终认识是,PDF文件并不是保存文字内容,而是保存了大量的绘图指令。
在PDF文件中,没有“句子”的概念,存储的实际上是绘图指令。一行文字在PDF中的表现形式类似于:BT /F1 11 Tf 72 700 Td [(W) -30 (e) 15 (l) -20 (come)] TJ。这里的TJ数组将一个视觉上的单词拆解成了各个字母,并且包含了每个字母之间的字距微调,而整个文件中并不存在“Welcome”这一字符串,也没有段落、行以及“这些字形属于同一个词”的概念。所有的文本结构都是由解析PDF文件的程序所推断出来的。
因此,所谓的“查找替换”并非简单的字符串操作,而是需要从位置确定的字形中重建出逻辑文本,然后在重建的文本中查找目标单词,最后反推对应的绘图指令,删除原有内容并绘制新内容,同时还需确保新内容在视觉上与原内容无异。
要想实现无缝的文字替换,必须获取四个关键要素:原字体、字号、基线位置和颜色。然而,这四个要素都不是易于获取的。字号的获取并不只是Tf后面那个数字那么简单,文本矩阵的缩放会影响实际呈现效果。如果在代码中显示为Tf 1,但渲染时被放大了24倍,实际上显示的字号就是24磅。基线位置也极其重要,提升几点就会被肉眼察觉,即便字体和字号完全一致。颜色在扫描文档时尤其棘手,依据背景色参考,可能会导致在米黄色纸张上显示出白色块。
这位开发者采取的策略是:从周围文本区域推测所需的字体、字号和基线,加权计算中位数,只有在精确数据无法获取时才依赖这个估算值。而大部分错误都发生在这一步骤。
在替换学术论文中的文字时,他遇到了最痛苦的教训。每次尝试,文档中的文字都变成了错误的字体,例如,一篇使用衬线体的文档中却被插入了细无衬线体。尽管读者轻易就能识别出问题,他却始终无法再现这个错误。他自以为能够捕捉失败场景的测试文件通过了内嵌字体的检查,但在真实文档中依然失败。
最后,他决定直接从arXiv下载真实论文作为测试。结果同样不断失败,原因仅在一行代码中:let serif = low.contains("times") || low.contains("roman") || ... LaTeX嵌入的Times克隆字体叫NimbusRomNo9L,虽然其中字符有“Rom”,却并无“roman”一词,因此被误判为无衬线体,最终替换为Helvetica。而Computer Modern中的CMR10和CMBX12也面临同样的问题,均未能找到“roman”这个关键词。这种误命名假设还导致了字重检测的问题,使得Nimbus的粗体以“-Medi”命名,而非“-Bold”。
7月乘用车出口数据揭晓:奇瑞以19.9万辆名列第一 超越日系三巨头
“这里的健身环境非常好,教练们的指导也非常专业,每次训练都让我充满动力!”...
媒体报道:赵继伟因膝伤缺席亚运会名单,情况令人担忧
“这里的健身环境非常好,教练们的指导也非常专业,每次训练都让我充满动力!”...