# How TeX Calculates Glue Settings in an \hbox#

This is the third, and concluding, article in a series which takes a look at T E X TEX boxes and glue. The first post Boxes and Glue: A Brief, but Visual, Introduction Using LuaTeX introduced the concepts of boxes and glue and was followed by Pandora’s \hbox: Using LuaTeX to Lift the Lid of TeX Boxes which presented a Lua T E X LuaTEX -based Overleaf project to explore the deeper structures of T E X TEX boxes through the use node graphs. In this final piece we take a “deep dive” into the mechanics of how T E X TEX calculates glue values in an \hbox: a process referred to as setting the glue. We make extensive use of node graphs (introduced in the Pandora’s \hbox: Using LuaTeX to Lift the Lid of TeX Boxes in this series) and show how to use and interpret some of the data they provide: glue_set, glue_sign and glue_order.

We provide a fully worked example of glue calculations for an \hbox and cover a lot of detail; however, there may be additional circumstances and considerations that we don’t have space to address here and the interested reader is referred to page 77 of The T E X book The TEXbook .

## The challenge#

Suppose we have an \hbox such as this:

 1 2 3 4 5 6 \hbox to100pt{% A\hskip4pt plus3pt minus 2pt% B\hskip 0pt plus 2fil% C\hskip 0pt plus 2fill% D\hskip 0pt plus 3fill% } 

Here is what this box looks like—for clarity, shown enlarged and with a border:

The question is: what is the final value, in T E X TEX points, of the space (glue) between the following items:

• A and B
• B and C
• C and D
• D and the end of the box

i.e., we want to calculate the values of g 1 , g 2 , g 3 and g 4 : g1,g2,g3 and g4:

Here is a node graph representing the above box. Of particular interest are three values contained in the “metadata” section:

• glue_set
• glue_sign
• glue_order

It is important to note that a particular set of values for glue_set, glue_sign and glue_order only affect glues within the top-level box: they do not affect glues within nested boxes: each nested box (hlist or vlist object) has its own values for these three parameters. Here is an example of an \hbox nested within an outer \hbox. In this example, you can clearly see the different values of glue_set—of course, the nested box can also have different values for glue_sign and glue_order.

 1 \hbox to 75pt{\hfill ABC\hbox to15pt{\hfill D}} 

## Glue types, infinities and orders: A summary#

T E X TEX provides a number of primitive glue-related commands, including:

• horizontal glue: \hskip, \hfil, \hfill, \hfilneg, \hss;
• vertical glue:\vskip, \vfil, \vfill, \vfilneg, \vss;

together with \mskip for inserting glue in math expressions.

An item of glue is defined by a set of three values:

• natural width: how much space it occupies if you don’t stretch or shrink it;
• stretch component: by how much the glue can stretch;
• shrink component: by how much the glue can shrink.

What we are going to consider is the use of glue inside an \hbox{...} and the calculations T E X TEX uses to determine how much space the glue will eventually occupy. The command we’ll be using to create some horizontal glue is \hskip, which takes the form:

\hskipplusminus_For _vertical glue you would use \vskipplusminus.

For example, some typical horizontal glue would be expressed as \hskip 3pt plus 2pt minus 1pt. You can use other physical units too:

• \hskip 3mm plus 2mm minus 1mm
• \hskip 3in plus 2in minus 1in
• \hskip 1in plus 3cm minus 20mm

## T E X TEX glue and units of “infinity”#

For the shrink or stretch component of the glue T E X TEX introduces another type of unit: so-called “infinities”: fil fil , fill fill and filll filll . These three “levels of infinity” are such that when listed in a sequence, each one is “more infinite” than the previous:

fil < fill < filll fil<fill<filll

Perhaps “infinities” is a slightly confusing name for these units—it might be helpful to also think of them as different levels of priority, because, ultimately, they help to determine which glues actually take part in the process of stretching or shrinking. By having glue with an “infinite” stretch or shrink component, T E X TEX lets you create glue that can stretch or shrink by any desired amount. Note that for finite glues, T E X TEX will restrict the amount by which such glues can shrink. An example of “infinite” glue is

\hskip 3pt plus 2fil minus 1fillNote, we can’t write, say, \hskip 1fil because T E X TEX will report an error with the message Illegal unit of measure (pt inserted). At this point, these “levels of infinity” may sound very strange but, for now, just accept it at face value and we’ll soon see how T E X TEX uses these infinities when performing glue calculations.

### Levels of infinity (“glue order”)#

Internally, when T E X TEX performs its glue calculations it considers that each level of infinity is a “glue order” ranging from 0–3 where the 0th order is for glue with physical dimensions such as bp, pt, mm and so forth. However, with Lua T E X LuaTEX there is a slight deviation because it actually has an extra type (order) of infinity not present in many other T E X TEX engines: fi fi (see explanation below). If you read The T E X book The TEXbook you will not see any mention of the fi fi infinity—simply because it is not implemented in Knuth’s original T E X TEX software. Consequently, we have a slight “disconnect” between Lua T E X 's LuaTEX's order of infinities and those you might see in books on T E X TEX . Lua T E X LuaTEX uses infinities whose order ranges from 0–4 but other (common) T E X TEX engines range from 0–3. Here is a table showing the glue order assigned to each type of glue unit.

Physical units (pt, mm, in) fi fil fill filll Lua T E X LuaTEX 0 1 2 3 4 Other engines 0 N/A 1 2 3

### Notes On Lua T E X LuaTEX : Why have an extra infinity?#

Lua T E X LuaTEX is derived from a number of projects and code libraries, including one called Omega. Lua T E X LuaTEX incorporated certain aspects of Omega’s code and that includes a new type of infinite glue called fi fi . From the Omega manual:

“A new infinity level > fi > fi > has been added. It is smaller than > fil > fil > but bigger than any finite quantity. Its original intention was for inter-letter stretching: either filling-in-the-black, as is done for calligraphic scripts such as Arabic; or for emphasis, as in Russian; all this without having to rewrite existing macro packages. There is therefore a new keyword, > fi > fi > , and two new primitives, > \hfi> and > \vfi> .”

## Back to our challenge#

Following Knuth’s model, let’s define two quantities:

• the desired width of a box: W D WD —how big do we want it to be;
• the natural width a box: W N WN —the total space occupied by its constituent elements before any glues are stretched or shrunk.

### The natural width of a box#

The natural width of a box is the total width of all components in that box: characters, kerns, nested boxes and any glue. For glue inside the box its natural width ignores any stretch or shrink of the glue: i.e., its size before any stretching or shrinking takes place.

Once again, here is the box we are examining:

 1 2 3 4 5 6 \hbox to100pt{% A\hskip4pt plus3pt minus 2pt% B\hskip 0pt plus 2fil% C\hskip 0pt plus 2fill% D\hskip 0pt plus 3fill% } 

Clearly, we want the box to be 100pt wide, hence W D = 100 p t WD=100pt but what about its natural width, W N WN ? To calculate the natural width it is clear that we need the widths of the four characters (A, B, C and D) plus the natural widths of the four glues.

W N = width(A) + width(B) + width(C) + width(D) + width ( \hskip 4pt plus3pt minus 2pt ) + width ( \hskip 0pt plus 2fil ) + width ( \hskip 0pt plus 2fill) + width ( \hskip 0pt plus 3fill ) WN=width(A)+width(B)+width(C)+width(D)+width(\hskip 4pt plus3pt minus 2pt)+width(\hskip 0pt plus 2fil)+width(\hskip 0pt plus 2fill)+width(\hskip 0pt plus 3fill)

Where width width is just a notation to denote the natural width of an item. We can obtain the natural widths of the four characters (A, B, C and D) from our node graph:

From the above node graph we can see that:

width(A) width(B) width(C) width(D) = 7.50002 pt = 7.08336 pt = 7.22223 pt = 7.6389 pt width(A)=7.50002ptwidth(B)=7.08336ptwidth(C)=7.22223ptwidth(D)=7.6389pt

Now, all we need are the natural widths of our glues which are easily obtained by ignoring the stretch and shrink components: width ( \hskip 4pt plus3pt minus 2pt ) width ( \hskip 0pt plus 2fil ) width ( \hskip 0pt plus 2fill) width ( \hskip 0pt plus 3fill ) = 4 pt = 0 pt = 0 pt = 0 pt width(\hskip 4pt plus3pt minus 2pt)=4ptwidth(\hskip 0pt plus 2fil)=0ptwidth(\hskip 0pt plus 2fill)=0ptwidth(\hskip 0pt plus 3fill)=0pt

Hence:

W N = widths of characters + width of all glues = 7.50002 pt + 7.08336 pt + 7.22223 pt + 7.6389 pt + 4 pt (from \hskip ) = 33.4445 pt WN=widths of characters+width of all glues=7.50002pt+7.08336pt+7.22223pt+7.6389pt+4pt(from \hskip)=33.4445pt

We now have two key pieces of information:

W D W N = 100 pt = 33.4445 pt WD=100ptWN=33.4445pt

Clearly, W D > W N WD>WN and the difference is ( 100 − 33.4445 ) pt = 66.5555 pt (100−33.4445)pt=66.5555pt ; this excess space has to be filled by stretching the glues—but which ones and by how much?

### Who has the most stretch?#

Following Knuth’s methodology (page 77 of The T E X book The TEXbook ), but allowing for the additional infinity type ( fi fi ) provided by Lua T E X LuaTEX , the next step is to write down the box’s total stretch in the form:

total stretch = y 0 + y 1 fi + y 2 fil + y 3 fill + y 4 filll total stretch=y0+y1fi+y2fil+y3fill+y4filll

Firstly, if we write down the total glue total glue :

total glue = ( 4pt plus3pt minus 2pt ) + ( 0pt plus 2fil ) + ( 0pt plus 2fill ) + ( 0pt plus 3fill ) total glue =(4pt plus3pt minus 2pt)+(0pt plus 2fil)+(0pt plus 2fill)+(0pt plus 3fill)

we can then see that the total stretch total stretch is:

total stretch = 3 pt + 0 fi + ( 2 fil ) + ( 2 fill + 3 fill ) + 0 filll = 3 pt + 0 fi + 2 fil + 5 fill + 0 filll total stretch=3pt+0fi+(2fil)+(2fill+3fill)+0filll=3pt+0fi+2fil+5fill+0filll

Comparing this to total stretch = y 0 + y 1 fi + y 2 fil + y 3 fill + y 4 filll total stretch=y0+y1fi+y2fil+y3fill+y4filll we can see that:

y 0 y 1 y 2 y 3 y 4 = 3 pt = 0 = 2 = 5 = 0 y0=3pty1=0y2=2y3=5y4=0

T E X TEX next “asks itself”: looking at the total stretch total stretch , what is the highest level of infinity with a non-zero value? On inspection of our box’s total stretch total stretch it is clear that the “most infinite” non-zero stretch component is fill fill and we have y 3 = 5 y3=5 units of that: it is glues with a fill fill stretch component that provide all the stretching. The subscript 3 of y 3 y3 tells us the glue_order of the glue that will be used—in this case for stretching. Now, if we look at the “metadata” section within our node diagram for this \hbox we can now make sense of two more “metadata values” (we’ll address glue_set in the next section)

• glue_sign: tells you whether the glue is set to its natural length, stretched or shrunk:

• 0=set to natural width

• 1=stretch
• 2=shrink In our example, glue_sign has the value of 1, meaning that participating glues are to be stretched.

• glue_order tells you which “infinity” is involved; for Lua T E X LuaTEX a value of 3 tells you that glues with a fill fill component will participate in glue calculations—in our case they will stretch.

Any glue that does not have a stretch component defined in units of fill fill will be set to its natural length: i.e., it will not (in our case) stretch at all.

### How much to stretch or shrink: calculating glue_setTo summarize where we are and what we know:#

1. desired width of box: W D = 100 pt WD=100pt ;
2. natural width of box: W N = 33.4445 pt WN=33.4445pt ;
3. glue will have to stretch but only glues with a fill fill stretch component will do that stretching;
4. we have a total of ( 2 + 3 ) = 5 (2+3)=5 units of fill fill available.

The next question is: by how much will those glues actually stretch? Enter the glue set ratio—referred to as glue_set in our node graph. What T E X TEX does is to work out how much space must be filled and then distributes that amount of space among the appropriate glues in proportion to the size of their stretch component. If you look back at our actual \hbox you can see exactly which glues have stretch components containing units of fill fill :

 1 2 3 4 5 6 \hbox to100pt{% A\hskip4pt plus3pt minus 2pt% B\hskip 0pt plus 2fil% C\hskip 0pt plus 2fill% D\hskip 0pt plus 3fill% } 

The glue set ratio ( or glue_set ) glue set ratio (or glue_set) is calculated as follows:

glue set ratio ( glue_set ) = = = = = amount to stretch value of highest infinity W D − W N y 3 ( 100 − 33.4445 ) 5 66.5555 5 13.3111 ( to 4 decimal places ) glue set ratio(glue_set)=amount to stretchvalue of highest infinity=WD−WNy3=(100−33.4445)5=66.55555=13.3111(to 4 decimal places)

And now the final step in the T E X TEX algorithm is applied:

1. for each item of glue whose stretch component matches the desired glue_order (3 in our case) the length of that glue will become:

stretched value = natural length + ( glue_set × value of stretch component ) stretched value=natural length+(glue_set×value of stretch component)

1. all other glues are set to their natural length—i.e., they do not stretch at all.

Looking at the glues in our box:

 1 2 3 4 5 6 \hbox to100pt{% A\hskip4pt plus3pt minus 2pt% B\hskip 0pt plus 2fil% C\hskip 0pt plus 2fill% D\hskip 0pt plus 3fill% } 

we can go through them to calculate their final values:

1. Between A and B: \hskip 4pt plus3pt minus 2pt. The stretch component is 3pt, which is order 0. The required glue_order is 3: the stretch component is ignored and this glue assumes its natural width of 4pt.
2. Between B and C: \hskip 0pt plus 2fil. The stretch component is 2fil, which is order 2. The required glue_order is 3: the stretch component is ignored and this glue assumes its natural width of 0pt.
3. Between C and D: \hskip 0pt plus 2fill. The stretch component is 2fill, which is order 3 and matches the required glue_order of 3. This glue will be stretched to: stretched value = = = natural width + ( glue_set × value of stretch component ) 0 pt + 13.3111 × 2 26.6222 pt stretched value=natural width+(glue_set×value of stretch component)=0pt+13.3111×2=26.6222pt 1. Between D and the end of the box: \hskip 0pt plus 3fill. The stretch component is 3fill, which is order 3 and matches the required glue_order of 3. This glue will be stretched to: stretched value = = = natural width + ( glue_set × value of stretch component ) 0 pt + 13.3111 × 3 39.9333 pt stretched value=natural width+(glue_set×value of stretch component)=0pt+13.3111×3=39.9333pt

## And finally: Checking the total width#

The process of calculating the actual space occupied by glue is called setting the glue so we can now check if we have filled the box to the desired width, ( W D = 100pt ) (WD=100pt) :

W D = width of all characters + width of all set glue values = A:7.50002pt + B:7.08336pt + C:7.22223pt + D:7.6389pt + 4pt + 0pt + 26.6222pt + 39.9333pt = 100.00pt WD=width of all characters+width of all set glue values=A:7.50002pt+B:7.08336pt+C:7.22223pt+D:7.6389pt+4pt+0pt+26.6222pt+39.9333pt=100.00pt

We now know the widths of all glues and can prepare a graphic which answers the question posed at the start of this article: here are the glue widths between the characters in our \hbox: