从正确呈现的 PDF 中复制粘贴印地语只能正确粘贴某些字符

Copy-pasting Hindi from a correctly rendering PDF pastes only certain characters correctly

我有一个可以正确呈现的 PDF ([0])。如果我尝试从中复制粘贴,粘贴的文字会有点偏离。它不会发生在所有的文本上——只有一些单词。 PDF 中嵌入了字体 (Devanagari MT);在一种情况下,我安装了完全相同的字体,但它仍然无法正确粘贴。我附上了一张图片以更好地说明我所看到的。有点忙所以我会分解它:左边side/background是在MacOS Mavericks(10.10)上的Adobe Acrobat DC Reader中打开的PDF;右侧是将文本粘贴到 Notes(顶部)和 Pages(底部)中。红色矩形勾勒出所使用的字体在所有示例中都很常见,绿色矩形勾勒出正确复制的单词部分。突出显示的文本表示正在复制或粘贴的完整单词。除了 Adob​​e Acrobat DC reader,我还尝试从预览中复制(MacOS 默认用于查看 PDF)。在图片之外(即终端、浏览器或随机文本框等)和 Windows 10 我得到相同的结果。转换为例如RTF 或 .docx 也会产生同样的问题。什么丢失或配置错误?我该如何解决这个问题,以便可靠地复制和粘贴?预先感谢您的想法和见解。

亲切的问候,

-杰斯

[0] https://repositories.lib.utexas.edu/bitstream/handle/2152/41433/GlossariesAlive_01.pdf

编辑:混合页面和 Acrobat DC

用于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是set text matrix,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' 的文本是您的 Devanagri 字体,定义为:

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 table(它是一种 TrueType 字体)中的特定字形。因为它不是标准编码,所以无法知道字符编码 'mean'。但是,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

取第一行:

<21><21><092e>

这意味着从 0x21 到 0x21 的字符代码映射到从 0x092e 开始的 Unicode 代码点。显然这是一个单一的字符代码,但它可以是一个范围。

现在您会注意到 CMap 在范围内有 'holes',例如没有 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 或(因为文件已被修改)编辑应用程序 'Pages'.

的错误

如何解决这个问题?那么您可以手动编辑 ToUnicode CMap 文件并为每个字符代码添加条目。这将是一个费力的过程,因为首先您必须识别文本中的每个字符代码并弄清楚它的 Unicode 代码点是什么。此外,PDF 是一种二进制格式,具有交叉引用 table。如果您在文件中进行任何插入,则外部参照 table 将无效并且 PDF 文件实际上已损坏。有些观众能够修复它,有些则不能。

正如我上面所暗示的,通常会创建一个自定义编码的子集字体,以便文档中使用的第一个字符的字符代码为 1,第二个为 2,依此类推。因此,对于每个文档,实际映射都是唯一的,不可能编写一些代码来可靠地为您执行此操作,因为没有 'one size fits all' 映射。

基本上您需要使用在 PDF 文件中嵌入正确 ToUnicode CMap 的软件重新制作 PDF 文件。