我对 TeX 中的页面构建器感到困惑:
- TeX 何时更新
\pagetotal
尺寸? - TeX 何时更新
\tracingpages
结果? - 为什么 TeX 不同时更新它们两个?
以下是一些测试代码及日志:
\documentclass{article}
\tracingpages=1
\newcommand\mypagedim[1]{%
\message{------------------ \unexpanded{#1} ----------------^^J}%
#1%
\message{\string\pagetotal=\the\pagetotal\space\string\pagegoal=\the\pagegoal^^J}%
\ignorespaces
}
\newcommand\myloghrule{%
\message{------------------------------------------------^^J}%
}
\begin{document}
\message{^^J}
\mypagedim{A\par}
\mypagedim{B\par}
\mypagedim{C\par}
\myloghrule
\newpage
\message{^^J}
\mypagedim{\leavevmode}
\mypagedim{A\par}
\mypagedim{\leavevmode}
\mypagedim{B\par}
\mypagedim{\leavevmode}
\mypagedim{C\par}
\mypagedim{\leavevmode}
\myloghrule
\newpage
\message{^^J}
\mypagedim{\penalty 0\relax}
\mypagedim{A\par}
\mypagedim{\penalty 0\relax}
\mypagedim{B\par}
\mypagedim{\penalty 0\relax}
\mypagedim{C\par}
\mypagedim{\penalty 0\relax}
\myloghrule
\newpage
\message{^^J}
\mypagedim{\penalty 10000\relax}
\mypagedim{A\par}
\mypagedim{\penalty 10000\relax}
\mypagedim{B\par}
\mypagedim{\penalty 10000\relax}
\mypagedim{C\par}
\mypagedim{\penalty 10000\relax}
\myloghrule
\newpage
\message{^^J}
\mypagedim{\hrule height 1pt\relax}
\mypagedim{A\par}
\mypagedim{\hrule height 1pt\relax}
\mypagedim{B\par}
\mypagedim{\hrule height 1pt\relax}
\mypagedim{C\par}
\mypagedim{\hrule height 1pt\relax}
\myloghrule
\newpage
\message{^^J}
\mypagedim{\hrule height 1pt\relax}
\mypagedim{\vskip 12pt\relax}
\mypagedim{\hrule height 1pt\relax}
\mypagedim{\vskip 12pt\relax}
\mypagedim{\hrule height 1pt\relax}
\mypagedim{\vskip 12pt\relax}
\mypagedim{\hrule height 1pt\relax}
\myloghrule
\newpage
\message{^^J}
\mypagedim{\hrule height 1pt\relax}
\mypagedim{\vskip 12pt\relax}
\mypagedim{\penalty 0\relax}
\mypagedim{\hrule height 1pt\relax}
\mypagedim{\vskip 12pt\relax}
\mypagedim{\penalty 0\relax}
\mypagedim{\hrule height 1pt\relax}
\mypagedim{\vskip 12pt\relax}
\mypagedim{\penalty 0\relax}
\mypagedim{\hrule height 1pt\relax}
\myloghrule
\end{document}
------------------ A\par ----------------
%% goal height=550.0, max depth=5.0
% t=0.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=10.0pt \pagegoal=550.0pt
------------------ B\par ----------------
% t=10.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=22.0pt \pagegoal=550.0pt
------------------ C\par ----------------
% t=22.0 plus 1.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=34.0pt \pagegoal=550.0pt
------------------------------------------------
% t=34.0 plus 2.0 g=550.0 b=10000 p=0 c=100000#
% t=34.0 plus 2.0 plus 1.0fil g=550.0 b=0 p=-10000 c=-10000#
[1]
------------------ \leavevmode ----------------
\pagetotal=0.0pt \pagegoal=16383.99998pt
------------------ A\par ----------------
%% goal height=550.0, max depth=5.0
\pagetotal=10.0pt \pagegoal=550.0pt
------------------ \leavevmode ----------------
% t=10.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=10.0pt \pagegoal=550.0pt
------------------ B\par ----------------
\pagetotal=22.0pt \pagegoal=550.0pt
------------------ \leavevmode ----------------
% t=22.0 plus 1.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=22.0pt \pagegoal=550.0pt
------------------ C\par ----------------
\pagetotal=34.0pt \pagegoal=550.0pt
------------------ \leavevmode ----------------
% t=34.0 plus 2.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=34.0pt \pagegoal=550.0pt
------------------------------------------------
% t=46.0 plus 3.0 g=550.0 b=10000 p=0 c=100000#
% t=46.0 plus 3.0 plus 1.0fil g=550.0 b=0 p=-10000 c=-10000#
[2]
------------------ \penalty 0\relax ----------------
\pagetotal=0.0pt \pagegoal=16383.99998pt
------------------ A\par ----------------
%% goal height=550.0, max depth=5.0
\pagetotal=10.0pt \pagegoal=550.0pt
------------------ \penalty 0\relax ----------------
% t=10.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=10.0pt \pagegoal=550.0pt
------------------ B\par ----------------
\pagetotal=22.0pt \pagegoal=550.0pt
------------------ \penalty 0\relax ----------------
% t=22.0 plus 1.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=22.0pt \pagegoal=550.0pt
------------------ C\par ----------------
\pagetotal=34.0pt \pagegoal=550.0pt
------------------ \penalty 0\relax ----------------
% t=34.0 plus 2.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=34.0pt \pagegoal=550.0pt
------------------------------------------------
% t=34.0 plus 2.0 plus 1.0fil g=550.0 b=0 p=-10000 c=-10000#
[3]
------------------ \penalty 10000\relax ----------------
\pagetotal=0.0pt \pagegoal=16383.99998pt
------------------ A\par ----------------
%% goal height=550.0, max depth=5.0
\pagetotal=10.0pt \pagegoal=550.0pt
------------------ \penalty 10000\relax ----------------
\pagetotal=10.0pt \pagegoal=550.0pt
------------------ B\par ----------------
\pagetotal=22.0pt \pagegoal=550.0pt
------------------ \penalty 10000\relax ----------------
\pagetotal=22.0pt \pagegoal=550.0pt
------------------ C\par ----------------
\pagetotal=34.0pt \pagegoal=550.0pt
------------------ \penalty 10000\relax ----------------
\pagetotal=34.0pt \pagegoal=550.0pt
------------------------------------------------
% t=34.0 plus 2.0 plus 1.0fil g=550.0 b=0 p=-10000 c=-10000#
[4]
------------------ \hrule height 1pt\relax ----------------
\pagetotal=0.0pt \pagegoal=16383.99998pt
------------------ A\par ----------------
%% goal height=550.0, max depth=5.0
% t=10.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=16.83331pt \pagegoal=550.0pt
------------------ \hrule height 1pt\relax ----------------
\pagetotal=16.83331pt \pagegoal=550.0pt
------------------ B\par ----------------
% t=17.83331 plus 1.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=24.66663pt \pagegoal=550.0pt
------------------ \hrule height 1pt\relax ----------------
\pagetotal=24.66663pt \pagegoal=550.0pt
------------------ C\par ----------------
% t=25.66663 plus 2.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=32.49994pt \pagegoal=550.0pt
------------------ \hrule height 1pt\relax ----------------
\pagetotal=32.49994pt \pagegoal=550.0pt
------------------------------------------------
% t=33.49994 plus 3.0 g=550.0 b=10000 p=0 c=100000#
% t=33.49994 plus 3.0 plus 1.0fil g=550.0 b=0 p=-10000 c=-10000#
[5]
------------------ \hrule height 1pt\relax ----------------
\pagetotal=0.0pt \pagegoal=16383.99998pt
------------------ \vskip 12pt\relax ----------------
\pagetotal=0.0pt \pagegoal=16383.99998pt
------------------ \hrule height 1pt\relax ----------------
\pagetotal=0.0pt \pagegoal=16383.99998pt
------------------ \vskip 12pt\relax ----------------
\pagetotal=0.0pt \pagegoal=16383.99998pt
------------------ \hrule height 1pt\relax ----------------
\pagetotal=0.0pt \pagegoal=16383.99998pt
------------------ \vskip 12pt\relax ----------------
\pagetotal=0.0pt \pagegoal=16383.99998pt
------------------ \hrule height 1pt\relax ----------------
\pagetotal=0.0pt \pagegoal=16383.99998pt
------------------------------------------------
%% goal height=550.0, max depth=5.0
% t=10.0 g=550.0 b=10000 p=0 c=100000#
% t=23.0 g=550.0 b=10000 p=0 c=100000#
% t=36.0 g=550.0 b=10000 p=0 c=100000#
% t=49.0 g=550.0 b=10000 p=0 c=100000#
% t=49.0 plus 1.0fil g=550.0 b=0 p=-10000 c=-10000#
[6]
------------------ \hrule height 1pt\relax ----------------
\pagetotal=0.0pt \pagegoal=16383.99998pt
------------------ \vskip 12pt\relax ----------------
\pagetotal=0.0pt \pagegoal=16383.99998pt
------------------ \penalty 0\relax ----------------
%% goal height=550.0, max depth=5.0
% t=10.0 g=550.0 b=10000 p=0 c=100000#
% t=22.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=22.0pt \pagegoal=550.0pt
------------------ \hrule height 1pt\relax ----------------
\pagetotal=22.0pt \pagegoal=550.0pt
------------------ \vskip 12pt\relax ----------------
\pagetotal=22.0pt \pagegoal=550.0pt
------------------ \penalty 0\relax ----------------
% t=23.0 g=550.0 b=10000 p=0 c=100000#
% t=35.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=35.0pt \pagegoal=550.0pt
------------------ \hrule height 1pt\relax ----------------
\pagetotal=35.0pt \pagegoal=550.0pt
------------------ \vskip 12pt\relax ----------------
\pagetotal=35.0pt \pagegoal=550.0pt
------------------ \penalty 0\relax ----------------
% t=36.0 g=550.0 b=10000 p=0 c=100000#
% t=48.0 g=550.0 b=10000 p=0 c=100000#
\pagetotal=48.0pt \pagegoal=550.0pt
------------------ \hrule height 1pt\relax ----------------
\pagetotal=48.0pt \pagegoal=550.0pt
------------------------------------------------
% t=49.0 g=550.0 b=10000 p=0 c=100000#
% t=49.0 plus 1.0fil g=550.0 b=0 p=-10000 c=-10000#
[7]
答案1
TeX
\pagetotal
每次“执行页面构建器”时都会更新,也就是 TeX 将“贡献列表”上的所有项目移至“当前页面”时。贡献列表是 TeX 尚未考虑添加到下一页的内容。当前页面是 TeX 已考虑添加到下一页的内容(但实际上可能不会出现在下一页上)。在第 122 页,TeXBook 列出了 TeX 执行页面构建器的情况:(a) 在段落的开头或结尾,前提是该段落正在被添加到主垂直列表中。 (b) 在这样的段落中显示的等式的开头或结尾。 (c) 在
\halign
垂直模式下完成后。 (d) 在向主垂直列表添加一个框或惩罚或插入之后。 (e) 在一个\output
例程结束后。但是,请注意,当当前页面上没有框(或规则)时,TeX 会丢弃移动到当前页面的可丢弃项目,因此此时
\pagetotal
不一定会增加。每当在当前页面中添加合法断点时, TeX 都会记录
\tracingpages
一行。具体来说,TeX 通常会\tracingpages
在行间惩罚之后输出行,或者在行间惩罚之后不输出行间粘连之后的行,因为这些项目是合法的断点,至少在没有 的情况下是这样的\vadjust
。然而,TeX 不会不是\tracingpages
在代表段落行的水平盒子 (hbox) 之后输出行,因为盒子永远不是合法的断点。上面的最后一点解释了为什么值表面上与某些示例中的行
\pagetotal
不同步:段落为当前页面贡献的最后一项是代表最后一行的水平框(假设不出现在最后一行)。段落之后,此水平框的高度将并入,但没有合法的断点\tracingpages
\vadjust
\pagetotal
后该 hbox,因此没有\tracingpages
一条线会包含它的高度。您的其他示例可以通过确定页面构建器在何时运行,以及页面构建器在何时将合法断点从贡献列表移动到当前页面来解释。特别要注意的是,规则和跳过不会运行页面构建器,但惩罚会。您可能会发现这
\showlists
很有帮助。
这是一个简单的例子,我已注释以解释所有必要的细节。请注意,我编写步骤的顺序可能不是 TeX 的顺序实际上他们这样做。
\tracingpages=1
\hbox{A}
% 1. \hbox{A} added to contribution list, which causes...
% 2. Page builder exercised.
% 2.a. \topskip glue added to current page. No \tracingpages line is logged,
% because the \topskip glue is not preceded by a nondiscardable item, so
% it is not a legal breakpoint.
% 2.b. \hbox{A} moved to current page.
% 2.c. \pagetotal calculated based on \topskip and height of A.
\hbox{B}
% 1. Interline glue added to contribution list.
% 2. \hbox{B} added to contribution list, which causes...
% 3. Page builder exercised.
% 3.a. Interline glue moved to current page. This is a legal breakpoint, so
% a \tracingpages line is logged.
% 3.b. \hbox{B} moved to current page.
% 3.c. \pagetotal increased by depth of A, plus interline glue, plus height
% of B.
\vskip1pt
% 1. \vskip1pt added to contribution list. The page builder is *not* exercised,
% so a \tracingpages line is not yet logged.
\par
% 1. Page builder exercised.
% 1.a. \vskip1pt moved to current page. This is a legal breakpoint, so
% a \tracingpages line is logged.
% 1.b. \pagetotal is increased by the depth of B plus 1pt.
\hbox{C}
% 1. Interline glue added to contribution list.
% 2. \hbox{C} added to contribution list, which causes...
% 3. Page builder exercised.
% 3.a. Interline glue moved to current page. This time, the interline glue is
% not a legal breakpoint, because it is preceded by a discardable item,
% so no \tracingpages line is logged.
% 3.b. \hbox{C} moved to current page.
% 3.c. \pagetotal increased by interline glue plus height of C.
\bye
请注意,我曾经\par
强制执行页面构建器而不向主垂直列表添加任何内容。\par
经常被重新定义,因此您通常应该为此目的使用\endgraf
(它只是原始的别名 )。\par
答案2
根据 TexByTopic
"The main vertical list of TEX is divided in two parts: the ‘current page’ and the list of
‘recent contributions’. Any material that is added to the main vertical list is appended
to the recent contributions; the act of moving the recent contributions to the current
page is known as ‘exercising the page builder’."
当您只放置 hrules 和 vskips 时,它们都会保留在“最近贡献”列表中,并且当前页面的大小不会更新。只有在终点页面构建器才会运行,并且它们才会被放入主页中。当您放置诸如框或惩罚之类的材料时,它们几乎会立即移动到主页上。