lowlevel-boxes.tex /size: 28 Kb    last modification: 2024-01-16 09:02
1% language=us runpath=texruns:manuals/lowlevel
2
3% \hfil \hss
4% spread
5
6\environment lowlevel-style
7
8\startdocument
9  [title=boxes,
10   color=middlered]
11
12\startsectionlevel[title=Introduction]
13
14An average \CONTEXT\ user will not use the low level box primitives but a basic
15understanding of how \TEX\ works doesn't hurt. In fact, occasionally using a box
16command might bring a solution not easily achieved otherwise, simply because a
17more high level interface can also be in the way.
18
19The best reference is of course The \TeX book so if you're really interested in
20the details you should get a copy of that book. Below I will not go into details
21about all kind of glues, kerns and penalties, just boxes it is.
22
23This explanation will be extended when I feel the need (or users have questions
24that can be answered here).
25
26\stopsectionlevel
27
28\startsectionlevel[title=Boxes]
29
30This paragraph of text is made from lines that contain words that themselves
31contain symbolic representations of characters. Each line is wrapped in a so
32called horizontal box and eventually those lines themselves get wrapped in what
33we call a vertical box.
34
35\startbuffer
36\vbox \bgroup
37    \hsize 5cm
38    \raggedright
39    This is a rather narrow paragraph blown up a bit. Here we use a flush left,
40    aka ragged right, approach.
41\egroup
42\stopbuffer
43
44When we expose some details of a paragraph it looks like this:
45
46\startlinecorrection
47\startcombination[2*1]
48    {\scale[width=8cm]{\showmakeup[boxes]\getbuffer}} {}
49    {\scale[width=8cm]{\showmakeup\getbuffer}}        {}
50\stopcombination
51\stoplinecorrection
52
53The left only shows the boxes, the variant at the right shows (font) kerns and
54glue too. Because we flush left, there is rather strong right skip glue at the
55right boundary of the box. If font kerns show up depends on the font, not all
56fonts have them (or have only a few). The glyphs themselves are also kind of
57boxed, as their dimensions determine the area that they occupy:
58
59\startlinecorrection
60    \scale[width=\textwidth]{\showglyphs\hbox{This is a rather ...}}
61\stoplinecorrection
62
63But, internally they are not really boxed, as they already are a single quantity.
64The same is true for rules: they are just blobs with dimensions. A box on the
65other hand wraps a linked list of so called nodes: glyphs, kerns, glue,
66penalties, rules, boxes, etc. It is a container with properties like width,
67height, depth and shift.
68
69\stopsectionlevel
70
71\startsectionlevel[title={\TEX\ primitives}]
72
73The box model is reflected in \TEX's user interface but not by that many
74commands, most noticeably \type {\hbox}, \type {\vbox} and \type {\vtop}. Here is
75an example of the first one:
76
77\starttyping[option=TEX]
78\hbox width 10cm{text}
79\hbox width 10cm height 1cm depth 5mm{text}
80text \raise5mm\hbox{text} text
81\stoptyping
82
83The \type {\raise} and \type {\lower} commands behave the same but in opposite
84directions. One could as well have been defined in terms of the other.
85
86\startbuffer
87text \raise  5mm \hbox to 2cm {text}
88text \lower -5mm \hbox to 2cm {text}
89text \raise -5mm \hbox to 2cm {text}
90text \lower  5mm \hbox to 2cm {text}
91\stopbuffer
92
93\typebuffer[option=TEX]
94
95\startlinecorrection
96{\dontcomplain\showboxes\getbuffer}
97\stoplinecorrection
98
99A box can be moved to the left or right but, believe it or not, in \CONTEXT\ we
100never use that feature, probably because the consequences for the width are such
101that we can as well use kerns. Here are some examples:
102
103\startbuffer
104text \vbox{\moveleft  5mm \hbox {left}}text !
105text \vbox{\moveright 5mm \hbox{right}}text !
106\stopbuffer
107
108\typebuffer[option=TEX]
109
110\startlinecorrection
111{\dontcomplain\getbuffer}
112\stoplinecorrection
113
114\startbuffer
115text \vbox{\moveleft  25mm \hbox {left}}text !
116text \vbox{\moveright 25mm \hbox{right}}text !
117\stopbuffer
118
119\typebuffer[option=TEX]
120
121\startlinecorrection
122{\dontcomplain\getbuffer}
123\stoplinecorrection
124
125Code like this will produce a complaint about an underfull box but we can easily
126get around that:
127
128\startbuffer
129text \raise  5mm \hbox to 2cm {\hss text}
130text \lower -5mm \hbox to 2cm {text\hss}
131text \raise -5mm \hbox to 2cm {\hss text}
132text \lower  5mm \hbox to 2cm {text\hss}
133\stopbuffer
134
135\typebuffer[option=TEX]
136
137The \type {\hss} primitive injects a glue that when needed will fill up the
138available space. So, here we force the text to the right or left.
139
140\startlinecorrection
141{\dontcomplain\showboxes\getbuffer}
142\stoplinecorrection
143
144Instead of \type {\raise} you can also provide the shift (up or down) with a
145keyword:
146
147\startbuffer
148\ruledhbox\bgroup
149    x\raise  5pt\ruledhbox            {1}x
150    x\raise-10pt\ruledhbox            {2}x
151    x\raise -5pt\ruledhbox shift -20pt{3}x
152    x\ruledhbox            shift -10pt{4}x
153\egroup
154\stopbuffer
155
156\typebuffer[option=TEX]
157
158\startlinecorrection
159{\dontcomplain\showboxes\getbuffer}
160\stoplinecorrection
161
162
163We have three kind of boxes: \type {\hbox}, \type {\vbox} and \type {\vtop}.
164Actually we have a fourth type \type {\dbox} but that is a variant on \type
165{\vbox} to which we come back later.
166
167\startbuffer
168\hbox{\strut height and depth\strut}
169\vbox{\hsize 4cm \strut height and depth\par and width\strut}
170\vtop{\hsize 4cm \strut height and depth\par and width\strut}
171\stopbuffer
172
173\typebuffer[option=TEX]
174
175A \type {\vbox} aligns at the bottom and a \type {\vtop} at the top. I have added
176some so called struts to enforce a consistent height and depth. A strut is an
177invisible quantity (consider it a black box) that enforces consistent line
178dimensions: height and depth.
179
180\startlinecorrection
181{\dontcomplain\hbox{\showstruts\showboxes\getbuffer}}
182\stoplinecorrection
183
184You can store a box in a register but you need to be careful not to use a
185predefined one. If you need a lot of boxes you can reserve some for your own:
186
187\starttyping
188\newbox\MySpecialBox
189\stoptyping
190
191but normally you can do with one of the scratch registers, like 0, 2, 4, 6 or 8,
192for local boxes, and 1, 3, 5, 7 and 9 for global ones. Registers are used like:
193
194\starttyping
195       \setbox0\hbox{here}
196\global\setbox1\hbox{there}
197\stoptyping
198
199In \CONTEXT\ you can also use
200
201\starttyping
202\setbox\scratchbox   \hbox{here}
203\setbox\scratchboxone\hbox{here}
204\setbox\scratchboxtwo\hbox{here}
205\stoptyping
206
207and some more. In fact, there are quite some predefined scratch registers (boxes,
208dimensions, counters, etc). Feel free to investigate further.
209
210When a box is stored, you can consult its dimensions with \type {\wd}, \type
211{\ht} and \type {\dp}. You can of course store them for later use.
212
213\starttyping
214\scratchwidth \wd\scratchbox
215\scratchheight\ht\scratchbox
216\scratchdepth \dp\scratchbox
217\scratchtotal \dimexpr\ht\scratchbox+\dp\scratchbox\relax
218\scratchtotal \htdp\scratchbox
219\stoptyping
220
221The last line is \CONTEXT\ specific. You can also set the dimensions
222
223\starttyping
224\wd\scratchbox 10cm
225\ht\scratchbox 10mm
226\dp\scratchbox  5mm
227\stoptyping
228
229So you can cheat! A box is placed with \type {\copy}, which keeps the original
230intact or \type {\box} which just inserts the box and then wipes the register. In
231practice you seldom need a copy, which is more expensive in runtime anyway. Here
232we use copy because it serves the examples.
233
234\starttyping
235\copy\scratchbox
236\box \scratchbox
237\stoptyping
238
239\stopsectionlevel
240
241\startsectionlevel[title={\ETEX\ primitives}]
242
243The \ETEX\ extensions don't add something relevant for boxes, apart from that you
244can use the expressions mechanism to mess around with their dimensions. There is
245a mechanism for typesetting r2l within a paragraph but that has limited
246capabilities and doesn't change much as it's mostly a way to trick the backend
247into outputting a stretch of text in the other direction. This feature is not
248available in \LUATEX\ because it has an alternative direction mechanism.
249
250\stopsectionlevel
251
252\startsectionlevel[title={\LUATEX\ primitives}]
253
254The concept of boxes is the same in \LUATEX\ as in its predecessors but there are
255some aspects to keep in mind. When a box is typeset this happens in \LUATEX:
256
257\startitemize[n]
258    \startitem
259        A list of nodes is constructed. In \LUATEX\ this is a double linked
260        list (so that it can easily be manipulated in \LUA) but \TEX\ itself
261        only uses the forward links.
262    \stopitem
263    \startitem
264        That list is hyphenated, that is: so called discretionary nodes are
265        injected. This depends on the language properties of the glyph
266        (character) nodes.
267    \stopitem
268    \startitem
269        Then ligatures are constructed, if the font has such combinations. When
270        this built|-|in mechanism is used, in \CONTEXT\ we speak of base mode.
271    \stopitem
272    \startitem
273        After that inter|-|character kerns are applied, if the font provides
274        them. Again this is a base mode action.
275    \stopitem
276    \startitem
277        Finally the box gets packaged:
278        \startitemize
279            \startitem
280                In the case of a horizontal box, the list is packaged in a
281                hlist node, basically one liner, and its dimensions are calculated
282                and set.
283            \stopitem
284            \startitem
285                In the case of a vertical box, the paragraph is broken into one
286                or more lines, without hyphenation, with optimal hyphenation or
287                in the worst case with so called emergency stretch applied, and
288                the result becomes a vlist node with its dimensions set.
289            \stopitem
290        \stopitemize
291    \stopitem
292\stopitemize
293
294In traditional \TEX\ the first four steps are interwoven but in \LUATEX\ we need
295them split because the step~5 can be overloaded by a callback. In that case steps
2963 and 4 (and maybe 2) are probably also overloaded, especially when you bring
297handling of fonts under \LUA\ control.
298
299New in \LUATEX\ are three packers: \type {\hpack}, \type {\vpack} and \type
300{\tpack}, which are companions to \type {\hbox}, \type {\vbox} and \type {\vtop}
301but without the callbacks applied. Using them is a bit tricky as you never know
302if a callback should be applied, which, because users can often add their own
303\LUA\ code, is not something predictable.
304
305Another box related extension is direction. There are four possible directions
306but because in \LUAMETATEX\ there are only two. Because this model has been upgraded,
307it will be discusses in the next section. A \CONTEXT\ user is supposed to use the
308official \CONTEXT\ interfaces in order to be downward compatible.
309
310\stopsectionlevel
311
312\startsectionlevel[title={\LUAMETATEX\ primitives}]
313
314There are two possible directions: left to right (the default) and right to left
315for Hebrew and Arabic. Here is an example that shows how it'd done with low level
316directives:
317
318\startbuffer
319\hbox direction 0 {from left to right}
320\hbox direction 1 {from right to left}
321\stopbuffer
322
323\typebuffer[option=TEX]
324
325\startlinecorrection
326\getbuffer
327\stoplinecorrection
328
329A low level direction switch is done with:
330
331\startbuffer
332\hbox direction 0
333    {from left to right \textdirection 1 from right to left}
334\hbox direction 1
335    {from right to left \textdirection 1 from left to right}
336\stopbuffer
337
338\typebuffer[option=TEX]
339
340\startlinecorrection
341\getbuffer
342\stoplinecorrection
343
344but actually this is kind of {\em not done} in \CONTEXT, because there you are
345supposed to use the proper direction switches:
346
347\startbuffer
348\naturalhbox {from left to right}
349\reversehbox {from right to left}
350\naturalhbox {from left to right \righttoleft from right to left}
351\reversehbox {from right to left \lefttoright from left to right}
352\stopbuffer
353
354\typebuffer[option=TEX]
355
356\startlinecorrection
357\getbuffer
358\stoplinecorrection
359
360Often more is needed to properly support right to left typesetting so using the
361\CONTEXT\ commands is more robust.
362
363In \LUAMETATEX\ the box model has been extended a bit, this as a consequence of
364dropping the vertical directional typesetting, which never worked well. In
365previous sections we discussed the properties width, height and depth and the
366shift resulting from a \type {\raise}, \type {\lower}, \type {\moveleft} and
367\type {\moveright}. Actually, the shift is also used in for instance positioning
368math elements.
369
370The way shifting influences dimensions can be somewhat puzzling. Internally, when
371\TEX\ packages content in a box there are two cases:
372
373\startitemize
374    \startitem
375        When a horizontal box is made, and \typ {height - shift} is larger than the
376        maximum height so far, that delta is taken. When \typ {depth + shift} is
377        larger than the current depth, then that depth is adapted. So, a shift up
378        influences the height and a shift down influences the depth.
379    \stopitem
380    \startitem
381        In the case of vertical packaging, when \typ {width + shift} is larger
382        than the maximum box (line) width so far, that maximum gets bumped. So, a
383        shift to the right can contribute, but a shift to the left cannot result
384        in a negative width. This is also why vertical typesetting, where height
385        and depth are swapped with width, goes wrong: we somehow need to map two
386        properties onto one and conceptually \TEX\ is really set up for
387        horizontal typesetting. (And it's why I decided to just remove it from the
388        engine.)
389    \stopitem
390\stopitemize
391
392This is one of these cases where \TEX\ behaves as expected but it also means that
393there is some limitation to what can be manipulated. Setting the shift using one
394of the four commands has a direct consequence when a box gets packaged which
395happens immediately because the box is an argument to the foursome.
396
397There is in traditional \TEX, probably for good reason, no way to set the shift
398of a box, if only because the effect would normally be none. But in \LUATEX\ we
399can cheat, and therefore, for educational purposed \CONTEXT\ has implements
400some cheats.
401
402We use this sample box:
403
404\startbuffer[demo]
405\setbox\scratchbox\hbox\bgroup
406    \middlegray\vrule width 20mm depth  -.5mm height 10mm
407    \hskip-20mm
408    \darkgray  \vrule width 20mm height -.5mm depth   5mm
409\egroup
410\stopbuffer
411
412\typebuffer[demo][option=TEX]
413
414When we mess with the shift using the \CONTEXT\ \type {\shiftbox} helper, we see
415no immediate effect. We only get the shift applied when we use another helper,
416\type {\hpackbox}.
417
418\startbuffer
419\hbox\bgroup
420    \showstruts \strut
421    \quad                            \copy\scratchbox
422    \quad \shiftbox\scratchbox -20mm \copy\scratchbox
423    \quad \hpackbox\scratchbox       \box \scratchbox
424    \quad \strut
425\egroup
426\stopbuffer
427
428\typebuffer[option=TEX]
429
430\startlinecorrection
431\getbuffer[demo]\getbuffer
432\stoplinecorrection
433
434When instead we use \type {\vpackbox} we get a different result. This time we
435move left.
436
437\startbuffer
438\hbox\bgroup
439    \showstruts \strut
440    \quad                            \copy\scratchbox
441    \quad \shiftbox\scratchbox -10mm \copy\scratchbox
442    \quad \vpackbox\scratchbox       \copy\scratchbox
443    \quad \strut
444\egroup
445\stopbuffer
446
447\typebuffer[option=TEX]
448
449\startlinecorrection
450\getbuffer[demo]\getbuffer
451\stoplinecorrection
452
453The shift is set via \LUA\ and the repackaging is also done in \LUA, using the
454low level \type {hpack} and \type {vpack} helpers and these just happen to look
455at the shift when doing their job. At the \TEX\ end this never happens.
456
457This long exploration of shifting serves a purpose: it demonstrates that there is
458not that much direct control over boxes apart from their three dimensions.
459However this was never a real problem as one can just wrap a box in another one
460and use kerns to move the embedded box around. But nevertheless I decided to see
461if the engine can be a bit more helpful, if only because all that extra wrapping
462gives some overhead and complications when we want to manipulate boxes. And of
463course it is also a nice playground.
464
465We start with changing the direction. Changing this property doesn't require
466repackaging because directions are not really dealt with in the frontend. When
467a box is converted to (for instance \PDF) the reversion happens.
468
469\startbuffer
470\setbox\scratchbox\hbox{whatever}
471\the\boxdirection\scratchbox: \copy\scratchbox \crlf
472\boxdirection\scratchbox 1
473\the\boxdirection\scratchbox: \copy\scratchbox
474\stopbuffer
475
476\typebuffer[option=TEX]
477
478\startlinecorrection
479\getbuffer
480\stoplinecorrection
481
482Another property that can be queried and set is an attribute. In order to get
483a private attribute we define one.
484
485\startbuffer
486\newattribute\MyAt
487\setbox\scratchbox\hbox attr \MyAt 123 {whatever}
488[\the\boxattribute\scratchbox\MyAt]
489\boxattribute\scratchbox\MyAt 456
490[\the\boxattribute\scratchbox\MyAt]
491[\ifnum\boxattribute\scratchbox\MyAt>400 okay\fi]
492\stopbuffer
493
494\typebuffer[option=TEX]
495
496\startlinecorrection
497\getbuffer
498\stoplinecorrection
499
500The sum of the height and depth is available too. Because for practical reasons
501setting that property is also needed then, the choice was made to distribute the
502value equally over height and depth.
503
504\startbuffer
505\setbox\scratchbox\hbox {height and depth}
506[\the\ht\scratchbox]
507[\the\dp\scratchbox]
508[\the\boxtotal\scratchbox]
509\boxtotal\scratchbox=20pt
510[\the\ht\scratchbox]
511[\the\dp\scratchbox]
512[\the\boxtotal\scratchbox]
513\stopbuffer
514
515\typebuffer[option=TEX]
516
517\startlinecorrection
518\getbuffer
519\stoplinecorrection
520
521We've now arrived to a set of properties that relate to each other. They are
522a bit complex and given the number of possibilities one might need to revert
523to some trial and error: orientations and offsets. As with the dimensions,
524directions and attributes, they are passed as box specification. We start
525with the orientation.
526
527\startbuffer
528\hbox \bgroup \showboxes
529          \hbox orientation 0 {right}
530    \quad \hbox orientation 1 {up}
531    \quad \hbox orientation 2 {left}
532    \quad \hbox orientation 3 {down}
533\egroup
534\stopbuffer
535
536\typebuffer[option=TEX]
537
538\startlinecorrection
539\getbuffer
540\stoplinecorrection
541
542When the orientation is set, you can also set an offset. Where shifting around a box
543can have consequences for the dimensions, an offset is virtual. It gets effective
544in the backend, when the contents is converted to some output format.
545
546\startbuffer
547\hbox \bgroup \showboxes
548          \hbox orientation 0 yoffset  10pt {right}
549    \quad \hbox orientation 1 xoffset  10pt {up}
550    \quad \hbox orientation 2 yoffset -10pt {left}
551    \quad \hbox orientation 3 xoffset -10pt {down}
552\egroup
553\stopbuffer
554
555\typebuffer[option=TEX]
556
557\startlinecorrection
558\getbuffer
559\stoplinecorrection
560
561The reason that offsets are related to orientation is that we need to know in
562what direction the offsets have to be applied and this binding forces the user to
563think about it. You can also set the offsets using commands.
564
565\startbuffer
566\setbox\scratchbox\hbox{whatever}%
5671                                  \copy\scratchbox
5682 \boxorientation\scratchbox 2     \copy\scratchbox
5693 \boxxoffset    \scratchbox -15pt \copy\scratchbox
5704 \boxyoffset    \scratchbox -15pt \copy\scratchbox
5715
572\stopbuffer
573
574\typebuffer[option=TEX]
575
576\startlinecorrection
577\ruledhbox{\getbuffer}
578\stoplinecorrection
579
580\startbuffer
581\setbox\scratchboxone\hbox{whatever}%
582\setbox\scratchboxtwo\hbox{whatever}%
5831 \boxxoffset \scratchboxone -15pt \copy\scratchboxone
5842 \boxyoffset \scratchboxone -15pt \copy\scratchboxone
5853 \boxxoffset \scratchboxone -15pt \copy\scratchboxone
5864 \boxyoffset \scratchboxone -15pt \copy\scratchboxone
5875 \boxxmove   \scratchboxtwo -15pt \copy\scratchboxtwo
5886 \boxymove   \scratchboxtwo -15pt \copy\scratchboxtwo
5897 \boxxmove   \scratchboxtwo -15pt \copy\scratchboxtwo
5908 \boxymove   \scratchboxtwo -15pt \copy\scratchboxtwo
591\stopbuffer
592
593\typebuffer[option=TEX]
594
595\startlinecorrection
596\ruledhbox{\getbuffer}
597\stoplinecorrection
598
599The move commands are provides as convenience and contrary to the offsets they do
600adapt the dimensions. Internally, with the box, we register the orientation and
601the offsets and when you apply these commands multiple times the current values
602get overwritten. But \unknown\ because an orientation can be more complex you
603might not get the effects you expect when the options we discuss next are used.
604The reason is that we store the original dimensions too and these come into play
605when these other options are used: anchoring. So, normally you will apply an
606orientation and offsets once only.
607
608% the next bit is derived from the followingup document
609
610The orientation specifier is actually a three byte number that best can be seen
611hexadecimal (although we stay within the decimal domain). There are three
612components: x|-|anchoring, y|-|anchoring and orientation:
613
614\starttyping
6150x<X><Y><O>
616\stoptyping
617
618or in \TEX\ speak:
619
620\starttyping
621"<X><Y><O>
622\stoptyping
623
624The landscape and seascape variants both sit on top of the baseline while the
625flipped variant has its depth swapped with the height. Although this would be
626enough a bit more control is possible.
627
628The vertical options of the horizontal variants anchor on the baseline, lower
629corner, upper corner or center.
630
631\startbuffer
632\ruledhbox orientation "002 {\TEX} and
633\ruledhbox orientation "012 {\TEX} and
634\ruledhbox orientation "022 {\TEX} and
635\ruledhbox orientation "032 {\TEX}
636\stopbuffer
637
638\typebuffer[option=TEX]
639
640\startlinecorrection
641\ruledhbox{\getbuffer}
642\stoplinecorrection
643
644The horizontal options of the horizontal variants anchor in the center, left,
645right, halfway left and halfway right.
646
647\startbuffer
648\ruledhbox orientation "002 {\TEX} and
649\ruledhbox orientation "102 {\TEX} and
650\ruledhbox orientation "202 {\TEX} and
651\ruledhbox orientation "302 {\TEX} and
652\ruledhbox orientation "402 {\TEX}
653\stopbuffer
654
655\typebuffer[option=TEX]
656
657\startlinecorrection
658\ruledhbox{\getbuffer}
659\stoplinecorrection
660
661The orientation has consequences for the dimensions so they are dealt with in the
662expected way in constructing lines, paragraphs and pages, but the anchoring is
663virtual, like the offsets. There are two extra variants for orientation zero: on
664top of baseline or below, with dimensions taken into account.
665
666\startbuffer
667\ruledhbox orientation "000 {\TEX} and
668\ruledhbox orientation "004 {\TEX} and
669\ruledhbox orientation "005 {\TEX}
670\stopbuffer
671
672\typebuffer[option=TEX]
673
674\startlinecorrection
675\ruledhbox{\getbuffer}
676\stoplinecorrection
677
678The anchoring can look somewhat confusing but you need to keep in mind that it is
679normally only used in very controlled circumstances and not in running text.
680Wrapped in macros users don't see the details. We're talking boxes here, so for
681instance:
682
683\startbuffer
684test\quad
685\hbox orientation 3 \bgroup
686    \strut test\hbox orientation "002 \bgroup\strut test\egroup test%
687\egroup \quad
688\hbox orientation 3 \bgroup
689    \strut test\hbox orientation "002 \bgroup\strut test\egroup test%
690\egroup \quad
691\hbox orientation 3 \bgroup
692    \strut test\hbox orientation "012 \bgroup\strut test\egroup test%
693\egroup \quad
694\hbox orientation 3 \bgroup
695    \strut test\hbox orientation "022 \bgroup\strut test\egroup test%
696\egroup \quad
697\hbox orientation 3 \bgroup
698    \strut test\hbox orientation "032 \bgroup\strut test\egroup test%
699\egroup \quad
700\hbox orientation 3 \bgroup
701    \strut test\hbox orientation "042 \bgroup\strut test\egroup test%
702\egroup
703\quad test
704\stopbuffer
705
706\typebuffer[option=TEX]
707
708\startlinecorrection
709\ruledhbox{\getbuffer}
710\stoplinecorrection
711
712Where a \type {\vtop} has the baseline at the top, a \type {\vbox} has it at the
713bottom. In \LUAMETATEX\ we also have a \type {\dbox}, which is a \type {\vbox} with
714that behaves like a \type {\vtop} when it's appended to a vertical list: the height of
715the first box or rule determines the (base)line correction that gets applied. The following
716example demonstrates this:
717
718\startlinecorrection
719\startcombination [nx=3,ny=1,location=top]
720    {\vbox \bgroup \hsize .3\textwidth
721        \small\small \setupalign[tolerant,stretch] \dontcomplain
722        xxxxxxxxxxxxxxxx\par
723        \ruledvbox{\samplefile{tufte}}\par
724        xxxxxxxxxxxxxxxx\par
725     \egroup} {\type {\vbox}}
726    {\vbox \bgroup \hsize .3\textwidth
727        \small\small \setupalign[tolerant,stretch] \dontcomplain
728        xxxxxxxxxxxxxxxx\par
729        \ruledvtop{\samplefile{tufte}}\par
730        xxxxxxxxxxxxxxxx\par
731     \egroup} {\type {\vtop}}
732    {\vbox \bgroup \hsize .3\textwidth
733        \small\small \setupalign[tolerant,stretch] \dontcomplain
734        xxxxxxxxxxxxxxxx\par
735        \ruleddbox{\samplefile{tufte} }\par
736        xxxxxxxxxxxxxxxx\par
737     \egroup} {\type {\dbox}}
738\stopcombination
739\stoplinecorrection
740
741The \type {d} stands for \quote {dual} because we (sort of) have two baselines. The
742regular height and depth are those of a \type {\vbox}.
743
744\stopsectionlevel
745
746\startsectionlevel[title=Splitting]
747
748When you feed \TEX\ a paragraph of text it will accumulate the content in a
749list of nodes. When the paragraphs is finished by \type {\par} or an empty line
750it will be fed into the par builder that will try to break the lines as good
751as possible. Normally that paragraph will be added to the page and at some point
752there can be breaks between lines in order not to overflow the page. When you
753collect the paragraph in a box you can use \type {\vsplit} to emulate this.
754
755\startbuffer[sample]
756\setbox\scratchbox\vbox{\samplefile{tufte}}
757
758\startlinecorrection
759\ruledhbox{\vsplit\scratchbox to 2\lineheight}
760\stoplinecorrection
761\stopbuffer
762
763\typebuffer[sample][option=TEX] \getbuffer[sample]
764
765The split off box is given the specified height, but in \LUAMETATEX\ you can also
766get the natural dimensions:
767
768\startbuffer[sample]
769\setbox\scratchbox\vbox{\samplefile{tufte}}
770
771\startlinecorrection
772\ruledhbox{\vsplit\scratchbox upto 2\lineheight}
773\stoplinecorrection
774\stopbuffer
775
776\typebuffer[sample][option=TEX] \getbuffer[sample]
777
778We can force a resulting box type by using \type {\vsplit}, \type {\tsplit} and
779\type {\dsplit} (here we use the visualized variants):
780
781\startbuffer[sample]
782\setbox\scratchbox\vbox{\samplefile{tufte}}
783
784\startlinecorrection
785\ruledtsplit \scratchbox upto 2\lineheight
786\stoplinecorrection
787\stopbuffer
788
789\typebuffer[sample][option=TEX] \getbuffer[sample]
790
791\startbuffer[sample]
792\setbox\scratchbox\vbox{\samplefile{tufte}}
793
794\startlinecorrection
795\ruledvsplit \scratchbox upto 2\lineheight
796\stoplinecorrection
797\stopbuffer
798
799\typebuffer[sample][option=TEX] \getbuffer[sample]
800
801\startbuffer[sample]
802\setbox\scratchbox\vbox{\samplefile{tufte}}
803
804\startlinecorrection
805\ruleddsplit \scratchbox upto 2\lineheight
806\stoplinecorrection
807\stopbuffer
808
809\typebuffer[sample][option=TEX] \getbuffer[sample]
810
811The engine provides vertical splitters but \CONTEXT\ itself also has
812a horizontal one. \footnote {At some point I might turn that one into
813a native engine primitive.}
814
815\startbuffer
816\starttexdefinition Test #1#2#3
817    \par
818    \dontleavehmode
819    \strut
820    \llap{{\infofont #2}\quad}
821    \blackrule[width=#2,color=darkblue]
822    \par
823    \setbox\scratchbox\hbox{\samplefile{#1}}
824    \hsplit\scratchbox
825        to              #2
826        depth           \strutdp
827        height          \strutht
828        shrinkcriterium #3 % badness
829    \par
830\stoptexdefinition
831
832\dostepwiserecurse {100} {120} {2} {
833    \Test{tufte}{#1mm}{1000}
834    \Test{tufte}{#1mm}{-100}
835}
836\stopbuffer
837
838\typebuffer[option=TEX] \startpacked \getbuffer \stoppacked
839
840A split off box gets packed at its natural size and a badness as well as
841overshoot amount is calculated. When the overshoot is positive and the the
842badness is larger than the stretch criterium, the box gets repacked to the
843natural size. The same happens when the overshoot is negative and the badness
844exceeds the shrink criterium. When the overshoot is zero (basically we have a
845fit) but the badness still exceeds the stretch or shrink we also repack. Indeed
846this is a bit fuzzy, but so is badness.
847
848\startbuffer
849\starttexdefinition Test #1#2#3
850    \par
851    \dontleavehmode
852    \strut
853    \llap{{\infofont #2}\quad}
854    \blackrule[width=#2,color=darkblue]
855    \par
856    \setbox\scratchbox\hbox{\samplefile{#1}}
857    \doloop {
858        \ifvoid\scratchbox
859            \exitloop
860        \else
861            \hsplit\scratchbox
862                to     #2
863                depth  \strutdp
864                height \strutht
865                #3
866            \par
867            \allowbreak
868        \fi
869    }
870\stoptexdefinition
871
872\Test{tufte}{100mm}{shrinkcriterium 1000}
873\Test{tufte}{100mm}{shrinkcriterium 0}
874\Test{tufte}{100mm}{}
875\stopbuffer
876
877\typebuffer[option=TEX] \getbuffer
878
879Watch how the last line get stretched when we set the criterium to zero. I'm sure
880that users will find reasons to abuse this effect.
881
882\stopsectionlevel
883
884\stopdocument
885
886% todo:
887
888% \setbox0\hbox{\strut this is just a\footnote{oeps} test}
889% \setbox2\hbox{\strut this is just a\footnote{oeps} test}
890%
891% \setprelistbox 0\hbox{\strut \quad before: \prelistbox0}
892% \setpostlistbox0\hbox{\strut \quad after: \postlistbox0}
893%
894% \setprelistbox 2\hbox{\strut \quad before}
895% \setpostlistbox2\hbox{\strut \quad after}
896%
897% test \par \box0 \par \box2 \par test
898
899
900\setbox0\vbox
901{
902    \setbox    \scratchbox      \hbox{XXX}
903    \boxvadjust\scratchbox pre       {BBB}
904    \boxvadjust\scratchbox post      {AAA}
905%     \dontleavehmode % needed
906    \box\scratchbox
907%     \unhbox\scratchbox
908}
909
910111111\par \box0 \par 222222\par
911