4

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

我设法制作了一个简单的文件。文件在这里

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

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

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

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

该文件的链接在这里

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

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

4

1 回答 1

20

一个非常简短和简化的介绍

PDF 中的字体是PDF 对象-Font字典,包含许多参数和子字典,是选择字形、显示它们并将字符代码转换为逻辑 (Unicode) 表示以进行内容提取所必需的。外行术语中的字体(我们将它们视为 *.ttf 或 *.pfb 文件)称为字体程序,可以是嵌入的或外部的,并且由对象的子字典之一引用Font

Fonts分为两组:

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

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

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

现在,字符选择器 ( CID) 通常不直接用于从字体程序中选择字形。对于类型,它CIDFontCIDFontType2字典包含CIDToGIDMap条目,很明显,它映射CID到字形标识符。最后,这些GIDs用于从嵌入式字体程序中选择字形(对于CIDFontType2字体,它是一个TrueType字体程序(不要与TrueTypeFont的对象混淆))。 Subtype

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

在我称之为简单的情况下(并且,我认为,明智的决定),CMap是预定义的 Identity-H名称,CIDToGIDMap是预定义的身份名称,因此,从字符串中提取的字符代码(显示运算符的文本参数)总是 2 -字节数字,有效地直接从嵌入式TrueType程序中选择字形。根据我的经验,这是最常见的情况,并且看起来就是这种情况,针对其测试通用软件。

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

(简短的介绍结束)

在我们的文件中,显示操作符的文本有效地获取了这个字符串:

0x000a 0x000a 0x000a 0x20 0x0020 0x0020 0x0020 0x20 0x0025 0x0025 0x0025 

当然没有“组”,它们在这里是因为我制作了它们,基于CMap它包含 2 个范围:

<20> <20>
<0000> <19FF>

长话短说,如果我们查找字符代码CMap并获取 CID,然后查找 CIDCIDToGIDMap并获取 GID,然后查找嵌入的 David-Bold字体的 GID 并获取 Unicode 值,这是表格

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代码(和)(参见上面的评论)。CID这个假设是基于几年前的一个案例,当(旧版本的)Acrobat 没有用0x20代码显示字符时,当它位于字符串的末尾时——假设它是space,实际上,根据编码向量(一种简单的字体),它是另一个字符。

我改变了这个:

  • 0x00200x0004内容流中;
  • 字节 08 和 09CIDToGIDMap到 GID=159;
  • WidthsCID=4 到 'vav' 宽度的数组中的值;
  • ToUnicode cmap进行了相应的调整。
  • (+ 后来我尝试<0020> 32从 - 中删除字符串CMAP- 未反映在文件中,在评论中链接)

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


然后我想,也许可变字符代码宽度是问题所在。

我返回到原始文件并更改了这个:

  • 0x200x00e4内容流中;
  • <20> 228到; <00e4> 228_CMAP
  • codespacerange <20> <20>CMAP已删除;
  • codespacerange <20> <20>ToUnicode Cmap删除。

文件似乎可以在所有查看器中完美打开,在下面的原始问题和评论中提到。奇迹般地,0x0020编码并32 CID不受干扰。


我认为,结论可能是这样的:

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

于 2013-11-16T18:31:28.293 回答