根据练习 12.10 的答案电子书,盒子的高度可能为负数:
是的,但只是因为他的盒子都没有负高度或负深度。
但第 77 页却说:
结果
\hbox
永远不会有负高度或负深度,但宽度可以为负。
如何构造一个具有负高度的盒子?
为什么在下面的例子中\prevdepth
没有设置新盒子的深度?
\vbox{\hrule depth -5pt \showthe\prevdepth \hbox{world}}
(第 80 页说\prevdepth
设置为新盒子的深度)
TeXbook p.80 说:
...以最底下的盒子的参考点作为整体的参考点,并设置胶水,使得最终的高度具有某个期望值。
考虑以下输入:
\tracingonline=1
\setbox0=\vbox to 20pt{\hbox{x}\vss}
\showbox0
a\box0 b
\end
输出为
请注意,最下面的框带有“x”,然后是胶水:
> \box0=
\vbox(20.0+0.0)x5.2778, glue set 15.69446fil
.\hbox(4.30554+0.0)x5.2778
..\tenrm x
.\glue 0.0 plus 1.0fil minus 1.0fil
但整体的参考点并不是“x”的参考点(如图所示)。这是否矛盾?
答案1
简短回答:据我所知,直接用命令生成的框\hbox
不能有负高度,但用\vbox
命令生成的框可以。水平框能如果将其存储在盒子寄存器中,则具有负高度,例如,并且执行具有负数的\box0
形式的分配。\ht0=〈dimen〉
〈dimen〉
\vbox
具有负高度的示例
让我们考虑以下代码:
\setbox0=\vbox to -10pt{\vss\hbox{a}}
This is \vbox{\hrule\box0\nointerlineskip \hbox{test}}.
\bye
如果你\showbox0
在使用之前这样做\box0
,你会看到:
> \box0=
\vbox(-10.0+0.0)x5.00002, glue set - 14.30554fil
.\glue 0.0 plus 1.0fil minus 1.0fil
.\hbox(4.30554+0.0)x5.00002
..\tenrm a
盒子的高度为 -10pt,深度为 0pt。由于这个负高度,所以\hrule
正好位于 10 点以下字符框的基线a
。实际上,将 更改-10pt
为0pt
:
\setbox0=\vbox to 0pt{\vss\hbox{a}}
\showbox0
This is \vbox{\hrule\box0\nointerlineskip \hbox{test}}.
\bye
给出这个:
下面是它的工作原理:
外部的 的参考点
\vbox
与\vbox{\hrule\box0\nointerlineskip \hbox{test}}
的参考点相同\hbox{test}
;它与下一个句号的参考点对齐,即:位于段落第一行也是唯一一行的基线。由于
\nointerlineskip
,\box0
位于 的顶部\hbox{test}
,没有分离(没有行间胶)。的深度
\box0
是\hbox{a}
(\hbox{a}
是一个框 — 不是字距或粘连 — 和 的最后一项\box0
),即 0pt。根据我下面的解释,这意味着 的参考点\box0
与 的底部位于相同的垂直位置\hbox{a}
:即其基线。现在,让我们考虑一下这种情况
\setbox0=\vbox to -10pt{\vss\hbox{a}}
。我们要求\box0
高度为 -10pt,即从我们刚刚计算的参考点开始,这意味着我们必须移动 10 个点向下到达 的“顶部”\box0
,在这种情况下,它不是通常意义上的顶部,而是指“\vbox
的第一个元素之前”。这意味着\vss
此处的行为相当于 ,\vskip
其值为 -10pt 减去 的高度\hbox{a}
。这可以通过以下方法验证:\setbox2=\hbox{a} % Without e-TeX's \dimexpr: \dimen0=-\ht2 \advance\dimen0 by -10pt \setbox0=\vbox to -10pt{\vskip\dimen0 \hbox{a}} \setbox0=\vbox to -10pt{\vskip\dimexpr-\ht2-10pt\relax \hbox{a}} 〈rest unchanged〉
这给出了相同的结果。事实上,当我们继续从 的最后一项之后 走到 的第一项之前 时
\box0
,在到达 之前\vss
,我们位于 的顶部\hbox{a}
,因此为了到达 的所谓顶部\vbox
(对应于“第一项之前”),我们必须向下移动以到达参考点以下 10pt 处,并且此向下移动的幅度必须包括 的所有高度\hbox{a}
加上 10pt。换句话说,\vbox to -10pt{...}
表示 的第一项之前\vbox
必须位于参考点10pt
下方\vbox
。因此,为了找到对应于 的开头\vbox
(我称之为 的第一项之前)的垂直位置,首先要做的是找到参考点;然后根据框的自然高度或在 的情况下根据其规定的高度向上或向下移动\vbox to
。\hrule
outer 的 inside位于\vbox
之前\box0
。由于在垂直模式下规则框后没有添加行间粘连,因此它\hrule
位于\box0
我们刚刚描述的“顶部”的正上方,即 基线下方 10pt\hbox{a}
。
构造的盒子的高度、宽度或深度为负
命令\hbox
无法生成具有负高度或负深度的框,1但可以生成具有负宽度的框。\vbox
命令无法生成具有负宽度的框 (TeXbook p. 81),2但可以生成具有负高度或负深度的框。负深度的示例:
\setbox2=\vbox{\hrule height 0pt depth -2pt}
\showbox2
显示:
> \box2=
\vbox(0.0+-2.0)x0.0
.\rule(0.0+-2.0)x*
为了帮助记忆,请注意这两个句子之间的对称性:
构建的水平盒子的高度和深度分别由内部盒子到达基线上方和下方的最大距离决定。
(TeXbook 第 77 页)和
计算的宽度
\vbox
是封闭框延伸到参考点右侧的最大距离,考虑到可能的移动。
(TeXbook 第 81 页)。由\hbox
或\vbox
命令直接得出的其他框尺寸可能为负数。
\prevdepth
垂直模式下的规则框之后
关于\prevdepth
,TeXbook 第 79 和 80 页说:
TeX 的行间粘合实现涉及另一个原始量,称为
\prevdepth
,它通常包含当前垂直列表中最近框的深度。但是,\prevdepth
在垂直列表的开头或规则框之后设置为标记值 −1000 pt;(...)
由于您的示例\showthe\prevdepth
就在规则框之后,我们恰好处于\prevdepth
设置为 -1000 pt 的特殊情况之一。
构造的参考点\vbox
关于你补充的\vbox to 20pt{\hbox{x}\vss}
,这是一个新问题!答案在第 80 页你引用的后面两段中:
但是,这种对垂直盒子的描述掩盖了在考虑不寻常情况时出现的一些技术细节 (...) 因此,实际规则 (...) (2) 如果至少有一个盒子,但如果最后一个盒子后面跟着字距调整或粘合,可能还会出现惩罚或其他事情,则深度为零。
深度为零意味着框的参考点恰好位于 的底部\vss
(框不会延伸到 的下方)。此参考点与构成段落第一行且唯一一行的水平框内的和字符框\vss
的参考点在一条水平线上对齐。请注意,此参考点对齐过程不会a
b
不是对应于你给出的报价,因为后者涉及框内的对齐垂直列表(这些对齐过程在正交方向上进行)。
我“查看” a 的参考点的方法\vbox
是从最后一个项目开始,然后根据 TeXbook 第 80 和 81 页段落中给出的规则计算出的深度向上或向下移动。例如,如果计算出的深度是 5pt,则意味着 的参考点\vbox
从其最后一个元素的底部向上 5pt。以下示例的扩展可能会有所帮助:
\setbox2=\vbox{\hrule height 0pt depth 5pt}
\setbox0=\vbox to 20pt{\hbox{x}\vss\box2}
a\vrule height 20pt\box0 b
\bye
解释:
\hrule
的宽度\box2
没有明确指定,因此它由包围它的最小框或对齐决定,即\box2
(参见 TeXbook 第 221 页)。由于 里面没有其他东西\box2
, 的宽度\hrule
为 0pt;这就是为什么我们在屏幕截图上看不到它的原因。\box2
是一个\vbox
,其最后一个元素是一个框(规则框),因此其深度是最后一个元素的深度(默认情况\boxmaxdepth
下等于\maxdimen
)。因此的深度\box2
为 5pt。这意味着的参考点
\box2
位于其最后一个元素底部上方 5pt 处,因此它与\hrule
内部的顶部重合\box2
。里面所有材质的自然高度加上深度
\box2
是 5pt。由于\box2
的深度也是 5pt,所以 的自然高度\box2
是 0pt。这个自然高度 0pt 是
\box2
的高度,因为\box2
是用 构建的\vbox
,而不是\vbox to
。到目前为止,我们已经解释了这一点:> \box2= \vbox(0.0+5.0)x0.0 .\rule(0.0+5.0)x*
出于与上述相同的原因,的深度
\box0
为\box2
,即5pt,并且的参考点与内部\box0
的顶部位于同一水平线上,该水平线与的顶部重合(对于本文中“顶部”一词的两种可能含义而言)。\hrule
\box2
\box2
的垂直范围
\box2
恰好覆盖 的5pt 深度。内部\box0
剩余部分加上 之前插入的行间粘连,因此恰好覆盖 规定的 20pt 高度(之前计算的行间粘连的精确量无关紧要,因为会适应任何量,从而使 的顶部位于 的参考点上方 20pt )。\hbox{x}\vss
\box0
\box2
\box0
\box2
\vss
\hbox{x}
\box0
上一点解释了为什么
\vrule height 20pt
精确地到达 的顶部x
,并向下到达段落第一行也是唯一一行的基线以下 5pt(因为\vrule
的深度没有明确指定,它由“包围它的最小框或对齐方式”决定,也就是对应于段落唯一行的水平框,其最深元素——除了具有自由深度的规则——是\box0
)。
脚注
但是,可以通过诸如
\ht0=〈dimen〉
或\dp0=〈dimen〉
之类的赋值使存储在寄存器中的水平框具有负高度或负深度,如下所示David Carlisle 指出。但同样,
\setbox0=\vbox{\hbox{a}}\wd0=-3pt
会导致盒子寄存器 0 包含一个具有负宽度的垂直盒子:> \box0= \vbox(4.30554+0.0)x-3.0 .\hbox(4.30554+0.0)x5.00002 ..\tenrm a
答案2
您可以拥有一个具有负高度的水平框,因为框寄存器的尺寸是可分配的,但是在构建\hbox
最大值为 0pt 的框时,将使用内容的正高度。
\tracingonline1
\setbox0=\hbox{a}
\showbox0
\ht0=-20pt
\showbox0
\setbox2\hbox{\box0}
\showbox2
\bye
生产
\hbox(4.30554+0.0)x5.00002
自然高度 4.3pt
\hbox(-20.0+0.0)x5.00002
指定高度-20pt
\hbox(0.0+0.0)x5.00002
构造“自然”高度 0pt。