重命名PDF嵌入字体

时间:2018-09-16 02:30:17

标签: pdf ghostscript

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

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

首选Linux下的解决方案。

P.S。我回避了其他工具来合并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感到困惑。

1 个答案:

答案 0 :(得分:2)

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

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

您尚未说明要使用的Ghostscript版本。最新版本的Ghostscript使用字体名称和PDF对象编号来尝试并赋予更大的唯一性。因此,只有两个PDF文件中的名称对象编号相同时,字体才会发生冲突。

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

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

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

如果字体对象可以存储在压缩的对象流中,我就不会想起来,否则它们将大大增加问题的发生,因为您必须解压缩流,修改数据,重新压缩它,并且很可能修改外部参照表,因为重新压缩的流不太可能与原始长度相同。