我在用用户定义的 whatsit 标记数学内容(在这个例子中,我将讨论简单的上标)时遇到了麻烦。如果 whatsit 位于字符之间(通常应放置 kern),则不会显示字体字距调整。
标记上标是在mlist_to_hlist
回调中完成的,稍后(在pre_output_filter
回调中)我正在处理节点列表,我需要知道上标从哪里开始/结束某物用它。
luatex 文档没有过多提及用户定义的 whatsis,但它们似乎应该是虚拟的,不应该影响输出。我尝试通过创建node.kerning()
并添加到正确的位置来修复字距调整,但随后我需要一些如何重新计算所有外部框(hlist、vlist)。kerning
我想使用回调可以做一些事情,但它似乎现在可以显示数学转换的节点。我只看到hlist
节点,但它没有头。
问题:有没有一种安全的方法可以在不影响输出的情况下在数学中添加用户定义的 whatsit。或者有没有另一种方法可以在数学节点中标记一些位置并将它们放入 pre_output_filter 中。
测试.tex
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{luatexbase}
\directlua{dofile("mathsup.lua")}
\begin{document}
\loggingall
$$ xdf$$
$$ xdf^2 $$
\end{document}
mathsup.lua
local USER_MARK = node.new("whatsit","user_defined")
USER_MARK.type = 115
USER_MARK.value = "0"
local function tag_superscript (h, d, p)
for n in node.traverse(h) do
if n.sup then
-- tagging superscript Begin and End
local A = node.copy(USER_MARK)
A.value = "pre_superscript"
h = node.insert_before(h, n, A)
local B = node.copy(USER_MARK)
B.value = "post_superscript"
node.insert_after(h, n, B)
end
end
return node.mlist_to_hlist(h, d, p)
end
luatexbase.add_to_callback('mlist_to_hlist', tag_superscript, 'Tag superscript')
在第一个显示器的输出中有\kern-1.66667
:
...\hbox(6.94444+1.94444)x15.22572, shifted 164.88715, direction TLT
....\OML/cmm/m/it/10 x
....\OML/cmm/m/it/10 d
....\kern-1.66667 (font)
....\OML/cmm/m/it/10 f
....\kern1.0764 (italic)
在第二个显示的输出中缺少 kern:
...\hbox(8.64003+1.94444)x21.37852, shifted 161.81075, direction TLT
....\OML/cmm/m/it/10 x
....\OML/cmm/m/it/10 d
....\whatsit0="pre_superscript"
....\OML/cmm/m/it/10 f
....\kern1.0764 (italic)
....\hbox(4.51111+0.0)x4.48613, shifted -4.12892, direction TLT
.....\OT1/cmr/m/n/7 2
....\whatsit0="post_superscript"
答案1
您可以使用节点属性来标记一些节点:
local sup_attr = luatexbase.new_attribute("sup_attr")
local glyph_id = node.id "glyph"
local hlist_id = node.id "hlist"
local vlist_id = node.id "vlist"
local function tag_superscript (h, d, p)
for n in node.traverse(h) do
if n.sup then
node.set_attribute(n.sup, sup_attr, 1)
end
end
return node.mlist_to_hlist(h, d, p)
end
local uchar = unicode.utf8.char
local function traverse_hlist(head, groupcode)
for n in node.traverse(head) do
local id = n.id
if id == glyph_id and node.has_attribute(n, sup_attr) then
print("here is a subscript", uchar(n.char), node.get_attribute(n, sup_attr))
-- do your stuff here
node.unset_attribute(n, sup_attr)
elseif id == hlist_id or id == vlist_id then
traverse_hlist(n.head)
end
end
return head
end
luatexbase.add_to_callback('mlist_to_hlist', tag_superscript, 'Tag superscript')
luatexbase.add_to_callback("pre_linebreak_filter", traverse_hlist, "Find superscript")
luatexbase.add_to_callback("hpack_filter", traverse_hlist, "Find superscript")
luatexbase.add_to_callback("vpack_filter", traverse_hlist, "Find superscript")
自定义属性使用 定义luatexbase.new_attribute("sup_attr")
,在具有 字段的数学节点中设置sup
。属性直接设置为sup
字段中的节点。
在节点遍历回调中,我们正在寻找已设置属性的字形。您可以在此处执行您的操作。然后删除该属性,以防止多次执行节点处理。
请注意,您的特定示例由 处理vpack_filter
,因为pre_linebreak_filter
它不处理显示数学。