
如何使用LuaTeX節點庫找到迷你頁面中multicols環境內容的真實高度(和其他尺寸)?到目前為止,在我對 luatex 節點庫的實驗中,我已經能夠使用 post_linebreak_filter 來處理 hlist 節點,但不知道如何存取 vlist 節點並查詢它們。從 luatex 手冊中,我看到可以使用 查詢節點的維度node.dimensions(<node> n)
。雖然我不知道如何遍歷 minipage 的內容以取得 multicols 環境輸出的 vboxes。透過遍歷它們,我可能會找到垂直盒子中的最大高度,以確定真實高度。
如果有人可以建議是否/如何使用節點清單視覺化工具,那將會有額外的幫助 https://gist.github.com/pgundlach/556247可用於視覺化小型頁面的內容。 (注意:請原諒外部鏈接,這似乎是一種標準可視化工具,但在 ctan 上不作為包提供)
這是我的測試程式碼,下面是輸出的螢幕截圖,我期待找到 3 列文字的真實尺寸,該尺寸與 multicols 環境周圍的 minipage (4in) 的指定值大小不同。
% lualatex vboxdimensions.tex
\documentclass[notitlepage,letterpaper]{article}
\usepackage{lua-visual-debug}
\usepackage[english]{babel}
\usepackage{blindtext}
\usepackage{multicol}
\begin{document}
\blindtext[1]\vspace{\baselineskip}
\noindent\begin{minipage}[t][4in][t]{\textwidth}%
% STARTPOINT for dimension measurement
\begin{multicols}{3}%
\blindtext[2]
\end{multicols}%
% ENDPOINT for dimension measurement
\end{minipage}
\blindtext[1]
\end{document}
答案1
在討論node
庫之前,進行此類測量的更簡單方法是比較前後頁面上的位置:
% lualatex vboxdimensions.tex
\documentclass[notitlepage,letterpaper]{article}
\usepackage{lua-visual-debug}
\usepackage[english]{babel}
\usepackage{blindtext}
\usepackage{multicol}
\begin{document}
\showoutput
\blindtext[1]\vspace{\baselineskip}
\noindent\begin{minipage}[t][4in][t]{\textwidth}%
% STARTPOINT for dimension measurement
\latelua{
assert(measurement_y == nil, "global variable already in use")
measurement_y = pdf.getvpos()
}%
\begin{multicols}{3}%
\blindtext[2]
\end{multicols}%
\latelua{
texio.write_nl(string.format("\csstring\%fin measured\string\n", (measurement_y - pdf.getvpos()) / tex.sp'1in'))
measurement_y = nil
}%
% ENDPOINT for dimension measurement
\end{minipage}
\blindtext[1]
\end{document}
如果你想使用節點庫,我建議使用tex.nest.top.tail
存取在某些 Lua 命令之前插入的最後一個 TeX 節點。這可以用作回掃的起點,直到找到您要尋找的節點。例如:(這裡我們測量hlist
包含所有三個vlist
s,這確實對應於最大 vlist 的高度。)
% lualatex vboxdimensions.tex
\documentclass[notitlepage,letterpaper]{article}
\usepackage{lua-visual-debug}
\usepackage[english]{babel}
\usepackage{blindtext}
\usepackage{multicol}
\begin{document}
\showoutput
\blindtext[1]\vspace{\baselineskip}
\noindent\begin{minipage}[t][4in][t]{\textwidth}%
% STARTPOINT for dimension measurement
\begin{multicols}{3}%
\blindtext[2]
\end{multicols}%
\directlua{
local hlist_id = node.id'hlist' % The id we are looking for
local last_tail = tex.nest.top.tail % Start at the end of the list TeX is working on
while last_tail.id \string~= hlist_id do last_tail = last_tail.prev end % Move to the previous node until a hlist is found
texio.write_nl(string.format("\csstring\%fin measured\string\n", (last_tail.height+last_tail.depth) / tex.sp'1in'))}%
% ENDPOINT for dimension measurement
\end{minipage}
\blindtext[1]
\end{document}
從這裡,您也可以使用 hlist 的 .head 成員來存取隱藏在其中的 vlist:
% lualatex vboxdimensions.tex
\documentclass[notitlepage,letterpaper]{article}
\usepackage{lua-visual-debug}
\usepackage[english]{babel}
\usepackage{blindtext}
\usepackage{multicol}
\begin{document}
\showoutput
\blindtext[1]\vspace{\baselineskip}
\noindent\begin{minipage}[t][4in][t]{\textwidth}%
% STARTPOINT for dimension measurement
\begin{multicols}{3}%
\blindtext[2]
\end{multicols}%
\directlua{
local hlist_id = node.id'hlist' % The id we are looking for
local last_tail = tex.nest.top.tail % Start at the end of the list TeX is working on
while last_tail.id \string~= hlist_id do last_tail = last_tail.prev end % Move to the previous node until a hlist is found
% Now last_tail is the hlist containing the vlists.
for n in node.traverse_id(node.id'vlist', last_tail.head) do
% Now n is one of the inner vlists.
texio.write_nl(string.format("Found column of height \csstring\%fin.",(n.height+n.depth)/tex.sp'1in'))
end}%
% ENDPOINT for dimension measurement
\end{minipage}
\blindtext[1]
\end{document}
您可能會注意到,尤其是第一個版本提供了更高的價值。原因是 multicols 插入了一些間距,這些間距在使用 point 和 getvpos 時包含在內,但在查看原始框時不包含在內。