LuaLaTeX: ノード ライブラリを使用して、複数段組環境 (vbox のシリーズ) の実際の高さを見つける

LuaLaTeX: ノード ライブラリを使用して、複数段組環境 (vbox のシリーズ) の実際の高さを見つける

LuaTeX ノード ライブラリを使用して、ミニ ページの multicols 環境のコンテンツの実際の高さ (およびその他の寸法) を見つけるにはどうすればよいでしょうか。これまでの luatex ノード ライブラリの実験では、post_linebreak_filter を使用して hlist ノードを操作できましたが、vlist ノードにアクセスしてクエリを実行する方法がわかりません。luatex のマニュアルによると、を使用してノードの寸法をクエリできることがわかりますnode.dimensions(<node> n)。ただし、ミニ ページのコンテンツをトラバースして、multicols 環境によって出力される vboxes に到達する方法がわかりません。それらをトラバースすることで、vboxes の最大の高さを見つけて、実際の高さを決定できる可能性があります。

ノードリスト可視化ツールがどう機能するかについて、誰かにアドバイスをいただければ助かります。 https://gist.github.com/pgundlach/556247ミニページの内容を視覚化するために使用できます。(注: 外部リンクについてはご容赦ください。これは標準的な視覚化ツールの一種のようですが、ctan ではパッケージとして利用できません)

これが私のテスト コードです。その下には出力のスクリーンショットがあります。multicols 環境を囲む minipage の指定値サイズ (4 インチ) とは異なる 3 列テキストの実際の寸法を見つけるのが楽しみです。

% 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.tailLua コマンドの前に TeX が挿入した最後のノードにアクセスするために を使用することをお勧めします。これは、探しているノードが見つかるまでスキャンバックするための開始点として使用できます。例: (ここでは、hlist3 つの すべてを含むを測定していますvlistが、これは最大 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 によっていくらかのスペースが挿入されるためです。このスペースは points と getvpos を使用する場合には含まれますが、raw ボックスを表示する場合には含まれません。

関連情報