PDF文档文本在IE / Firefox / Chrome中的显示方式不同

时间:2013-11-15 11:15:25

标签: google-chrome firefox pdf pdf-generation

我尝试使用希伯来文文本生成PDF文本文件。

我设法制作了一个简单的文件。档案是here

该文件在Adobe Acrobat Reader中完美打开,显示字符串“אאאווותתת”。 它也在IE中完美打开。

问题是其他观众表现得很糟糕: 谷歌浏览器/谷歌文档显示没有所有“ו”出现(即三个字母“ו”消失!)

Mozilla Firefox显示非常糟糕,多次显示一些字母并在页面上的奇怪位置...

我做错了什么? 文件有什么问题?

A link to the file is here

我知道这是一个棘手的问题。

任何帮助将不胜感激......

1 个答案:

答案 0 :(得分:17)

非常简短的简介

PDF中的字体是 PDF对象 - Font字典,包含许多参数和子字典,用于选择字形,显示它们并将字符代码转换为逻辑(Unicode)表示形式内容提取。外行术语中的字体 - 我们将它们视为* .ttf或* .pfb文件 - 被称为字体程序,无论是嵌入式还是外部的,并由{的一个子字典引用{1}}对象。

Font分为两组:

  • 简单字体(Type1,Type3或TrueType),其中字形由单字节字符代码选择,该字符代码从文本显示运算符显示的字符串中获取。从代码到字形的映射称为字体的编码,它可以内置到字体程序中,也可以由Fonts对象定义(通过预定义的名称或明确地),或者在特殊情况下,根据查看器应用程序定义的规则构建。

有问题的文件并不包含简单的字体,我们不会再进一步​​讨论它们了 - 但是,请注意,过于简单的描述甚至不会开始反映任何真实的生活的复杂性。

  • 复合字体(Type0),用于显示字符代码可以具有可变长度(最多4个字节)的文本,因此不限制为256个代码点。 Type0 字体总是有一个后代,它是一个名为Font字体对象,类似于简单字体的编码,一个CIDFont对象,用于将字符代码映射到字符选择器,在PDF中,它始终为CMap - 整数最多为65536。

现在,字符选择器(CIDs)通常不直接用于从字体程序中选择字形。对于CID类型的CIDFont,其字典包含CIDFontType2条目,显然,它将CIDToGIDMap映射到字形标识符。那些CID最后用于从嵌入式字体程序中选择字形(对于GIDs字体,它是 TrueType 字体程序(不要与 TrueType CIDFontType2)的Font对象混淆。)

Subtype对象可以拥有Font资源,将CID映射到Unicode值以进行索引,搜索和提取。它被称为ToUnicode(因为它遵循类似的语法),但不应与上面提到的ToUnicode Cmap对象混淆。

在我称之为简单案例(并且,我认为,明智的决定)中,CMap是预定义的 Identity-H 名称,CMap是预定义的标识名称,因此,从字符串中提取的字符代码(显示运算符的文本的参数)始终是2字节数字,实际上可以直接从嵌入式 TrueType 程序中选择字形。根据我的经验,它是最常见的情况,而且看起来就是这种情况,对于哪种常见软件进行了测试。

但是,有问题的文件并非如此。

(简短介绍的结尾)

在我们的文件中,显示运算符的文本有效地获取此字符串:

CIDToGIDMap

当然没有'群组',他们在这里是因为我根据包含2个范围的0x000a 0x000a 0x000a 0x20 0x0020 0x0020 0x0020 0x20 0x0025 0x0025 0x0025 制作了这些群组:

CMap

简而言之,如果我们在<20> <20> <0000> <19FF> 中查找字符代码并获取CID,请在CMap中查找CID并获取GID,然后在嵌入式 David中查找GID -Bold 字体并获取Unicode值,这里是表

CIDToGIDMap

现在我们有足够的信息来推测,混淆了查看器应用程序


在我的第一次尝试中,我建议将Code CID GID Unicode Name 0x000a 10 180 05EA tav 0x0020 32 159 05D5 vav 0x0025 37 154 05D0 alef 0x20 228 03 0020 space 代码(和32)用于非空格字符(请参阅上面的评论)。这个假设是基于几年前的一个案例,当时(旧版本的)Acrobat没有显示带有CID代码的字符,当它位于字符串的末尾时 - 假设它事实上,根据编码向量(简单字体),它是0x20,它是另一个角色。

我改变了这个:

    内容流中的
  • space0x0020;
  • 0x0004中的字节08和09到GID = 159;
  • {CID = 4的CIDToGIDMap数组中的值=&#39; vav&#39;宽度;
  • Widths已相应调整。
  • (+之后我尝试从ToUnicode cmap删除<0020> 32字符串 - 未反映在文件中,在评论中链接)

嗯,它确实有所帮助,但不幸的是,一些观众仍然拒绝遵守规范。


然后我想,可能是变量字符代码宽度问题。

我返回原始文件并更改了此内容:

    内容流中的
  • CMAP0x20;
  • {li> 0x00e4<20> 228中的<00e4> 228; {li> CMAP codespacerange已删除<20> <20>; 已删除CMAP中的
  • codespacerange <20> <20>

This文件似乎在所有观看者中完全打开,在下面的原始问题和评论中提到。奇迹般地,ToUnicode Cmap代码和0x0020 32不会干涉。


我认为结论可以是:

鉴于目前的情况,PDF创建者 NOT 建议在字体编码中混合使用单字节和双字节代码(CID)。