以下是一些情况,当 vbox 中有内容时,基线跳跃有时存在,有时不存在。或者可能是其他原因导致了差异?
\setbox0\vbox{% halign is vertical mode material?
\halign{& \strut$#\hfil$\cr
a& b& c\cr
d& e& f\cr
g& h& i\cr}}% each cell expands out to \hbox{...
\setbox1\hbox{% valign is horizontal mode material?
\valign{& \hbox{\strut$#\hfil$}\cr
a& d& g\cr
b& e& h\cr
c& f& i\cr}}% each cell expands out to \vbox{\hbox{...
\hbox{\box0\box1}
\vbox{When there is just text inside a \vbox{vbox,}
it uses the whole hsize and indents}
\vbox{\hbox{except when}\hbox{it consists}\hbox{of consecutive}\hbox{hboxes}}
\bye
我多次遇到过这种情况,但从未真正了解发生了什么或如何解决它。
(问题为什么 \baselineskip 没有插入到 \unvbox 之前?可能与此有关?
答案1
让我们简化一下你的例子。重点在这里
\hsize=6cm % just to get a two line paragraph
\vbox{When there is just text inside a vbox
it uses the whole hsize and indents}
\vbox{\hbox{except when}\hbox{it consists}\hbox{of consecutive}\hbox{hboxes}}
A\vbox
的深度等于其中最后一个项目的深度。因此两个 vbox 的深度均为零,因为恰巧第一个框中的第二行没有降部,而 也是如此\hbox{hboxes}
。
其余部分都计入 的高度\vbox
。因此,当 TeX 想要将两个垂直框堆叠在一起时,它会计算行间粘连。但显然,第二个的高度\vbox
大于\baselineskip
,因此规则强制 TeX 插入\lineskip
粘连(默认值为 1pt)。
我们来看一张设置\lineskip
为20pt得到的图片,只是为了看看它是否插入:
我们该如何解决这个问题呢?答案如下:
\hsize=6cm % just to get a two line paragraph
\vbox{When there is just text inside a vbox
it uses the whole hsize and indents\strut}
\nointerlineskip
\vbox{\hbox{\strut except when}\hbox{it consists}\hbox{of consecutive}\hbox{hboxes}}
只需使用 抑制\baselineskip
- \lineskiplimit
-\lineskip
计算,并确保使用支柱正确分隔两条线即可。但是,如果上面的深度很大,或者下面的第一个框的高度很大,\nointerlineskip
则此方法不起作用。\vbox
\vbox
现在让我们来解决这个\halign
问题\valign
。输入
\setbox0=\vbox{% halign is vertical mode material
\halign{& \strut$#\hfil$\cr
a& b& c\cr
d& e& f\cr
g& h& i\cr}}% each cell expands out to \hbox{...
相当于
\setbox0=\vbox{
\hbox{\hskip0pt
\hbox to X{\strut$a\hfil$}\hskip0pt
\hbox to X{\strut$b\hfil$}\hskip0pt
\hbox to X{\strut$c\hfil$}\hskip0pt}
\hbox{\hskip0pt
\hbox to X{\strut$d\hfil$}\hskip0pt
\hbox to X{\strut$e\hfil$}\hskip0pt
\hbox to X{\strut$f\hfil$}\hskip0pt}
\hbox{\hskip0pt
\hbox to X{\strut$g\hfil$}\hskip0pt
\hbox to X{\strut$h\hfil$}\hskip0pt
\hbox to X{\strut$i\hfil$}\hskip0pt}
}
其中X
代表单元格的最大宽度(由 TeX 计算)并且\hskip0pt
来自的默认值\tabskip
。
这与之前的属性相同:盒子的深度是其中最后一个盒子的深度(因此是支柱的深度),其余部分构成高度。参考点与最后一个盒子的参考点相同,因此数学模式“g”、“h”和“i”位于由此参考点确定的基线上。
那\valign
? 输入
\setbox2=\hbox{% valign is horizontal mode material
\valign{& \hbox{\strut$#\hfil$}\cr
a& d& g\cr
b& e& h\cr
c& f& i\cr}}% each cell expands out to \vbox{\hbox{...
\hbox{\box0\box1}
相当于
\setbox2=\hbox{%
\vbox{\vskip0pt
\vbox to X{\hbox{\strut$a\hfil$}}\vskip0pt
\vbox to X{\hbox{\strut$d\hfil$}}\vskip0pt
\vbox to X{\hbox{\strut$g\hfil$}}\vskip0pt}%
\vbox{\vskip0pt
\vbox to X{\hbox{\strut$b\hfil$}}\vskip0pt
\vbox to X{\hbox{\strut$e\hfil$}}\vskip0pt
\vbox to X{\hbox{\strut$h\hfil$}}\vskip0pt}%
\vbox{\vskip0pt
\vbox to X{\hbox{\strut$c\hfil$}}\vskip0pt
\vbox to X{\hbox{\strut$f\hfil$}}\vskip0pt
\vbox to X{\hbox{\strut$i\hfil$}}\vskip0pt}%
}
其中X
是单元格的最大高度(在本例中为\ht\strutbox
)。但这里发生了“坏事”!参考点由最后一个项目(即胶水)决定。因此 的底部$g$
位于由此确定的线上。
做就是了
\noindent\rlap{\vrule height0.4pt width 4cm}\vrule\box2
X
(你写在哪里\ht\strutbox
)你就会意识到这个事实。
它在这里:第一个是\valign
,第二个是“等效”框。
答案2
您的输入的一个具有更好对齐的版本是
\setbox0\vbox{% halign is vertical mode material?
\halign{& \strut$#\hfil$\cr
a& b& c\cr
d& e& f\cr
\strut g& h& i\cr}\kern0pt}% each cell expands out to \hbox{...
\setbox2\hbox{% valign is horizontal mode material?
\valign{& \hbox{\strut$#\hfil$}\cr
a& d& g\cr
b& e& h\cr
c& f& i\cr}}% each cell expands out to \vbox{\hbox{...
\hbox{\box0\box2\strut}
\nointerlineskip
\vbox{\strut When there is just text inside a \hbox{vbox,}
it uses the whole hsize and indents\strut}
\nointerlineskip
\vbox{\hbox{\strut except when}\hbox{it consists}\hbox{of consecutive}\hbox{hboxes}}
\tracingoutput2
\bye
这使用box2
而不是box1
哪个不会改变任何东西,但使用奇数寄存器进行本地分配是不道德的:-)
两个对齐方式的总垂直尺寸相同,但第一个对齐方式的深度为零,在第二个对齐方式的垂直列表末尾添加 kern 0pt,将所有尺寸推入高度,以使它们匹配。
像您的示例一样使用 vbox 中间段落几乎没有任何用处,所以我只是将其更改为 hbox。(内部 vbox 中设置的段落将设置为宽行,\hsize
因此它们永远不会真正适合设置为相同尺寸的外部段落。)