How to construct an hbox with negative height?

Short answer: as far as I know, a box directly produced with the \hbox command can't have a negative height, but a box produced with the \vbox command can. A horizontal box can have a negative height if it is stored in a box register, say \box0, and one executes an assignment of the form \ht0=〈dimen〉 with a negative 〈dimen〉.

Example of a \vbox with negative height

Let's consider the following code:

\setbox0=\vbox to -10pt{\vss\hbox{a}}
This is \vbox{\hrule\box0\nointerlineskip \hbox{test}}.
\bye

Screenshot

If you do \showbox0 before using \box0, you'll see:

> \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

The box is -10pt height and 0pt deep. Because of this negative height, the \hrule lies exactly 10 points below the baseline of the character box a. Indeed, changing the -10pt to 0pt:

\setbox0=\vbox to 0pt{\vss\hbox{a}}
\showbox0
This is \vbox{\hrule\box0\nointerlineskip \hbox{test}}.
\bye

gives this:

Screenshot

Here is how it works:

  • The reference point of the outer \vbox, \vbox{\hrule\box0\nointerlineskip \hbox{test}}, is the same as that of \hbox{test}; it gets aligned with that of the following period, i.e.: lies on the baseline of the paragraph's first and only line.

  • Because of the \nointerlineskip, \box0 sits on top of the \hbox{test}, with no separation (no interline glue).

  • The depth of \box0 is that of \hbox{a} (\hbox{a} is a box—not a kern or glue—and the last item of \box0), i.e., 0pt. According to what I explain below, this implies that the reference point of \box0 is at the same vertical position as the bottom of \hbox{a}: its baseline.

  • Now, let's consider the case where we do \setbox0=\vbox to -10pt{\vss\hbox{a}}. We mandate \box0 to have height -10pt, i.e., from the reference point we just computed, this means we have to move 10 points down to reach the “top” of \box0, which in this precise case is not the top in the usual sense, but means “right before the \vbox's first element”. This implies that the \vss here behaves as a \vskip whose value is -10pt minus the height of \hbox{a}. This can be verified with:

    \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〉
    

    which gives the same result. Indeed, when continuing our walk from after-last-item to before-first-item of \box0, before getting to the \vss, we are at the top of the \hbox{a}, so in order to reach the so-called top of the \vbox (what corresponds to “before the first item”), we must move down in order to arrive 10pt below the reference point, and the amplitude of this downward move has to comprise all the height of \hbox{a}, plus 10pt. In other words, \vbox to -10pt{...} says that before-first-item of the \vbox must be 10pt below the \vbox reference point. So, the first thing to do in order to find the vertical position corresponding to the start of a \vbox (what I call before-first-item) is to find the reference point; then move up or down depending either on the natural height of the box, or on its prescribed height in the case of a \vbox to.

  • The \hrule inside the outer \vbox comes right before \box0. Since no interline glue is added after a rule box in vertical mode, this \hrule comes right above the “top” of \box0 which we just described, i.e.: 10pt below the baseline of the \hbox{a}.

Negative height, width or depth of constructed boxes

An \hbox command can't produce a box with negative height or depth,1 but it can produce a box with negative width. A \vbox command can't produce a box with negative width (TeXbook p. 81),2 but it can produce a box with negative height or depth. Example for a negative depth:

\setbox2=\vbox{\hrule height 0pt depth -2pt}
\showbox2

shows:

> \box2=
\vbox(0.0+-2.0)x0.0
.\rule(0.0+-2.0)x*

To aid memory, note the symmetry between these two sentences:

The height and depth of a constructed hbox are determined by the maximum distances by which the interior boxes reach above and below the baseline, respectively.

(TeXbook p. 77) and

The width of a computed \vbox is the maximum distance by which an enclosed box extends to the right of the reference point, taking possible shifting into account.

(TeXbook p. 81). Other box dimensions immediately resulting from an \hbox or \vbox command may be negative.

\prevdepth after a rule box in vertical mode

Regarding \prevdepth, the TeXbook pp. 79 and 80 says:

TeX's implementation of interline glue involves another primitive quantity called \prevdepth, which usually contains the depth of the most recent box on the current vertical list. However, \prevdepth is set to the sentinel value −1000 pt at the beginning of a vertical list, or just after a rule box; (...)

Since your example does \showthe\prevdepth just after a rule box, we are precisely in one of the particular cases where \prevdepth is set to -1000 pt.

Reference point of a constructed \vbox

Regarding your addition concerning \vbox to 20pt{\hbox{x}\vss}, this is a new question! The answer is in the next two paragraphs after the one you quoted on p. 80:

However, this description of vboxes glosses over some technicalities that come up when you consider unusual cases (...) Therefore, the actual rules (...) (2) If there’s at least one box, but if the final box is followed by kerning or glue, possibly with intervening penalties or other things, the depth is zero.

Depth zero means that the reference point of the box is precisely at the bottom of the \vss (the box doesn't extend below this \vss). This reference point is aligned on a horizontal line with the reference points of the a and b character boxes inside the horizontal box that forms the first and only line of your paragraph. Note that this alignment process of reference points does not correspond to the quote you gave, because the latter concerned alignment of boxes inside a vertical list (these alignment processes work in orthogonal directions).

My method to “see“ the reference point of a \vbox is to start after the last item, then move up or down according to the depth computed by the rules given in the paragraph that spans over pages 80 and 81 of the TeXbook. If for instance, the computed depth is 5pt, it means that the reference point of the \vbox is 5pt up from the bottom of its final element. The following extension of your example may help:

\setbox2=\vbox{\hrule height 0pt depth 5pt}
\setbox0=\vbox to 20pt{\hbox{x}\vss\box2}
a\vrule height 20pt\box0 b
\bye

Screenshot

Explanations:

  • The width of the \hrule in \box2 isn't explicitly specified, therefore it is determined by the smallest box or alignment that encloses it, i.e., \box2 (cf. TeXbook p. 221). Since there is nothing else inside \box2, the width of the \hrule is 0pt; that is why we don't see it on the screenshot.

  • \box2 is a \vbox whose last element is a box (a rule box), therefore its depth is the depth of that last element (\boxmaxdepth being equal to \maxdimen by default). The depth of \box2 is thus 5pt.

  • This implies that the reference point of \box2 lies 5pt above the bottom of its last element, therefore it coincides with the top of the \hrule inside \box2.

  • The natural height plus depth of all the material inside \box2 is 5pt. Since \box2's depth is also 5pt, the natural height of \box2 is 0pt.

  • This natural height of 0pt is \box2's height because \box2 is built with \vbox as opposed to \vbox to. So far, we've explained this:

    > \box2=
    \vbox(0.0+5.0)x0.0
    .\rule(0.0+5.0)x*
    
  • For the same reasons as above, the depth of \box0 is that of \box2, namely 5pt, and the reference point of \box0 lies on the same horizontal line as the top of the \hrule inside \box2, which coincides with the top of \box2 (for both possible meanings of the word “top” in this context).

  • The vertical extent of \box2 exactly covers \box0's 5pt of depth. The remaining \hbox{x}\vss inside \box0, plus the interline glue inserted before \box2, therefore exactly cover the mandated 20pt of height of \box0 (the precise amount of computed interline glue before \box2 doesn't matter, because the \vss will adapt to any amount, making it so that the top of the \hbox{x} lies 20pt above the reference point of \box0).

  • The previous point explains why the \vrule height 20pt reaches up precisely as far as the top of the x, and down 5pt below the baseline of the paragraph's first and only line (since the \vrule's depth isn't explicitly specified, it is determined by the “smallest box or alignment that encloses it”, namely the horizontal box corresponding to the paragraph's only line, whose deepest element—apart from such rules with free depth—is \box0).


Footnotes

  1. However, a horizontal box stored in a register can be made to have negative height or depth via assignments such as \ht0=〈dimen〉 or \dp0=〈dimen〉, as pointed out by David Carlisle.

  2. But again, \setbox0=\vbox{\hbox{a}}\wd0=-3pt does cause box register 0 to contain a vertical box with negative width:

    > \box0=
    \vbox(4.30554+0.0)x-3.0
    .\hbox(4.30554+0.0)x5.00002
    ..\tenrm a
    

You can have a horizontal box with negative height, as the dimensions of box registers are assignable, but when constructing a box with \hbox the maximum of 0pt and the positive heights of the content is used.

\tracingonline1

\setbox0=\hbox{a}

\showbox0

\ht0=-20pt

\showbox0

\setbox2\hbox{\box0}

\showbox2

\bye

Produces

\hbox(4.30554+0.0)x5.00002

Natural height 4.3pt

\hbox(-20.0+0.0)x5.00002

assigned height -20pt

\hbox(0.0+0.0)x5.00002

Constructed "natural" height 0pt.

Tags:

Box

Boxes