如何定制 LuaLaTeX cmap?

如何定制 LuaLaTeX cmap?

我正在开发一个使用数据库内容生成多种语言 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 都将被忽略。目前,字符串格式正是 Adob​​e CMap 文件所期望的格式(十六进制编码的 utf-16BE),减去封闭的尖括号。这可能会在将来发生变化。小例子:fi 连字符的 tounicode 将是 00660069。

相关内容