【问题标题】:Handling (remapping) missing/problematic (CID/CJK) fonts in PDF with ghostscript?使用ghostscript处理(重新映射)PDF中丢失/有问题的(CID/CJK)字体?
【发布时间】:2012-06-21 00:36:08
【问题描述】:

简而言之,我正在处理一个有问题的 PDF,其中:

  • 由于缺少字体信息,无法在 evince 等文档查看器中完全呈现;
  • 但是 - ghostscript 可以完全呈现​​相同的 PDF。

因此——无论ghostscript 使用什么来填充空白(可能是备用字形,或访问字体的不同方法)——我希望能够使用 @ 987654334@ 生成(“提取”)输出 PDF,其中几乎什么都不会改变,除了添加的字体信息,因此evince 可以以与ghostscript 相同的方式呈现相同的文档能够。

我的问题是这样的——这有可能吗?如果是这样,命令行是什么来实现这样的目标?

非常感谢您的任何回答,
干杯!


详情:

我实际上使用的是较旧的 Ubuntu 10.04,我可能遇到了 - 不是错误 - 而是 evince 的安装问题(缺少 poppler-data 包),如 Bug #386008 “Some fonts fail to display due to “Unknown font tag...” : Bugs : “poppler” package : Ubuntu 中所述。

但是,这正是我想要处理的,所以我将使用该帖子所附的fontspec.pdf ("PDF triggering the bug.", // v .) 来演示问题。

evince

首先,我在evince 中打开此pdf 的第3 页;和evince 抱怨:

$ evince --page-label=3 fontspec.pdf

Error: Missing language pack for 'Adobe-Japan1' mapping
Error: Unknown font tag 'F5.1'
Error (7597): No font in show
Error: Unknown font tag 'F5.1'
Error (7630): No font in show
Error: Unknown font tag 'F5.1'
Error (7660): No font in show
Error: Unknown font tag 'F5.1'
...

渲染效果如下:

... 很明显有些字体形状丢失了。

Adobe acroread

仅说明 Adob​​e 的 Acrobat Reader for Linux 的行为方式;以下命令行:

$ ./Adobe/Reader9/bin/acroread /a "page=3" fontspec.pdf

... 不会向终端生成任何输出(有关/a 开关的更多信息,请参阅Man page acroread)——而且程序在显示字体方面绝对没有问题。

另外,虽然我想避免往返于 postscript - 但是,请注意 acroread 本身可用于将 PDF 转换为 postscript:

$ ./Adobe/Reader9/bin/acroread -v
9.5.1

$ ./Adobe/Reader9/bin/acroread -toPostScript \ 
-rotateAndCenter -choosePaperByPDFPageSize \
-start 3 -end 3 \
-level3 -transQuality 5 \
-optimizeForSpeed -saveVM \
fontspec.pdf ./ 

同样,上面的命令行将不会向终端生成任何输出; -optimizeForSpeed -saveVM 在那里,因为显然它们处理字体;最后一个参数./ 是输出目录(输出文件自动称为fontspec.ps)。

现在,evince 可以fontspec.ps 输出中显示以前丢失的字体 - 但再次抱怨:

$ evince fontspec.ps 
GPL Ghostscript 9.02: Error: Font Renderer Plugin ( FreeType ) return code = -1
GPL Ghostscript 9.02: Error: Font Renderer Plugin ( FreeType ) return code = -1
...

...此外,所有 text 似乎在后记中都被压平为曲线 - 所以现在不能再选择 evince 中的 .ps 文件中的文本了(注意 . ps 文件无法在acroread 中打开)。但是,可以再次将此 .ps 转换回 .pdf:

$ pstopdf fontspec.ps   # note, `pstopdf` has no output filename option;
                        # it will automatically choose 'fontspec.pdf',
                        # and overwrite previous 'fontspec.pdf' in 
                        # the same directory 

...现在pstopdf 输出中的文本可以在evince 中选择,所有字体都在那里,evince 不再抱怨了。但是,正如我所指出的,我想完全避免往返于 postscript 文件。

display(来自imagemagick

我们也可以使用imagemagicks display 观察同一个文档中的页面(注意image panning from the commandline using 'display' 显然仍然不可用,所以我在下面使用-crop 来调整视口):

$ display -density 150 -crop 740x450+280+200 fontspec.pdf[2]
   **** Warning: considering '0000000000 00000 n' as a free entry.
...
   **** This file had errors that were repaired or ignored.
   **** The file was produced by: 
   **** >>>> Mac OS X 10.5.4 Quartz PDFContext <<<<
   **** Please notify the author of the software that produced this
   **** file that it does not conform to Adobe's published PDF
   **** specification.

... 这会产生一些 ghostscripish 错误 - 结果如下:

... 很明显,evince 无法渲染的缺失字体现在显示在这里,imagemagicks display,正确。

ghostscript

最后,我们可以use ghostscript as x11 viewer自己——观察同一个页面,同一个文档:

$ gs -sDevice=x11 -g740x450 -r150x150 -dFirstPage=3 \
-c '<</PageOffset [-120 520]>> setpagedevice' \
-f fontspec.pdf

GPL Ghostscript 9.02 (2011-03-30)
Copyright (C) 2010 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
   **** Warning: considering '0000000000 00000 n' as a free entry.
   **** Warning: considering '0000000000 00000 n' as a free entry.
   **** Warning: considering '0000000000 00000 n' as a free entry.
   **** Warning: considering '0000000000 00000 n' as a free entry.
   **** Warning: considering '0000000000 00000 n' as a free entry.
   **** Warning: considering '0000000000 00000 n' as a free entry.
   **** Warning: considering '0000000000 00000 n' as a free entry.
Processing pages 3 through 74.
Page 3
>>showpage, press <return> to continue<<
^C

...以及此输出的结果:

 

总结:ghostscript(以及 显然 的扩展名,imagemagick)似乎可以找到丢失的字体(或者至少可以找到它的替代品),并且用它渲染一个页面——即使evince 在同一个文档中失败。

因此,我只想从ghostscript 导出一个PDF 版本,它只会嵌入缺少的字体,没有其他处理;所以我试试这个:

$ gs -dBATCH -dNOPAUSE -dSAFER  \
-dEmbedAllFonts -dSubsetFonts=true -dMaxSubsetPct=99 \
-dAutoFilterMonoImages=false \
-dAutoFilterGrayImages=false \
-dAutoFilterColorImages=false \
-dDownsampleColorImages=false \
-dDownsampleGrayImages=false \
-dDownsampleMonoImages=false \
-sDEVICE=pdfwrite \
-dFirstPage=3 -dLastPage=3 \
-sOutputFile=mypg3out.pdf -f fontspec.pdf

GPL Ghostscript 9.02 (2011-03-30)
Copyright (C) 2010 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
   **** Warning: considering '0000000000 00000 n' as a free entry.
   **** Warning: considering '0000000000 00000 n' as a free entry.
   **** Warning: considering '0000000000 00000 n' as a free entry.
   **** Warning: considering '0000000000 00000 n' as a free entry.
   **** Warning: considering '0000000000 00000 n' as a free entry.
   **** Warning: considering '0000000000 00000 n' as a free entry.
   **** Warning: considering '0000000000 00000 n' as a free entry.
Processing pages 3 through 3.
Page 3

   **** This file had errors that were repaired or ignored.
   **** The file was produced by:
   **** >>>> Mac OS X 10.5.4 Quartz PDFContext <<<<
   **** Please notify the author of the software that produced this
   **** file that it does not conform to Adobe's published PDF
   **** specification.

...但它不起作用 - 输出文件 mypg3out.pdf 遇到与前面提到的 evince 完全相同的问题。

注意:虽然我想避免 postscript 往返,但 gs 命令行的一个很好的例子,从 pdf 到 ps 并带有字体嵌入:(#277826) pdf - How to make GhostScript PS2PDF stop subsetting fonts;但 .pdf 到 .pdf 的相同命令行切换似乎对上述问题没有任何影响。

【问题讨论】:

  • 呸,棘手的问题。不是我的区域,但 +1 并祝你好运! (我认为您不能从其源应用程序重新创建 PDF?这可能更容易)。
  • 非常感谢@halfer 的评论 - 实际上,无法重新创建有问题的 PDF;照原样得到它,并且必须将它也包含在 PDF 集合中:/。至少,与此同时,我可以确认这是带有 CID/CJK 字体的font mapping problem;所以现在的问题是如何(如果可能)让ghostscript 根据“已知”字体映射(不会引发错误)重新映射嵌入的 CID 字体字形。干杯!

标签: pdf fonts ghostscript


【解决方案1】:

确定点1;您不能使用 Ghostscript 和 pdfwrite 来创建 PDF 文件“无需任何额外处理”。

pdfwrite 和 Ghostscript 的工作方式是完全解释传入的数据(PostScript、PDF、XPS、PCL 等),创建一系列图形基元,然后传递给 pdfwrite 设备。然后 pdfwrite 设备将这些重新组合成一个全新的 PDF 文件。

因此不可能将 PDF 文件作为输入并对其进行操作,它总是会创建一个新文件。

现在,我建议您先将 9.02 Ghostscript 升级到 9.05。丢失的 CIDFonts 在 9.05 中得到了更好的处理(今年晚些时候将在 9.06 中进一步改进)。 (您缺少的“Osaka Mono”字体实际上是 CIDFont,而不是常规字体)

使用当前最前沿的 Ghostscript 代码为我生成了一个 PDF 文件,其中嵌入了缺失的字体。我不知道这是否适合你,因为我的 evince 副本可以完美地呈现原始文件。

稍后添加

检查原始 PDF 文件,我发现确实嵌入了字体(正如我所料,因为它们是子集)。所以实际上正如您在上面自己的答案中所说,问题不在于字体嵌入,而在于 CIDFonts 的使用。

我在这里的回答对你没有帮助,因为 pdfwrite 仍然会在输出中产生一个 CIDFont。基本上,这是您的版本或 evince 安装中的缺陷。

“重新映射”字符的问题是字体被限制为 256 个字形,而 CIDFont 实际上没有限制。所以没有办法将 CIDFont 放入 Font 中。这样做的唯一方法是创建多个字体,每个字体都包含原始字体的一部分,然后根据需要在它们之间切换。缓慢而笨拙。

如果您使用 ps2write 设备转换为 PostScript,那么它会为您执行此操作,但您将面临很大的风险,即在此过程中它将矢量字形数据转换为无法很好缩放的位图。

从根本上说,您无法使用 Ghostscript 或实际上使用我知道的任何其他工具来真正实现您想要做的事情(将 1 个 CIDFont 转换为 N 个常规字体)。虽然它在技术上是可行的,但没有真正意义,因为所有 PDF 消费者都应该能够处理 CIDFonts。如果他们不能,那么它是 PDF 消费者中的一个错误。

【讨论】:

  • 非常感谢@KenS 的澄清!采取第 1 点;我在“没有任何额外处理”中措辞很糟糕——我的主要意思是images should be preserved。另外,我在一个单独的文件夹中有 gs9.05,运行相同的 cmdline,结果在我的evince 中几乎相同。我也意识到这是一个CID font mapping problem,所以现在问题归结为:是否有可能以某种方式重新映射已经嵌入源pdf中的字形?干杯!
  • 非常感谢@KenS 的更新答案 - 这可能不是我想要的,但现在我终于明白这里的问题是什么了!再次非常感谢 - 干杯!
【解决方案2】:

是的,我对此有更深入的了解(但不完全) - 所以我将在此处发布部分答案/评论。

本质上,这不是 PDF 中字体嵌入的问题 - 这是字体映射的问题。

为了证明这一点,让我们分析mypg3out.pdf,它是由OP中的gs提取的(来自fontspec.pdf文档的第3页):

$ pdffonts mypg3out.pdf 
name                                 type              emb sub uni object ID
------------------------------------ ----------------- --- --- --- ---------
Error: Missing language pack for 'Adobe-Japan1' mapping
CAAAAA+Osaka-Mono-Identity-H         CID TrueType      yes yes yes     19  0
GBWBYF+CMMI9                         Type 1C           yes yes yes     28  0
FDFZUN+Skia-Regular_wght13333_wdth11999 TrueType          yes yes yes     16  0
ZRLTKK+Optima-Regular                TrueType          yes yes yes     30  0
ZFQZLD+FPLNeu-Bold                   Type 1C           yes yes yes      8  0
DDRFOG+FPLNeu-Italic                 Type 1C           yes yes no      22  0
HMZJAO+FPLNeu-Regular                Type 1C           yes yes yes     10  0
RDNKXT+FPLNeu-Regular                Type 1C           yes yes yes     32  0
GBWBYF+Skia-Regular_wght13333_wdth11999 TrueType          yes yes no      26  0

正如输出所示 - 所有字体 都是,确实,嵌入;所以还有别的问题。 (在完整的fontspec.pdf 中观察到这一点会更加困难,因为那里有大量的字体和大量的错误消息。

这里的关键点(我认为)是:

  • 只有一条“Error: Missing language pack for 'Adobe-Japan1' mapping”消息;和
  • 只有一种CID TrueType字体,即CAAAAA+Osaka-Mono-Identity-H

CID TrueType 和“Adobe-Japan1”映射错误之间似乎存在明显的关系;我终于被CID fonts - How to use Ghostscript澄清了:

CID 字体是包含大量字形的 PostScript 资源(例如,远东语言、中文、日语和韩语的字形)。有关详细信息,请参阅 PostScript 语言参考,第三版。

CID 字体资源是一种不同于字体的 PostScript 资源。特别是,它们不能用作常规字体。 CID 字体资源必须先与定义字形的特定代码的 CMap 资源组合,然后才能用作字体。这允许重复使用具有不同编码的字形集合。

一切都好——除了这里我们处理的是 PDF 字体,而不是 PostScript 字体本身;让我们稍微演示一下。

例如,5.3. Using Ghostscript To Preview Fonts - Making Fonts Available To Ghostscript - Font HowTo 描述了如何使用 Ghostscript 安装的脚本 prfont.ps 来呈现字体表。

但是,这里只使用Listing Ghostscript Fonts [gs-devel] 会更容易,并使用resourcestatus operator 查询特定字体 - 这不需要特殊的 .ps 脚本:

$ gs -o /dev/null -dNODISPLAY -f mypg3out.pdf \
-c 'currentpagedevice (*) {=} 100 string /Font resourceforall'
...
Processing pages 1 through 1.
Page 1
URWAntiquaT-RegularCondensed
Palatino-Italic
Hershey-Gothic-Italian
...

$ gs -o /dev/null -dNODISPLAY -f mypg3out.pdf \
-c '/TimesNewRoman findfont pop [/TimesNewRoman /Font resourcestatus]'
....
Processing pages 1 through 1.
Page 1
Can't find (or can't open) font file /usr/share/ghostscript/9.02/Resource/Font/TimesNewRomanPSMT.
Can't find (or can't open) font file TimesNewRomanPSMT.
Can't find (or can't open) font file /usr/share/ghostscript/9.02/Resource/Font/TimesNewRomanPSMT.
Can't find (or can't open) font file TimesNewRomanPSMT.
Querying operating system for font files...
Loading TimesNewRomanPSMT font from /usr/share/fonts/truetype/msttcorefonts/times.ttf... 2549340 1142090 3496416 1237949 1 done.

我们得到了一个字体列表;但是,这些是ghostscript 可用的系统字体 - 不是 PDF 中嵌入的字体!

(基本上,

  • gs -o /dev/null -dNODISPLAY -f mypg3out.pdf -c 'currentpagedevice (*) {=} 100 string /Font resourceforall' | grep -i osaka 不会返回任何内容,并且
  • -c '/CAAAAA+Osaka-Mono-Identity-H findfont pop [/CAAAAA+Osaka-Mono-Identity-H /Font resourcestatus]' 将以“在系统上未找到此字体!将字体 Courier 替换为 CAAAAA+Osaka-Mono-Identity-H.”结束。)

要列出 PDF 中的字体,可以使用 Ghostscript 中的 pdf_info.ps script file未安装,在源代码中):

$ wget "http://git.ghostscript.com/?p=ghostpdl.git;a=blob_plain;f=gs/toolbin/pdf_info.ps" -O pdf_info.ps

$ gs -dNODISPLAY -q -sFile=mypg3out.pdf -dDumpFontsNeeded pdf_info.ps
...
No system fonts are needed.

$ gs -dNODISPLAY -q -sFile=mypg3out.pdf -dDumpFontsUsed -dShowEmbeddedFonts pdf_info.ps
...
Font or CIDFont resources used:
CAAAAA+Osaka-Mono
DDRFOG+FPLNeu-Italic
FDFZUN+Skia-Regular_wght13333_wdth11999
GBWBYF+CMMI9
GBWBYF+Skia-Regular_wght13333_wdth11999
GTIIKZ+Osaka-Mono
HMZJAO+FPLNeu-Regular
RDNKXT+FPLNeu-Regular
ZFQZLD+FPLNeu-Bold
ZRLTKK+Optima-Regular

所以最后我们可以在 Ghostscript 中观察到 CAAAAA+Osaka-Mono——虽然我不知道如何从 ghostscript 中查询有关它的更具体信息。

 

最后,我想我的问题归结为:如何使用 ghostscript 将字形从 CID 嵌入字体映射到具有不同“编码”的字体(或“字符映射”?),这不需要额外的语言文件?

附录

我也尝试过这些方法:

  • pdffonts 在此处的输出中不会列出大阪单声道,但它仍会抱怨“错误:缺少 'Adobe-Japan1' 映射的语言包”:
    $ wget http://whalepdfviewer.googlecode.com/svn/trunk/cmaps/japanese/Adobe-Japan1-UCS2
    $ gs -sDEVICE=pdfwrite -o mypg3o2.pdf -dBATCH -f mypg3out.pdf Adob​​e-Japan1-UCS2
  • 与以前相同 - 这(通过 Ghostscript 的“Use.htm”)也使 Osaka-Mono 从 pdffonts 列表中消失:
    gs -sDEVICE=pdfwrite -o mypg3o2.pdf -分贝\
    -c '/CIDSystemInfo >' \
    -f mypg3out.pdf
  • 这会因Error: /undefinedresource in findresource 而崩溃:
    gs -sDEVICE=pdfwrite -o mypg3o2.pdf -dBATCH \
    -c '/Osaka-Mono-Identity-H /H /CMap findresource [/Osaka-Mono-Identity /CIDFont findresource] == ' \
    -f mypg3out.pdf

最后请注意,一些.ps 脚本ghostscript 安装,它可能会自动使用;比如你可以找到gs_ttf.ps

$ locate gs_ttf.ps
/usr/share/ghostscript/9.02/Resource/Init/gs_ttf.ps

...然后使用sudo nano locate gs_ttf.ps,可以在代码开头添加语句(Hello from gs_ttf.ps\n) print;然后每当调用上述gs 命令之一时,打印输出将在标准输出中可见。

参考文献

【讨论】:

  • "this crash with Error: /undefinedresource in findresource" 错误和退出不是崩溃,它是从错误条件中优雅退出。它出错的原因是因为您没有定义一个名为 Osaka-Mono 的 CIDFont,您可以将一个添加到 cidfmap(并采取措施将该文件添加到搜索路径)然后它会起作用。将 CIDSystemInfo 字典添加到命令行没有任何效果,因为这些字典必须存在于 CIDFonts 和 CMap 中,其他任何地方都没有。
  • pdfinfo.ps 仅报告文件中使用了名为 Osaka-Mono 的字体(xxxxxx+ 前缀表示字体子集),并不表示已嵌入。请注意,有两个实例具有不同的前缀,因此您有两个子集。
  • 非常非常感谢这些 cmets,@KenS - 为我澄清了很多!我实际上没有 Osaka-Mono 字体;我按原样得到了这个pdf,它嵌入了那个字体......所以,从本质上讲,我要做的就是找到一种方法来“重新映射”(?)嵌入在源pdf中的已经存在的字形,进入其他一些“字符映射”(我猜?)这不会导致这个旧的evince 失败——如果有可能用gs 做类似的事情的话。再次感谢 - 干杯!
  • 是的,花了更多时间检查原始文件,我已经更新了我的答案,但恐怕它不是你想要的:-(
猜你喜欢
  • 2018-09-08
  • 2016-07-03
  • 2012-06-26
  • 2016-05-09
  • 2017-08-05
  • 1970-01-01
  • 2020-04-22
  • 2016-07-13
  • 1970-01-01
相关资源
最近更新 更多