小型大写字母、旧式数字和一些连字符会在 PDF 复制文本中产生奇怪的符号吗?

小型大写字母、旧式数字和一些连字符会在 PDF 复制文本中产生奇怪的符号吗?

这是我使用 XeLaTeX 时一直遇到的问题。以下是一个小例子:

\documentclass{article}
\usepackage{fontspec}
\setmainfont[Ligatures=TeX,Numbers={OldStyle,Proportional}]{Minion Pro}

\begin{document}
The \textsc{nato} office 1234
\end{document}

该文件编译并显示正常。但如果我尝试将其文本从 Acrobat 复制到另一个应用程序,我会得到乱码字符,而不是所有小写字母、旧式数字和连字符钍:

办公室

这也意味着,如果我搜索 PDF,找不到“The”、“NATO”或“1234”的匹配项。如果文件被被 Google 收录

现在,如果我切换到 LuaLaTeX,就不会遇到这个问题:

The \textsc{nato} office 1234

北约办公室 1234

然后如果我使用大写小型大写字母,我可以得到确切地我想要的是:

The \mbox{\addfontfeatures{Letters=UppercaseSmallCaps}NATO} office 1234

北约办公室 1234

但是,尽管我尝试使用 XeLaTeX,它仍然会给出相同的乱码复制文本。问题似乎是,在生成的 PDF 文件中,LuaTeX 生成“正确的”CMap 条目,而 XeTeX 生成引用私有使用区域的有缺陷的条目:

LuaTeX                                        XeTeX
--------------------------------------------- ---------------------------------------------

/CIDInit /ProcSet findresource begin          /CIDInit /ProcSet findresource begin
12 dict begin                                 12 dict begin
begincmap                                     begincmap
...                                           ...
1 begincodespacerange                         1 begincodespacerange
<0000> <FFFF>                                 <0000> <FFFF>
endcodespacerange                             endcodespacerange
0 beginbfrange                                5 beginbfchar
endbfrange                                    <0044> <0063>
13 beginbfchar                                <0046> <0065>
<0044> <0063>                                 <0050> <006F>
<0046> <0065>                                 <0107> <E062>
<0050> <006F>                                 <010F> <FB03>
<0107> <00540068>                             endbfchar
<010F> <FB03>                                 1 beginbfrange
<015D> <0031>                                 <015D> <0160> <F731>
<015E> <0032>                                 endbfrange
<015F> <0033>                                 4 beginbfchar
<0160> <0034>                                 <05C9> <E000>
<05C9> <0041>                                 <05D6> <E044>
<05D6> <004E>                                 <05D7> <E049>
<05D7> <004F>                                 <05DC> <E061>
<05DC> <0054>                                 endbfchar
endbfchar                                     endcmap
endcmap                                       CMapName currentdict /CMap defineresource pop
CMapName currentdict /CMap defineresource pop end
end                                           end
end

确实,如果我只是将所有这些 CMap 条目从 LuaTeX 的 PDF “移植”到 XeTeX 的 PDF 中,问题就消失了!所以:

  1. 有没有办法让 XeTeX 模拟 LuaTeX 制作 CMap 条目的方式?
  2. 如果没有,是否有办法编辑字体删除任何对私人使用区域的引用,这些引用可能会“诱使” XeTeX 做出这些不正确的 CMap 条目?
  3. 如果以上方法都行不通,那么有没有办法编辑 XeTeX 制作的 PDF 中的 CMap 条目呢?自动地无需运行 LuaTeX?

编辑:由于 Jörg 询问,下面是我进行“CMap 移植”的方法:

  1. test.tex创建一个包含以下内容的文件:

    \documentclass{article}
    \usepackage{fontspec}
    \setmainfont[Ligatures=TeX,Numbers={OldStyle,Proportional}]{Minion Pro}
    \begin{document}
    The \mbox{\addfontfeatures{Letters=UppercaseSmallCaps}NATO} office 1234
    \end{document}
    
  2. 使用以下方法编译xelatex lualatex并使用以下命令解压缩每个 PDF pdftk

    xelatex test
    mv test.pdf test_x.pdf
    lualatex test
    mv test.pdf test_l.pdf
    pdftk test_x.pdf output test_xu.pdf uncompress
    pdftk test_l.pdf output test_lu.pdf uncompress
    
  3. 文本编辑器并查找上面的部分。从 XeTeX 的 PDF 中删除该部分,并将其替换为 LuaTeX 的 PDF 中的等效部分(从begincodespacerangeendcmap)。

  4. PDF 现在已损坏,但pdftk可以修复它:

    pdftk test_xu.pdf output test_xf.pdf
    

现在test_xf.pdf将有正确的复制文本。这是一个简洁的概念验证,但由于以下几个原因,它毫无用处:

  • 你必须在 XeTeX 中编译LuaTeX。如果我的文件全部用 LuaTeX 编译,那么我只需使用 LuaTeX 就可以了。无论如何,这是理想的解决方案。

  • 您无法制作一个在 LuaTeX 中编译的“密钥文件”,然后将其 CMap 放入您使用 XeTeX 制作的每个 PDF 中,因为 XeTeX 似乎会在每次更改文件时分配随机输入代码(例如,,,<0044><0046><05C9>移植使用不同输入代码集的 CMap 会导致可以选择的字符。

  • 如果您使用多种字体,则需要为每种字体修复 CMap。这甚至适用于两种不同光学尺寸的同一种字体。

因此,我认为唯一可行的方法是,如果有人制作一个程序,该程序具有内置的字体及其有问题的 PUA 引用列表,它将逐行检查 PDF 中的每个 CMap 部分,根据目标识别 PUA 引用,然后根据列表更改目标。但这似乎工作量太大,而且在某个时候你只需要迁移到 LuaTeX

答案1

关于 PUA 编码的第二个问题的部分答案:

您可以使用 删除 PUA 编码ttx,该工具包含在OpenType 的 Adob​​e 字体开发工具包 (AFDKO)

然而,新字体(例如 Arno Pro)根本没有针对小型大写字母的 PUA 编码,但编译像您这样的文档仍然会导致小型大写字母无法搜索。因此,Jonathan Kews 提出的观点这里不幸的是,这是错的。错误不是 PUA 编码,而是 XeTeX 生成的错误 cmap。

话虽如此,您在问题中表示,您可以将 LuaTeX 生成的正确 cmap 移植到 XeTeX 生成的错误映射中。也许一种解决方法是为每个可能的字形创建一个正确的 cmap,然后将其用于 XeTeX。当然,这将完全取决于字体(和字体修订),但它应该适合您的私人目的。

不幸的是我无法尝试,因为我不知道如何“移植” cmap。你能详细说明一下你是怎么做到的吗?

编辑:我刚刚意识到一切都完美地JunicodeEB 加拉蒙德(当您单独指定 SC 字体时),即类似于:

\documentclass{article}

\usepackage{fontspec}
\setmainfont{Junicode}

\begin{document}

{\addfontfeature{Letters=UppercaseSmallCaps}DIE STRAßE IST ZU SCHMAL FÜR AUTOS.

{\addfontfeatures{Numbers=OldStyle}12345}

\end{document}

与可搜索 PDF 完美编译。也许我放弃尝试去理解发生了什么……

相关内容