这是我使用 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 中,问题就消失了!所以:
- 有没有办法让 XeTeX 模拟 LuaTeX 制作 CMap 条目的方式?
- 如果没有,是否有办法编辑字体删除任何对私人使用区域的引用,这些引用可能会“诱使” XeTeX 做出这些不正确的 CMap 条目?
- 如果以上方法都行不通,那么有没有办法编辑 XeTeX 制作的 PDF 中的 CMap 条目呢?自动地和无需运行 LuaTeX?
编辑:由于 Jörg 询问,下面是我进行“CMap 移植”的方法:
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}
使用以下方法编译
xelatex
和lualatex
并使用以下命令解压缩每个 PDFpdftk
: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
在文本编辑器并查找上面的部分。从 XeTeX 的 PDF 中删除该部分,并将其替换为 LuaTeX 的 PDF 中的等效部分(从
begincodespacerange
到endcmap
)。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 的 Adobe 字体开发工具包 (AFDKO)。
然而,新字体(例如 Arno Pro)根本没有针对小型大写字母的 PUA 编码,但编译像您这样的文档仍然会导致小型大写字母无法搜索。因此,Jonathan Kews 提出的观点这里不幸的是,这是错的。错误不是 PUA 编码,而是 XeTeX 生成的错误 cmap。
话虽如此,您在问题中表示,您可以将 LuaTeX 生成的正确 cmap 移植到 XeTeX 生成的错误映射中。也许一种解决方法是为每个可能的字形创建一个正确的 cmap,然后将其用于 XeTeX。当然,这将完全取决于字体(和字体修订),但它应该适合您的私人目的。
不幸的是我无法尝试,因为我不知道如何“移植” cmap。你能详细说明一下你是怎么做到的吗?
编辑:我刚刚意识到一切都完美地Junicode和EB 加拉蒙德(当您单独指定 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 完美编译。也许我放弃尝试去理解发生了什么……