LuaTeX 节点库:垂直粘合/内核在手动制作的节点列表中不起作用,缺少什么?

LuaTeX 节点库:垂直粘合/内核在手动制作的节点列表中不起作用,缺少什么?

这是一个 LuaTeX 节点库/节点列表问题。

在下面的代码中,我尝试排版一个手动制作的节点列表。为了添加换行符,我添加了一个惩罚节点,这样就可以正常工作(即换行符在该点处)。但是当我在换行符后添加垂直粘连/字距时,它实际上并没有添加任何垂直空间。我哪里做错了?需要哪些节点来告诉换行符例程添加垂直空间?我期望的行为类似于 LaTeX 的宏\vspace{25pt}\\[25pt]

旁注 lua 问题:1)require加载 lua 文件的方式可以吗?我的意思是,如果我的local变量名称与我加载的另一个 lua 文件require(例如变量)发生冲突,该怎么办local head?2) 除了将函数设为全局函数外,有没有办法使用linebreak.前缀之类的东西来调用它们,以避免与具有相同名称函数的其他 lua 文件发生名称冲突?

更新:上面的“旁注”问题现在作为单独的问题进行讨论这里,阅读此问题时请忽略上面的“Sidenote lua 问题”,因为它们与此问题无关。

屏幕截图(我预计第一行后有额外的 25pt 或 50pt 垂直空间): 输出截图

换行符.tex:

>>> lualatex linebreak.tex
\documentclass{article}
\directlua{require"linebreak.lua"}
\begin{document}
\raggedright
\directlua{
    initialize()
    addchars('H')
    addchars('e')
    addchars('l')
    addchars('l')
    addchars('o')
    addchars(' ')
    addchars('W')
    addchars('o')
    addchars('r')
    addchars('l')
    addchars('d')
    addpenalty(1,-10000) % Add line break, works fine!
    addglue(1,25*65536) % XXX: Add vertical glue, doesn't work!
    addkern(1,25*65536) % XXX: Add vertical kern, doesn't work!
    addchars(' ')
    addchars('H')
    addchars('e')
    addchars('y')
    writeparagraph()
}
\end{document}

linebreak.lua:

local glyph_id = node.id("glyph")
local glue_id  = node.id("glue")
local kern_id  = node.id("kern")
local penalty_id = node.id("penalty")
local current_font = font.current()
local font_parameters = font.getfont(current_font).parameters
local n, head, last

function addchars(c)
  for s in string.utfvalues(c) do
    local char = unicode.utf8.char(s)
    if unicode.utf8.match(char,"%s") then
      -- its a space
      n = node.new(glue_id)
      n.width   = font_parameters.space
      n.shrink  = font_parameters.space_shrink
      n.stretch = font_parameters.space_stretch
    else -- a glyph
      n = node.new(glyph_id)
      n.font = current_font
      n.subtype = 1
      n.char = s
      n.lang = tex.language
      n.uchyph = 1
      n.left = tex.lefthyphenmin
      n.right = tex.righthyphenmin
    end
    last.next = n
    last = n
  end
  return last
end

function addpenalty(s,p)
    n = node.new(penalty_id)
    n.subtype = s or 0
    n.penalty = p or 0
    last.next = n
    last = n
    return n
end

function addkern(s,p)
    n = node.new(kern_id)
    n.subtype = s or 0
    n.kern = p or 0
    last.next = n
    last = n
    return n
end

function addglue(s,a,b,c,d,e)
    n = node.new(glue_id)
    n.subtype = s
    n.width = a or 0
    n.stretch = b or 0
    n.shrink = c or 0
    n.stretch_order = d or 0
    n.shrink_order = e or 0
    last.next = n
    last = n
    return n
end

function initialize()
    -- add parindent glue in the beginning, create head node
    head = node.new("glue")
    head.width = tex.parindent
    last = head
end

function writeparagraph()
    -- append a penalty and parfillskip glue at the end of list
    addpenalty(0,10000)
    addglue(15,0,tex.parfillskip.stretch,tex.parfillskip.stretch_order)
    -- create prev pointers
    node.slide(head)
    -- hyphenate
    lang.hyphenate(head)
    -- take care of fonts, kerning, ligature, etc
    head = nodes.simple_font_handler(head)
    -- call tex linebreaking, write to pdf
    tex.write(tex.linebreak(head))
    -- initize pointers
    head = nil
    last = nil
end

答案1

基于大卫·卡莱尔对我的问题的评论,我添加了一个带有垂直粘连的调整节点。现在输出符合要求。以下是屏幕截图和代码:

截图显示了修改后的代码的输出

修改后的linebreak.tex:

\documentclass{article}
\directlua{require"linebreak.lua"}
\begin{document}
\raggedright
\directlua{
    initialize()
    addchars('H')
    addchars('e')
    addchars('l')
    addchars('l')
    addchars('o')
    addchars(' ')
    addchars('W')
    addchars('o')
    addchars('r')
    addchars('l')
    addchars('d')
    addpenalty(1,-10000) % Add line break
    vspace(25*65536) % Add vspace
    addchars('H')
    addchars('e')
    addchars('y')
    writeparagraph()
}
\end{document}

修改后的linebreak.lua:

local glyph_id = node.id("glyph")
local glue_id  = node.id("glue")
local kern_id  = node.id("kern")
local penalty_id = node.id("penalty")
local adjust_id  = node.id("adjust")
local current_font = font.current()
local font_parameters = font.getfont(current_font).parameters
local n, head, last

function addchars(c)
  for s in string.utfvalues(c) do
    local char = unicode.utf8.char(s)
    if unicode.utf8.match(char,"%s") then
      -- its a space
      n = node.new(glue_id)
      n.width   = font_parameters.space
      n.shrink  = font_parameters.space_shrink
      n.stretch = font_parameters.space_stretch
    else -- a glyph
      n = node.new(glyph_id)
      n.font = current_font
      n.subtype = 1
      n.char = s
      n.lang = tex.language
      n.uchyph = 1
      n.left = tex.lefthyphenmin
      n.right = tex.righthyphenmin
    end
    last.next = n
    last = n
  end
  return last
end

function addpenalty(s,p)
    n = node.new(penalty_id)
    n.subtype = s or 0
    n.penalty = p or 0
    last.next = n
    last = n
    return n
end

function addkern(s,p)
    n = node.new(kern_id)
    n.subtype = s or 0
    n.kern = p or 0
    last.next = n
    last = n
    return n
end

function addadjust(s,h)
    n = node.new(adjust_id)
    n.subtype = s or 0
    n.head = h
    last.next = n
    last = n
    return n
end

function vspace(s)
    g1 = node.new(glue_id)
    g1.width = s
    g1.subtype = 0
    addadjust(1,g1)
end

function addglue(s,a,b,c,d,e)
    n = node.new(glue_id)
    n.subtype = s
    n.width = a or 0
    n.stretch = b or 0
    n.shrink = c or 0
    n.stretch_order = d or 0
    n.shrink_order = e or 0
    last.next = n
    last = n
    return n
end

function initialize()
    -- add parindent glue in the beginning, create head node
    head = node.new("glue")
    head.width = tex.parindent
    last = head
end

function writeparagraph()
    -- append a penalty and the parfillskip glue at the end of list
    addpenalty(0,10000)
    addglue(15,0,tex.parfillskip.stretch,tex.parfillskip.stretch_order)
    -- create prev pointers
    node.slide(head)
    -- hyphenate
    lang.hyphenate(head)
    -- take care of fonts, kerning, ligature, etc
    head = nodes.simple_font_handler(head)
    -- call linebreaking
    tex.write(tex.linebreak(head))
    -- initize pointers
    head = nil
    last = nil
end

相关内容