LuaTeX:天城体字形顺序在 tex 的内部节点列表中被反转,如何在遍历字形节点时恢复正确顺序?

LuaTeX:天城体字形顺序在 tex 的内部节点列表中被反转,如何在遍历字形节点时恢复正确顺序?

注意:此问题中讨论的问题可能不仅影响天城文,还会影响其他脚本,这些脚本的字符(逻辑/类型)和字形(表示/排版)顺序在某些字符序列子集上被反转/重新排序。

在梵文中,元音附标文字书写系统, 一些元音符号(如拉丁字母中的重音符号)在辅音后输入的字符会改变辅音的形状,使其占据其左侧的空间,同时将辅音字形推向其右侧(尽管它是一个从左到右的书写/打字系统)。[1] LuaTeX 生成的 PDF 适合阅读和打印。尽管它并不总是[2] 生成的 PDF(对于梵文)适合搜索或将文本复制到文本编辑器,即使在最简单的Hello World-type 测试中(我已在下面添加)。注意:这个问题不一定只是关于正确复制/搜索文本,请在发表回复之前进一步阅读。我在测试我的和用户时发现了这一点米哈尔-h21的文本提取技术从 TeX 框中提取文本。该技术很简单:在 TeX 设置框后,遍历其节点列表以查找并连接所有 unicode 字符,以获取框中设置的文本的 unicode 字符串。

让我们举一个例子,其中在辅音之后输入的元音符号“似乎”在辅音之前:Hello पिताजी。在此文本中,第一个辅音-元音对पि按以下顺序输入:(辅音),然后ि(元音符号);但正如您所见,结果文本(正确地)似乎具有相反的表示顺序:(पि好像ि在之前)。您可以在文本编辑器中尝试此操作以查看魔术。现在让我们讨论使用 LuaLaTeX 和包在 pdf 中排版此文本的选项,以及复制/搜索和文本提取的相关问题。Hello पिताजीfontspec下面示例中使用的字体是 Noto Sans Devanagari,可用于 在这里下载。 我在用Adobe Acrobat Reader DC(免费)尝试从 pdf 复制并搜索,因为并非所有 pdf 阅读器都对非拉丁脚本有良好的支持(您可能会遇到从其他 pdf 阅读器复制粘贴非拉丁文本的问题)。

Fontspec with Renderer=Node(默认值为Renderer):此模式在复制/搜索时似乎特别不合适,我不确定是否有任何方法可以解读梵文文本的真实字形顺序。对于我们的测试文本Hello पिताजी,如果您将文本(从生成的 pdf)复制并粘贴到文本编辑器中,它将显示为Hello िपताजी。问题的根源在于,在此文本的内部节点列表表示中,TeX 巧妙地将 [ , ि] 的顺序交换为 [ ि, ],就像排版输出ि出现在 的左侧一样。但在这样做的同时,它还将这种错误的字形顺序“嵌入”到 pdf 中。因此,在搜索 pdf 时पि不会产生匹配,而从 pdf 复制时िप会复制 而不是预期的पि。最后,在遍历字形节点时,由于 TeX 确实更改了字形的内部顺序,因此提取的文本也有िप而不是पि。所以问题Renderer=Node是:有没有办法在遍历节点列表时解读字形的真实顺序?这将有助于提取文本并以其他方式对其进行操作。有没有办法生成正确的 PDF,其中梵文文本可以像拉丁字母文本一样被正确搜索/复制?

Fontspec with Renderer=HarfBuzz(new):至少在这个小测试用例中,此模式似乎可以生成正确的 pdf 来搜索/复制文本。我仍在尝试弄清楚如何通过遍历节点来正确提取文本。节点列表的结构不同,我认为可能存在解决方案。所以问题是Renderer=HarfBuzz:我们应该查看节点列表中的哪些字段以正确的顺序提取文本?fontspec 文档说“对 Harfbuzz 渲染器的支持是初步的,可能会随着时间的推移而改进。”,此外,我隐约记得(来自 TUG-2020)此渲染器在Node模式上有一些限制。有人可以列出最严重的限制是什么吗?fontspec 的作者在上面的摘录中所说的“初步”和“可能”是什么意思?

以下是的测试代码Renderer=Node

% >>lualatex testdevanode.tex
\documentclass{article}
\usepackage[lmargin=0.5in,tmargin=0.5in,rmargin=0.5in,bmargin=0.5in]{geometry}
\usepackage{fontspec}
\usepackage[callback={}]{nodetree}

%\newfontscript{Devanagari}{deva,dev2}
\newfontfamily{\devanagarifam}{Noto Sans Devanagari}[Script=Devanagari, Scale=1, Renderer=Node]

\begin{document}

    \NodetreeRegisterCallback{hpack_filter}

    \setbox0=\hbox{Hello \devanagarifam पिताजी}

    \box0

    \NodetreeUnregisterCallback{hpack_filter}

\end{document}

对于Renderer=HarfBuzz(ctan 版本的 nodetree 遇到了错误,Renderer=HarfBuzz因此它已被注释掉,如果您从其下载并使用最新版本,则可以取消注释它GitHub 重新定位):

% >>lualatex testdevaharf.tex
\documentclass{article}
\usepackage[lmargin=0.5in,tmargin=0.5in,rmargin=0.5in,bmargin=0.5in]{geometry}
\usepackage{fontspec}
% \usepackage[callback={}]{nodetree}

\newfontfamily{\devanagarifam}{Noto Sans Devanagari}[Script=Devanagari, Scale=1, Renderer=HarfBuzz]

\begin{document}

    % \NodetreeRegisterCallback{hpack_filter}

    \setbox0=\hbox{Hello \devanagarifam पिताजी}

    \box0

    % \NodetreeUnregisterCallback{hpack_filter}

\end{document}

更新:附上相关摘录Unicode 标准规范 v13.0 第 12 章确认Node渲染器已违反规定。该文档的链接由用户指向戴维斯洛

摘录自 Unicode 标准规范 13.0,其中展示了依赖元音的排序规则

[1] 当查看组成声音单位的组成字形(我们以后称之为辅音-元音对)时,对于受过拉丁字母阅读训练的人来说,可能觉得元音必须在辅音之前输入,但事实并非如此。

[2] 下面我们将讨论一种方法,至少在这个测试示例中,这种方法似乎可以生成适合复制梵文文本的 PDF。不过,它可能需要更多测试。

相关内容