用于 PDF 文件中文本的字符代码不需要与任何语言编码有任何直接关系。以下是 PDF 包含的您所指向的文本位:
/F1.0 1 Tf (these houses ) Tj ET Q q 1 0 0 -1 0 792 cm BT 11 0 0 -11 235.8 375
Tm /F2.1 1 Tf (7) Tj ET Q q 1 0 0 -1 0 792 cm BT 11 0 0 -11 242.2346 375 Tm
/F1.0 1 Tf ( ) Tj ET Q q 1 0 0 -1 0 792 cm BT 11 0 0 -11 244.9846 375 Tm /F2.1
1 Tf [ (!) 0.2 ("#) -0.3 ($) ] TJ ET Q q 1 0 0 -1 0 792 cm BT 11 0 0 -11 235.8 406
现在 Tf 选择字体(和磅值),Tj 绘制文本。 BT 和 ET 表示 Begin Text Block 和 End Text Block q 和 Q 表示 gsvare 和 grestore,cm 是 concatmatrix,Tm 是设置文本矩阵,TJ 是另一种绘制文本的方式。
你可以忽略其中的大部分。
只看我们拥有的重要部分:
/F1.0 1 Tf (these houses ) Tj
/F2.1 1 Tf (7) Tj
/F1.0 1 Tf ( ) Tj
/F2.1 1 Tf [ (!) 0.2 ("#) -0.3 ($) ] TJ
现在您可以看到名为“F1.0”的字体中的文本使用 ASCII 编码(或多或少),该字体是 AGaramondPro-Regular,使用 MacRomanEncoding:
8 0 obj
<<
/Type /Font
/Subtype /Type1
/BaseFont /GFJJBF+AGaramondPro-Regular
/FontDescriptor 54 0 R
/Widths 55 0 R
/FirstChar 32
/LastChar 169
/Encoding /MacRomanEncoding
>>
endobj
使用字体“F2.1”的文本是您的梵文字体,定义为:
10 0 obj
<<
/Type /Font
/Subtype /TrueType
/BaseFont /MWSGSJ+DevanagariMT
/FontDescriptor 48 0 R
/Widths 49 0 R
/FirstChar 33
/LastChar 105
/ToUnicode 50 0 R
>>
endobj
请注意,这没有编码,但它确实有一个 ToUnicode 条目。本质上,这意味着字体具有非标准的自定义编码。子集字体的定义方式是字符代码直接映射到字体 GLYF 表中的特定字形(它是 TrueType 字体)。因为它不是标准编码,所以无法知道字符代码的“含义”。但是,ToUnicode CMap 旨在为您提供从字符代码到 Unicode 代码点的映射。
ToUnicode CMap 是 Acrobat(和其他查看器)提取文本的首选和最佳方式。正确构造的 ToUnicode CMap 应该为您提供来自给定字符代码的直接 Unicode 代码点。文件中的 CMap 是:
50 0 obj
<<
/Length 913
>>
stream
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo <<
/Registry (Adobe)
/Ordering (UCS)
/Supplement 0
>> def
/CMapName /Adobe-Identity-UCS def
/CMapType 2 def
1 begincodespacerange
<00><FF>
endcodespacerange
39 beginbfrange
<21><21><092e>
<22><22><0915>
<23><23><093e>
<24><24><0928>
<25><25><092c>
<26><26><095c>
<27><27><0938>
<2a><2a><0926>
<2b><2b><0930>
<2c><2c><091b>
<2d><2d><094b>
<2e><2e><091f>
<2f><2f><090f>
<32><32><0924>
<33><33><0940>
<34><34><092f>
<35><35><0939>
<36><36><0935>
<39><39><0906>
<3a><3a><0932>
<3e><3e><092a>
<46><46><0905>
<49><49><095b>
<4a><4a><095a>
<4b><4b><091a>
<51><51><0917>
<52><52><091c>
<58><58><0920>
<5a><5b><095d>
<5c><5c><0959>
<5d><5d><0914>
<60><60><0921>
<61><61><094c>
<62><62><092d>
<63><63><0936>
<64><64><093f>
<65><65><0916>
<66><66><0907>
<68><68><0927>
endbfrange
endcmap
CMapName currentdict /CMap defineresource pop
end
end
endstream
endobj
取第一行:
这意味着从 0x21 到 0x21 的字符代码映射到从 0x092e 开始的 Unicode 代码点。显然这是一个单字符代码,但它可能是一个范围。
现在您会注意到 CMap 在范围中有“洞”,例如 0x28 和 0x29 没有条目。
因此,以您的文本为例,字符是 7、!、"、#、$。或者,十六进制 0x37、0x21、0x22、0x23、0x24(您可以看到索引是如何选择的,第一个字符在文件是 0x01,第二个是 0x02,依此类推,所以字形映射的代码取决于字符的使用顺序。
所以我们通过 ToUnicode CMap 运行这些数字,0x37 映射到... 哎呀! CMap 中没有字符代码 0x37 的条目! 0x21 对应 0x092e,0x22 对应 0x0915,0x23 对应 0x093e,0x24 对应 0x0928。
所以后四个字符可以正确复制和粘贴。 Acrobat(和任何其他查看器)不知道如何处理字符代码 0x37,因此它尽其所能并回退到旧的 ASCII 以希望它可能是正确的,这就是为什么最初粘贴的字符是一个 7,即 ASCII 中的 0x37。
这就是您的问题,ToUnicode CMap 不包含对 PDF 文件中使用的所有字符代码的 Unicode 代码点的映射。这是 PDF 创建工具 Mac OS/X 10.6 Quartz PDF Cn=ontext 或(因为文件已被修改)编辑应用程序“页面”的故障。
你怎么能解决这个问题?好吧,您可以手动编辑 ToUnicode CMap 文件并为每个字符代码添加条目。这将是一个费力的过程,因为首先您必须识别文本中的每个字符代码并弄清楚它的 Unicode 代码点是什么。此外,PDF 是一种二进制格式,带有交叉引用表。如果您在文件中进行任何插入,则外部参照表将无效并且 PDF 文件实际上已损坏。有些观众可以修复它,有些则不能。
正如我上面所暗示的,通常会创建一个自定义编码的子集字体,以便文档中使用的第一个字符被赋予字符代码 1,第二个是 2,依此类推。因此,对于每个文档,实际映射将是唯一的,不可能编写一些代码来可靠地为您执行此操作,因为没有“一刀切”的映射。
基本上,您需要使用在 PDF 文件中嵌入正确 ToUnicode CMap 的软件重新制作 PDF 文件。