【问题标题】:Copy-pasting Hindi from a correctly rendering PDF pastes only certain characters correctly从正确呈现的 PDF 复制粘贴印地语仅正确粘贴某些字符
【发布时间】:2019-10-02 15:32:38
【问题描述】:

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

亲切的问候,

-杰斯

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

编辑:混合页面和 Acrobat DC

【问题讨论】:

    标签: pdf copy-paste paste hindi embedded-fonts


    【解决方案1】:

    用于 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 文件。

    【讨论】:

    • 神圣的地狱。感谢您令人难以置信的详细和清晰的答复。这个答案的质量让我无语。我很感激。谢谢你。哇。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    • 2019-09-06
    • 1970-01-01
    相关资源
    最近更新 更多