我正在开发一个使用数据库内容生成多种语言 PDF 的系统。我目前正在研究亚美尼亚语。
到目前为止,我们开发的产品都使用了 pdfLaTeX。我制作了一种特殊的编码来处理亚美尼亚语,并使其全部正常工作,结果却发现 FreeSerif 中字形名称中带有下划线的五个连字符最终无法复制或搜索。例如,复制连字符 m_n_armenian 最终会得到“mn”,并且\pdfglyphtounicode
似乎无法覆盖将下划线分隔的 ASCII 字母视为复制和粘贴所需的目标字符的默认行为。
我尝试使用 XeLaTeX,但发现跨越多页的彩色脚注在第二页会失去颜色。pdfcolfoot 修复了 pdfLaTeX 中的这个问题,但 XeLaTeX 中没有所需的颜色堆栈。
我刚刚发现 LuaLaTeX 没有这个限制,所以我想看看它是否能满足我的要求。鉴于 LuaLaTeX 似乎是 pdfLaTeX 的继承者,如果 LuaLaTeX 可以完成我们需要做的所有事情,我们可能应该朝这个方向发展。
\documentclass[14pt]{memoir}
\usepackage{fontspec}
\setmainfont[Script=Armenian]{Freeserif}
\pdfcompresslevel=0
\begin{document}
ﬓ ﬔ ﬕ ﬖ ﬗ
մն մե մի վն մխ
\end{document}
上面的第一行文本包含所讨论的五个亚美尼亚连字符,即 Unicode 字符 FB13 至 FB17。第二行是组成这五个连字符的总共十个字符,范围从 0500 到 05FF。使用 LuaLaTeX 编译此文本,我最终正确显示了两行五个连字符。但是当我复制和粘贴时,我最终得到了两行五个连字符,而不是十个字符。
我想覆盖此默认行为。我希望 PDF 中的 cmap 指定:
<1BF9> <05740576>
<1BFA> <05740565>
<1BFB> <0574056B>
<1BFC> <057E0576>
<1BFD> <0574056D>
代替:
<1BF9> <1BFD> <FB13>
但我不知道如何通过 LuaLaTeX 改变 cmaps。我发现http://www.luatex.org/svn/branches/0.70.x/source/texk/web2c/luatexdir/font/tounicode.w但我不确定那里的功能是否可以通过宏访问。
我认为我需要让 PDF 的内容与数据库的内容保持一致。否则,有人可能会从数据库中获取内容并在 PDF 中搜索,但却永远找不到它,因为配对的十个字符会被连字符替换。
我该怎么办?可以通过 LuaLaTeX 修改 cmap 吗?我接下来要使用一种更难的语言,我想我需要对 cmap 进行这种级别的控制。
答案1
在序言中,包括:\usepackage{luacode}
。在 之前 \end{document}
,包括以下内容:
\begin{luacode*}
tounicodevalues = {
[64275] = "05740576",
[64276] = "05740565",
[64277] = "0574056B",
[64278] = "057E0576",
[64279] = "0574056D",
}
for i,f in font.each() do
if (string.match(f.name, "FreeSerif") and string.match(f.name, "script=armn")) then
for u, v in next, tounicodevalues do
f.characters[u].tounicode = v
end
font.fonts[i] = f
end
end
\end{luacode*}
为什么是之前\end{document}
?因为你希望在 LuaLaTeX 已经知道它实际要使用的所有字体之后执行此操作。
为什么要将例程限制为某些匹配的字体?这可以避免尝试更改已经访问过的字体(例如被禁止的 line10)的错误。
此代码可以包装在 TeX 宏中并放在前导码中,然后在 之前调用\end{document}
。此示例不使用 luacode 包:
\newcommand{\tounicode}[2][]{\directlua0{
tounicodevalues = {
[64275] = "05740576",
[64276] = "05740565",
[64277] = "0574056B",
[64278] = "057E0576",
[64279] = "0574056D",
}
for i,f in font.each() do
if (string.match(f.name, "#1") and string.match(f.name, "#2")) then
for u, v in next, tounicodevalues do
f.characters[u].tounicode = v
end
font.fonts[i] = f
end
end
}}
\begin{document}
ﬓ ﬔ ﬕ ﬖ ﬗ
\tounicode[script=armn]{FreeSerif}
\end{document}
使用 fontspec,我添加了字体功能,HyphenChar={1418}
将连字符更改为亚美尼亚连字符。这样做会导致使用上述函数时出现 altering-already-accessed-font 错误,除非使用可选参数(例如“script=armn”)添加其他匹配条件。
要找出您尝试匹配的字体名称,请将以下代码添加到上述函数中。
for i,f in font.each() do
texio.write_nl("["..i.."] => "..f.name)
end
答案2
LuaTeX 定义字体的机制提供了以下构建 /ToUnicode 条目的途径。以下文本取自第 7 节字体结构(LuaTeX beta 0.71.0 手册第 153 页):
tounicode 的用法如下:如果此字体在顶层指定了 tounicode=1,则 LuaTEX 将根据字符级 tounicode 字符串(如果可用)为 pdf 字体(或字体子集)构建一个 /ToUnicode 条目。如果字符没有合理的 Unicode 等效项,则不要提供字符串(没有空字符串)。如果未设置字体级 tounicode,则 LuaTEX 将根据您使用的 TEX 代码点构建 /ToUnicode,并且任何字符级 tounicode 都将被忽略。目前,字符串格式正是 Adobe CMap 文件所期望的格式(十六进制编码的 utf-16BE),减去封闭的尖括号。这可能会在将来发生变化。小例子:fi 连字符的 tounicode 将是 00660069。