这是一个 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