LuaLaTeX:使用節點庫尋找 multicols 環境(一系列 vbox)的真實高度

LuaLaTeX:使用節點庫尋找 multicols 環境(一系列 vbox)的真實高度

如何使用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包含所有三個vlists,這確實對應於最大 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 時包含在內,但在查看原始框時不包含在內。

相關內容