为什么用户定义的 whatsit 会踢出字距调整?

为什么用户定义的 whatsit 会踢出字距调整?

我在用用户定义的 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它不处理显示数学。

相关内容