tex中的盒子解析

tex中的盒子解析

我们知道tex中构成页面元素的核心是盒子。水平对齐,竖直对齐,断行分页等所有操作均与盒子相关。
输出页面本身就是一个大盒子,这个大盒子内部由很多的小盒子构成,每一行内容都是一个盒子,行中的每个字符也是盒子,页面就是盒子套盒子的大盒子。
tex中盒子是box,而hbox,vbox通常被译为水平盒子和竖直盒子,由此往往认为hbox就是一个水平的盒子,而vbox就是一个竖直的盒子,这其实是有误解的,也是
很多初学者或了解不深的人容易想当然的。
其实无论hbox,还是box,本质都是盒子。这是我们要特别记住的概念,理解这个概念对于在盒子对齐和放置处理中的非常关键。

盒子的描述

描述盒子主要是三个参数分别是高度,深度,宽度,如图1所示。这三个参数还带来两个概念分别是基点和边界(包括上下左右边界),其中宽度边界对于盒子的水平对齐很重要,而高度和深度的边界对于盒子的竖直对齐很重要。

tex中盒子构成命令就是前面所说的\hbox\vbox。他俩就是用来构成盒子的,其中\hbox构成一个水平对齐的盒子,所以“水平盒子”本质是一个水平对齐的盒子。
\vbox构成一个竖直对齐的盒子,所以“竖直盒子”本质是一个竖直对齐的盒子。两种盒子都是盒子,都由高度,深度,宽度描述,也使用基点和边界来组织堆叠和放置,只是在两种盒子在堆叠放置、位置确定中存在一定的规则差异。

盒子的构成

一个字符就是一个盒子,那么\hbox{a}就是由字符a盒子构成的一个水平对齐的盒子。这个盒子的高度,深度,宽度与字符a盒子相同。
如果水平对齐的盒子内部由多个元素(可以是盒子,标尺,铅空或粘连),那么各元素都依次排在一行,并将基点(参考点)在水平方向(一条基线)上对齐,后一个元素挨着前一个元素的右边界放置,即后一个元素的左边界紧接前一个元素的右边界,即后一个元素的基点位置由水平对齐基线和前一个盒子右边界的交点确定,这个基点位置是放置盒子的核心。盒子的高度和深度是盒子内所有元素在盒子基线上方和下方的最大值。盒子的宽度是盒子内所有元素宽度之和。水平对齐的盒子的高度和深度都是非负的,但宽度可以是负的。盒子的基点就是盒子左边界与基线的交点,而盒子的右边界就是盒子宽度确定的右边界。

\hbox{\hskip1cm} 盒子宽度为1cm
\hbox{\hskip-1cm} 盒子宽度为-1cm
\hbox{abc} 盒子为abc三个字符的总宽度
\hbox{\vrule height 10pt depth 10pt width 10pt} 盒子的宽度为10pt
\hbox{a\kern-1em b--} 盒子的宽度是字符a宽度-1em+字符b宽度+连接号的宽度,其放置和计算方式为:首先放置a字符则大盒子基点基线同字符a,右边界是a字符的右边界,接着放入水平铅空\kern-1em是向左跳过1em空白,本质上是盒子的宽度减1em,边界向左移动1em,此时大盒子的基点仍然同字符a的基点,高度深度同字符a,宽度变为字符a宽度-1em。接着放入字符b和连字符,b接着大盒子的右边界放置,即基线和大盒子的右边界确定了字符b盒子的基点位置。如果字符a基点所在位置为0,则字符b的基点位置在字符a宽度-1em位置,而连字符接着字符b的右边界放置。

\vbox{a}就是由字符a盒子构成的一个竖直对齐的盒子。这个盒子的高度,深度,宽度与字符a盒子相同。
如果竖直对齐的盒子由其内部多个元素构成,那么各个元素依次从上到下排列,并将基点在竖直方向(一条竖直参考线)上对齐,不同于水平对齐盒子的紧挨方式,竖直对齐的元素中,后一个元素与前一个元素默认间隔一个基线距离\baselineskip,当\baselineskip减去前一个元素的深度和后一个元素的高度后的值小于\lineskiplimit,那么后一个元素将不以默认的基线间距放置而是让后一个元素的上边界与前一个元素的下边界间隔\lineskip,并根据竖直参考线确定后一个元素的基点位置。如果设置\lineskip\baselineskip设置为0,那么后一个元素将紧挨着前一个元素,即后一个元素的上边界紧接前一个元素的下边界,这是后一个元素的基点位置等于前一个元素的基点+深度+后一个元素的高度。

竖直对齐的盒子的高度是除最后一个元素之外所有元素高度与深度之和,再加上最后一个元素的高度;盒子的深度则是最后一个元素的深度。盒子的宽度由各元素向右超出竖直参考线的最大距离确定。盒子的基点就是最后一个元素的基点。左边界由基点确定,右边界和上下边界分别由盒子的宽度,高度,深度确定。竖直对齐的盒子vbox还有一个特点就是当最后一个元素是铅空(kern)或粘连(glue)时,那么盒子的深度为0。

设置

\setlength{\baselineskip}{0pt}
\setlength{\lineskip}{0pt}
\setlength{\lineskiplimit}{100cm}

那么竖直对齐的盒子内部的元素都是紧挨着排列的。

\vbox{\vskip 5pt \hbox{\vrule height 5pt depth 5pt}} 首先加入大盒子的是一个粘连,大盒子的下边界到上边界的空白为5pt,接着在下方紧挨着加入hbox。大盒子的高度为10pt,深度为5pt,基点与内部hbox的基点一致。

\vbox{\hbox{\vrule height 5pt depth 5pt}\vskip 5pt } 首先加入大盒子的是hbox,接着在其下方紧挨着一个粘连。由于最后一个元素不是盒子或标尺,那么则大盒子的深度为0pt,高度为15pt,基点为下边界与左边界交点。

\vbox{\hbox{a}\hbox{b}\hbox{c}},就是由字符a盒子,字符b盒子,字符c盒子从上到下紧挨着排在一起并竖直对齐的盒子。盒子的高度为a字符盒子的高度加深度加b字符盒子的高度加深度加c字符的高度,深度为c字符盒子的深度。基点与c字符的基点相同。

盒子的位移调整

盒子可以通过raise和lower命令调整盒子的竖直位置,通常是在水平对齐的盒子中使用。
盒子可以通过moveleft和moveright命令调整盒子的水平位置,通常是在垂直对齐的盒子中使用。
如果把调整后的盒子当做一个新的盒子看待,那么很容易理解这种调整。

假设有一个盒子\hbox{\vrule height 10pt depth 10pt width 10pt},在hbox和vbox中对其做调整:

\hbox{\hbox{\vrule height 10pt depth 10pt width 10pt} \raise 10pt \hbox{\vrule height 10pt depth 10pt width 10pt}} 可以看到后一个盒子上移了10pt,假设上移过程形成了新的盒子,可以看到新盒子基点比原盒子低10pt。

\hbox{\hbox{\vrule height 10pt depth 10pt width 10pt} \lower 10pt \hbox{\vrule height 10pt depth 10pt width 10pt}} 可以看到后一个盒子下移了10pt。

\vbox{\hbox{\vrule height 10pt depth 10pt width 10pt} \moveright 10pt \hbox{\vrule height 10pt depth 10pt width 10pt}} 可以看到后一个盒子右移了10pt。

\vbox{\hbox{\vrule height 10pt depth 10pt width 10pt} \moveleft 10pt \hbox{\vrule height 10pt depth 10pt width 10pt}} 可以看到后一个盒子左移了10pt。

一些示例解析

  1. 假设 \box1 的高度为 1pt, 深度为 1pt, 宽度为 1pt; \box2 的高度为 2pt, 深度为 2pt, 宽度为 2pt; baselineskip, lineskip, 和 lineskiplimit 都是零;并且 \boxmaxdepth 很大。若第三个盒子定义为\setbox3=\vbox{\moveright3pt\box1\vskip-3pt plus3fil\box2}那么,\box3 的高度,深度和宽度各是什么?给出相对于 box3 的基准点的 box1 和 box2的基准点。
    若第三个盒子定义为\setbox3=\vbox to3pt{\moveright3pt\box1\vskip-3pt plus3fil\box2}那么,\box3 的高度,深度和宽度各是什么?给出相对于 box3 的基准点的 box1 和 box2的基准点。

这是the texbook 书中的题名,我们来看box3的构成。

第一种情况:

首先加入box3的向右移动后的box1,加入后box3的高度深度与box1一致,宽度为移动的3pt加上box1的原宽为4pt,基点在大盒子的左边界上。
接着加入粘连\vskip-3pt,当前下边界在盒子基点下方1pt处,由于粘连下边界上移3pt,到基点上方2pt处,box2在紧挨着该处加入,确定基点位置就在当前大盒子的基点处。最后构建完成的大盒子的基点由box2的基点位置一致,高度2pt,深度为2pt,宽度为4pt。大盒子基点向右3pt就是box1的基点。

形状示例见:

{
\setlength{\baselineskip}{0pt}
\setlength{\lineskip}{0pt}
\setlength{\lineskiplimit}{100cm}

\vbox{\moveright 3pt \hbox{\color{red}\vrule height 1pt depth 1pt width 1pt} \vskip -3pt plus 3fil \hbox{\color{blue}\vrule height 2pt depth 2pt width 2pt}}

}

第二种情况:

由于大盒子设定高度为3pt,而加入box2后高度无法满足要求,因此需要调整粘连,看到粘连加上了3fil是可以变大的,如果粘连调整为-1pt,那么加入粘连后的大盒子下边界在box1基点同一竖直位置上,这时紧挨放入box2后,高度满足为3pt,此时深度为2pt,宽度为4pt。最后构建完成的大盒子的基点与box2的基点位置一致,该基点向上移动2pt,向右3pt即为box1的基点。

形状示例见:
{
\setlength{\baselineskip}{0pt}
\setlength{\lineskip}{0pt}
\setlength{\lineskiplimit}{100cm}

\vbox to 3pt {\moveright 3pt \hbox{\color{red}\vrule height 1pt depth 1pt width 1pt} \vskip -3pt plus 3fil \hbox{\color{blue}\vrule height 2pt depth 2pt width 2pt}}
}

  1. 考察如下代码产生对应盒子的原因:

\hbox{a\setbox0=\vbox{\hbox{b}}\box0 c}\hbox{a\vbox{\hbox{b}}c}

这就是一个水平对齐的盒子,内部有三个元素,分别为字符a,b,c的盒子,从左到右依次放置。

\hbox{a\setbox0=\vbox{\hbox{b}}\ht0=0cm \box0 c}\hbox{a\vbox to 0pt {\hbox{b}}c}

这个水平对齐盒子,存在一定的差异,即中间的vbox的高度设置为0。分析大盒子中的放置情况,放入字符a盒子后,右侧边界在字符a盒子宽度所在位置。再看一下高度为0的vbox的情况,该vbox放入字符b的盒子后,由于高度设置为0,则vbox的基点从原来字符b的基点处移至字符b的上边界处。当该vbox紧挨着放置字符a盒子旁边,其基点位于字符a盒子右边界处,且与极限水平对齐,因此整个b字符在大盒子的基线以下。放入vbox后大盒子的右侧边界在ab字符宽度之和处,接着放入字符c盒子,基点水平对齐即可。

  1. 考察如下代码产生对应盒子的原因:
\setlength{\baselineskip}{0pt}
\setlength{\lineskip}{0pt}
\setlength{\lineskiplimit}{100cm}
\vbox{\hbox{a} \setbox0=\hbox{(} \ht0=0pt \dp0=0pt \box0 \hbox{b}}

这里的竖直对齐盒子由三个元素构成,第一个是字符a盒子,第二个是字符(构成的盒子,第三个字符b构成的盒子。第一个盒子放入后大盒子基点与hbox{a}相同,接着准备在其下方竖直对齐的放入\hbox{(},但由于其高度和深度都设置为0,所以hbox{(}内(字符盒子的基点要放置的位置与hbox{a}字符的下边界位置相同,所以放置该hbox后,字符(与字符a重叠。接着放入字符b,根据当前大盒子的基点,及其深度和hbox{b}的高度确定hbox{b}的基点位置后放入,即b字符在字符a下方。

\setlength{\baselineskip}{0pt}
\setlength{\lineskip}{0pt}
\setlength{\lineskiplimit}{100cm}
\vbox{\hbox{a} \setbox0=\vbox{\hbox{(}} \ht0=0pt \dp0=0pt \box0 \hbox{b}}

这里的竖直对齐盒子由三个元素构成,第一个是字符a盒子,第二个是字符(构成的盒子,第三个字符b构成的盒子。第一个盒子放入后大盒子基点与hbox{a}相同,接着准备在其下方竖直对齐的放入\vbox{(},先看一下vbox的内部,由于vbox的高度和深度都为0,因此vbox的基点与\hbox{(}的上边界和左边界的交点一致。放入vbox后,确定出vbox的基点所在的位置即为字符a盒子的下边界处,但由于vbox的基点在\hbox{(}左上角点,因此(字符在字符a的下方。此时大盒子的基点为字符a的基点,下边界仍然为字符a的下边界,在其下方法放入字符b,则字符(和b重叠。

其它问题

还有更多的细节问题没有讨论到,比如盒子寄存器,比如vtop盒子,比如盒子中标尺/铅空/粘连,比如盒子与不同模式的关系等等,但了解了上述box的基本原理后,那么剩下的内容就会变得很容易理解。掌握基本规则后就能开展分析。

\hbox{\vrule height 5pt depth 5pt}
\hbox{\hrule height 5pt depth 5pt}
\vbox{\hbox{a}\hbox{b}\hbox{c}}
\vbox{abc}
\vbox{\vbox{\vrule width 5pt height 5pt depth 5pt}\vbox{\vrule width 5pt height 5pt depth 5pt}}
\vbox{\vrule width 5pt height 5pt depth 5pt\vrule width 5pt height 5pt depth 5pt}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值