【问题标题】:Rename PDF embedded font重命名 PDF 嵌入字体
【发布时间】:2019-02-20 08:38:06
【问题描述】:

我正在使用 ghostscript 来合并 PDF 文件。但是偶尔嵌入的字体名称会在不同文件之间发生冲突,ghostscript会选择一个子集,合并后其他同名子集中的部分字符无法渲染。

为了解决这个问题,我想添加一个预处理阶段,为每个文件重命名嵌入字体,新名称由我的逻辑生成。

Linux下的解决方案是首选。

附:我已经评估了其他合并 pdf 的工具(pdfbox、pdfjam、pdftk、pdfunite、qpdf),但看起来它们都没有识别相同的图像,并且合并的 PDF 很大。 GhostScript 仅在多个输入文件中为完全相同的图像保留 1 个对象,它适合我的场景。


阅读@KenS 的回复后更新

GhostScript 版本:9.18

PDF 创建者:

  • xelatex:XeTeX 3.14159265-2.6-0.99998(TeX Live 2017)
  • xdvipdfmx:DVIPDFMx 项目团队的版本 20170318,针对 TeX Live 进行了修改。

2个带有冲突字体名称的PDF的输出:

$ gs -q -dSAFER -dBATCH -dNOPAUSE -dPDFSETTINGS=/prepress -sDEVICE=pdfwrite -sOutputFile=merged.pdf 1.pdf 2.pdf
GPL Ghostscript 9.18: Missing glyph CID=120, glyph=0078 in the font BLTQUA+LMRoman9-Regular . The output PDF may fail with some viewers.
GPL Ghostscript 9.18: Missing glyph CID=117, glyph=0075 in the font BLTQUA+LMRoman9-Regular . The output PDF may fail with some viewers.
GPL Ghostscript 9.18: Missing glyph CID=118, glyph=0076 in the font BLTQUA+LMRoman9-Regular . The output PDF may fail with some viewers.
GPL Ghostscript 9.18: Missing glyph CID=116, glyph=0074 in the font BLTQUA+LMRoman9-Regular . The output PDF may fail with some viewers.

嵌入字体:

$ pdffonts 1.pdf
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
ITLHBL+LMRoman10-Regular-Identity-H  CID Type 0C       Identity-H       yes yes yes      7  0
BLTQUA+LMRoman9-Regular-Identity-H   CID Type 0C       Identity-H       yes yes yes      9  0
MHRCBY+LMRoman8-Regular-Identity-H   CID Type 0C       Identity-H       yes yes yes     12  0

$ pdffonts 2.pdf
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
ITLHBL+LMRoman10-Regular-Identity-H  CID Type 0C       Identity-H       yes yes yes      7  0
BLTQUA+LMRoman9-Regular-Identity-H   CID Type 0C       Identity-H       yes yes yes      9  0
MHRCBY+LMRoman8-Regular-Identity-H   CID Type 0C       Identity-H       yes yes yes     12  0

字体名称完全相同。因为我使用 xelatex 以编程方式生成模式中的 PDF,所以字体的对象 id 完全相同。而且 GhostScript 认为来自 2 个文件的 BLTQUA+LMRoman9-Regular 字体是同一个子集,并在处理时抱怨。

正如@KenS 建议的那样,我让 GhostScript 为每个 PDF 生成一个新文件。

Ghostscript 将使用字体内容的 MD5 和来计算前缀。

然后检查字体:

$ pdffonts preproc_1.pdf 
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
JUVZAM+LMRoman8-Regular              CID Type 0C       Identity-H       yes yes yes     22  0
DCQLFZ+LMRoman9-Regular              CID Type 0C       Identity-H       yes yes yes     17  0
YAKIEH+LMRoman10-Regular             CID Type 0C       Identity-H       yes yes yes     13  0

$ pdffonts preproc_2.pdf 
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
JUVZAM+LMRoman8-Regular              CID Type 0C       Identity-H       yes yes yes     22  0
EQFACS+LMRoman9-Regular              CID Type 0C       Identity-H       yes yes yes     17  0
YAKIEH+LMRoman10-Regular             CID Type 0C       Identity-H       yes yes yes     13  0

现在,很明显LMRoman9-Regular 不是相同的子集(尽管仍然具有相同的对象 id),这不会再混淆 GhostScript。

【问题讨论】:

    标签: pdf ghostscript


    【解决方案1】:

    [插入关于 Ghostscript 不合并 PDF 文件这一事实的通常免责声明]

    请注意,当创建应用程序在选择嵌入字体名称的前缀方面做得不好时,这实际上只是一个问题。实际上,错误在于 PDF 创建者。

    您尚未说明您使用的是哪个版本的 Ghostscript。最新版本的 Ghostscript 使用字体名称和 PDF 对象编号来尝试提供更大程度的唯一性。所以只有当两个PDF文件中的名称对象编号相同时,字体才会发生冲突,这种可能性较小。

    如果这仍然是个问题,一个实用的解决方案是通过 Ghostscript 和 pdfwrite 设备传递每个原始 PDF 文件,以生成许多新的 PDF 文件。在新 PDF 文件中创建字体时,Ghostscript 将使用字体内容的 MD5 和来计算前缀。虽然不是绝对牢不可破,但两个不同子集的内容产生相同 MD5 哈希的可能性非常低。

    然后,您可以安全地处理新创建的 PDF 文件,而不会有不同字体具有相同名称和对象编号的真正风险。

    如果您坚持自己重命名,您可能只需在 PDF 文件中查找 XXXXX+FontName 的名称即可。您可以修改 5 个字母的前缀并重写文件。

    我不记得字体对象是否可以存储在压缩对象流中,如果可以的话,这会大大增加问题,因为您必须解压缩流,修改数据,重新压缩它,而且很可能修改外部参照表,因为重新压缩的流不太可能与原始流的长度相同。

    【讨论】:

    • 我将工具和实验结果更新到了原帖。使用默认配置的 xelatex 生成的 PDF 中没有纯文本 XXXXX+FontName 模式。我觉得 GhostScript 字体前缀算法已经足够好了,应用到我的流程中也很简单。如果有一天我在 MD5 碰撞上不走运,我会考虑对象编辑方法。
    猜你喜欢
    • 1970-01-01
    • 2014-08-13
    • 1970-01-01
    • 2010-10-12
    • 2015-02-16
    • 2014-12-17
    • 1970-01-01
    • 2016-08-29
    • 2013-10-08
    相关资源
    最近更新 更多