如果嵌入字体子集的名称相同,但这些子集的实际内容不同(包含不同的字形集) ,我已经看到会发生这种情况。
检查所有输入文件中使用的字体。为此使用 Poppler 的pdffonts
实用程序:
for i in input*.pdf; do
pdffonts ${i} | tee ${i}.pdffonts.txt
done
查找每个 PDF 中使用的字体名称。
我的理论/赌注是你看到不同的输入文件使用相同的字体名称(类似于 的名称BAAAAA+ArialMT
)。
用于子集字体的BAAAAA+
字体名称前缀应该是随机的(尽管官方规范对此不是很清楚)。然而,一些应用程序使用可预测BAAAAA+
的前缀,以 等开头CAAAAAA+
DAAAAA+
(OpenOffice.org 和 LibreOffice 因这一点而臭名昭著)。这意味着BAAAAA+
在每个使用至少一种子集字体的文件中都会使用前缀...
您的输入文件不使用完全相同的字符子集很容易发生。然而,使用相同的名称可能会使 Ghostscript 认为字体确实是相同的。它(错误地)“优化”合并的 PDF 并仅嵌入 2 个字体实例中的一个(都具有相同的名称,例如BAAAAA+Arial
)。但是,此实例可能不包括某些字形,这些字形是其他实例的一部分。
这会导致合并输出中缺少某些字符。
我知道最新版本的 Ghostscript 对其字体处理代码进行了大修。尝试 Ghostscript v9.06(迄今为止的最新版本)可能会让您更加幸运。
我非常有兴趣对此进行更详细的调查。如果您可以提供输入文件的示例(以及 GS v8.70 给出的合并输出),我可以测试它是否与 v9.06 一起工作得更好。
你可以做些什么来避免这个问题
尝试始终将字体作为完整集而不是子集嵌入:
- 我不知道在使用 wkhtmltopdf 时是否以及如何控制嵌入完整的字体。
- 如果您从 Libre/OpenOffice 生成输入 PDF,那么您就不走运了,您将无法控制它。
- 如果您使用 Acrobat 生成输入 PDF,您可以在 Distiller 设置中调整字体嵌入细节。
- 如果 Ghostscript 生成您的输入 PDF,则强制完整字体嵌入的命令行参数是:
gs -o output.pdf -sDEVICE=pdfwrite -dSubsetFonts=false input.file
某些类型的字体不能完全嵌入,而只能嵌入子集(TrueType、Type3、CIDFontType0、CIDFontType1、CIDFontType2)。请参阅此问题的答案“为什么 Acrobat Distiller 不完全嵌入所有字体?” 更多细节。
仅当您确定没有其他人可以看到或打印或使用您的个人输入文件时才执行以下操作:根本不要嵌入字体 - 仅在与 Ghostscript 合并时嵌入您输入的最终结果 PDF。
- 我不知道在使用 wkhtmltopdf 时是否以及如何控制没有字体嵌入。
- 如果您从 Libre/OpenOffice 生成输入 PDF,那么您就不走运了,您将无法控制它。
- 如果您使用 Acrobat 生成输入 PDF,您可以在 Distiller 设置中调整字体嵌入细节。
- 如果 Ghostscript 生成您的输入 PDF,则防止字体嵌入的命令行参数是:
gs -o output.pdf -sDEVICE=pdfwrite -dEmbedAllFonts=false -c "<</AlwaysEmbed [ ]>>setpagedevice" input.file
某些类型的字体不能完全嵌入,而只能嵌入子集(Type3、CIDFontType1)。请参阅 此问题的答案“为什么 Acrobat Distiller 不完全嵌入所有字体?” 更多细节。
不要使用 Ghostscript,而是pdftk
用于合并 PDF。 pdftk
在合并 PDF 时,它比 Ghostscript(至少旧版本的 pdftk 是)更“愚蠢”的实用程序,这种愚蠢可能是一个优势......
更新
再次回答,但这次更明确(在下面评论中@sacohe 的额外问题之后。在许多(不是全部)情况下,以下过程将起作用:
然后,即使输入 PDF 对不同的字体(子集)使用相同的名称前缀,生成的输出 PDF 也应该对字体名称使用不同的(唯一)前缀。
当我处理原始问题的作者“R先生”提供给我的原始输入文件样本时,此过程对我有用。在那次修复之后,“跳过字符问题”在最终结果中消失了(从固定输入文件创建的合并 PDF)。