使用ghostscript处理(重新映射)PDF中的缺失/有问题(CID / CJK)字体?

时间:2012-06-19 00:55:15

标签: pdf fonts ghostscript

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

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

因此 - 无论ghostscript用什么来填补空白(可能是后备字形,或者访问字体的其他方法) - 我希望能够使用ghostscript来生成(“提取”)输出PDF,除了添加的字体信息之外,几乎 nothing 将被更改,因此evince可以呈现相同的文档与ghostscript相同的方式。

我的问题因此 - 这是可能的吗?如果是这样,那么命令行会是什么样的呢?

非常感谢任何答案,
干杯!


详细说明:

我实际上是在较旧的Ubuntu 10.04上,我可能遇到过 - 而不是错误 - 但evince(缺少poppler-data包)的安装问题,如{{3 }}。

然而,这正是我想要处理的内容,因此我将使用该帖子附带的fontspec.pdfBug #386008 “Some fonts fail to display due to “Unknown font tag...” : Bugs : “poppler” package : Ubuntu”,/ /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'
...

渲染如下所示:

evince-pdf-missfont-render.png

...很明显缺少某些字体形状。

Adob​​e acroread

关于Adobe的Acrobat Reader for Linux如何表现的说明;以下命令行:

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

...不会向终端生成任何输出(更多关于/a开关,请参阅PDF triggering the bug. ) - 程序显示字体完全没问题。

<子> 此外,虽然我想避免往返附录 - 但请注意,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
...

...此外,所有文本似乎都被平铺到postscript中的曲线 - 所以现在无法再选择evince中的.ps文件中的文本了(请注意无法在acroread中打开.ps文件。但是,可以将此.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

我们还可以使用imagemagick s display来观察同一文档中的页面(请注意Man page acroread显然仍然无效,所以我使用了{{1下面调整视口):

-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. ish错误 - 并产生类似这样的结果:

imagemagick-display-pdf.png

...很明显,ghostscrip无法呈现的丢失字体现在显示在这里evince s imagemagick正确。

display

最后,我们可以image panning from the commandline using 'display'本身 - 观察相同的页面,相同的文档:

ghostscript

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

ghostscript-pdf-view.png

总之:$ 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),看似可以找到丢失的字体(或至少有一些替代字体) it),并使用它呈现一个页面 - 即使imagemagick对同一文档失败了。

因此,我只想从evince导出一个PDF版本,该版本只会嵌入缺少的字体,而不会进行其他处理;所以我试试这个:

ghostscript

...但它不起作用 - 输出文件$ 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中遇到了完全相同的问题。

注意:虽然我想避免postcript往返,但是evince命令行的一个很好的例子,从pdf到带有字体嵌入的ps在这里:use ghostscript as x11 viewer;但是同一命令行切换.pdf到.pdf似乎对上述问题没有任何影响。

2 个答案:

答案 0 :(得分:3)

是的,我对此有所了解(但并非完全) - 所以我会在这里发布部分答案/评论。

基本上,这不是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

如输出所示 - 所有字体 ,实际上 embedded ;所以还有别的问题。 (在完整的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语言参考,第3版。

     

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

一切都很好 - 除了这里我们处理PDF字体,而不是PostScript字体;让我们来证明一下。

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

但是,仅使用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 Adobe-Japan1-UCS2
  • 和以前一样 - 这个(通过Ghostscript的“Use.htm”)也使大阪单声道从pdffonts列表中消失:
    gs -sDEVICE=pdfwrite -o mypg3o2.pdf -dBATCH \
    -c '/CIDSystemInfo << /Registry (Adobe) /Ordering (Unicode) /Supplement 1 >>' \
    -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,您可以在代码的开头添加语句locate gs_ttf.ps;然后,无论何时调用上述(Hello from gs_ttf.ps\n) print命令之一,打印输出都将在标准输出中显示

参考

答案 1 :(得分:3)

OK点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消费者中的错误。