1
2
3\environment lowlevelstyle
4
5\startdocument
6 [title=paragraphs,
7 color=middlecyan]
8
9\startsectionlevel[title=Introduction]
10
11This manual is mostly discussing a few low level wrappers around low level \TEX\
12features. Its writing is triggered by an update to the \METAFUN\ and \LUAMETAFUN\
13manuals where we mess a bit with shapes. It gave a good reason to also cover some
14more paragraph related topics but it might take a while to complete. Remind me if
15you feel that takes too much time.
16
17Because paragraphs and their construction are rather central to \TEX, you can
18imagine that the engine exposes dealing with them. This happens via commands
19(primitives) but only when its robust. Then there are callbacks, and some
20provide detailed information about what were dealing with. However, intercepting
21node lists can already be hairy and we do that a lot in \CONTEXT. Intercepting
22and tweaking paragraph properties is even more tricky, which is why we try to
23avoid that in the core. But \unknown\ in the following sections you will see that
24there are actually a couple of mechanism that do so. Often new features like this
25are built in stepwise and enabled locally for a while and when they seem okay
26they get enabled by default. \footnote {For this we have \type
27{\enableexperiments} which one can use in \type {contloc.mkxl} or \type
28{contexp.mkxl}, files that are loaded runtime when on the system. When you use
29them, make sure they dont interfere; they are not part of the updates, contrary
30to \type {contnew.mkxl}.}
31
32\stopsectionlevel
33
34\startsectionlevel[title=Paragraphs]
35
36Before we demonstrate some trickery, lets see what a paragraph is. Normally a
37document source is formatted like this:
38
39\starttyping[option=TEX]
40some text (line 1)
41some text (line 2)
42
43some more test (line 1)
44some more test (line 2)
45\stoptyping
46
47There are two blocks of text here separated by an empty line and they become two
48paragraphs. Unless configured otherwise an empty line is an indication that we
49end a paragraph. You can also explicitly do that:
50
51\starttyping[option=TEX]
52some text (line 1)
53some text (line 2)
54\par
55some more test (line 1)
56some more test (line 2)
57\stoptyping
58
59When \TEX\ starts a paragraph, it actually also does something think of:
60
61\starttyping[option=TEX]
62[\the\everypar]some text (line 1) some text (line 2) \par
63[\the\everypar]some more test (line 1) some more test (line 2) \par
64\stoptyping
65
66or more accurate:
67
68\starttyping[option=TEX]
69[\the\everypar]some text some text \par
70[\the\everypar]some more test some more test \par
71\stoptyping
72
73because the endofline character has become a space. As mentioned,
74an empty line is actually the end of a paragraph. But in \LUAMETATEX\
75we can cheat a bit. If we have this:
76
77\startbuffer
78line 1
79
80line 2
81\stopbuffer
82
83\typebuffer[option=TEX]
84
85We can do this (watch how we need to permit overloading a primitive when we have
86enabled \type {\overloadmode}):
87
88\startbuffer
89\pushoverloadmode
90\def\linepar{\removeunwantedspaces !\ignorespaces}
91\popoverloadmode
92line 1
93
94line 2
95\stopbuffer
96
97\typebuffer[option=TEX]
98
99This comes out as:
100
101\start \getbuffer \stop
102
103I admit that since it got added (as part of some cleanup halfway the overhaul of
104the engine) I never saw a reason to use it, but it is a cheap feature. The \type
105{\linepar} primitive is undefined (\type {\undefined}) by default so no user sees
106it anyway. Just dont use it unless maybe for some pseudo database trickery (I
107considered using it for the database module but it is not needed). In a similar
108fashion, just dont redefine \type {\par}: its asking for troubles and \quote
109{not done} in \CONTEXT\ anyway.
110
111Back to reality. In \LUATEX\ we get a node list that starts with a so called
112\type {localpar} node and ends with a \type {\parfillskip}. The first node is
113prepended automatically. That list travels through the system: hyphenation,
114applying font properties, break the effectively one line into lines, wrap them
115and add them to a vertical list, etc. Each stage can be intercepted via
116callbacks.
117
118When the paragraph is broken into lines hanging indentation or a so called par
119shape can be applied, and we will see more of that later, here we talk \type
120{\par} and show another \LUAMETATEX\ trick:
121
122\startbuffer
123\def\foo{{\bf test:} \ignorepars}
124
125\foo
126
127line
128\stopbuffer
129
130\typebuffer[option=TEX]
131
132The macro typesets some text and then skips to the next paragraph:
133
134\start \getbuffer \stop
135
136Think of this primitive as being a more powerful variant of \type
137{\ignorespaces}. This leaves one aspect: how do we start a paragraph. Technically
138we need to force \TEX\ into so called horizontal mode. When you look at plain
139\TEX\ documents you will notice commands like \type {\noindent} and \type
140{\indent}. In \CONTEXT\ we have more high level variants, for instance we have
141\type {\noindentation}.
142
143A robust way to make sure that you get in horizontal mode is using \type
144{\dontleavehmode} which is a wink to \type {\leavevmode}, a command that you
145should never use in \CONTEXT, so when you come from plain or \LATEX, its one of
146the commands you should wipe from your memory.
147
148When \TEX\ starts with a paragraph the \type {\everypar} token list is expanded
149and again this is a primitive you should not mess with yourself unless in very
150controlled situations. If you change its content, youre on your own with respect
151to interferences and side effects.
152
153One of the things that \TEX\ does in injecting the indentation. Even when there
154is none, it gets added, not as skip but as an empty horizontal box of a certain
155width. This is easier on the engine when it constructs the paragraph from the one
156liner: starting with a skip demands a bit more testing in the process (a nice
157trick so to say). However, in \CONTEXT\ we enable the \LUAMETATEX\ feature that
158does use a skip instead of a box. Its part of the normalization that is
159discussed later. Instead of checking for a box with property indent, we check for
160a skip with such property. This is often easier and cleaner.
161
162A bit off topic is the fact that in traditional \TEX\ empty lines or \type {\par}
163primitives can trigger an error. This has to do with the fact that the program
164evolved in a time where paper terminals were used and runtime could be excessive.
165So, in order to catch a possible missing brace, a concept of \type {\long}
166macros, permitting \type {\par} or equivalents in arguments, was introduced as
167well as not permitting them in for instance display math. In \CONTEXT\ \MKII\
168most macros that could be sensitive for this were defined as \type {\long} so
169that users never had to bother about it and probably were not even aware of it.
170Right from the start in \LUATEX\ these errortriggers could be disabled which
171of course we enable in \CONTEXT\ and in \LUAMETATEX\ these features have been
172removed altogether. I dont think users will complain about this.
173
174If you want to enforce a newline but not a new paragraph you can use the \type
175{\crlf} command. When used on its own it will produce an empty line. Dont use
176this to create whitespace between lines.
177
178If you want to do something after so called par tokens are seen you can do this:
179
180\startbuffer
181\def\foo{{\bf >>>> }}
182\expandafterpars\foo
183
184this is a new paragraph ...
185
186\expandafterpars\foo
187\par\par\par\par
188this is a new paragraph ...
189\stopbuffer
190
191\typebuffer[option=TEX]
192
193This not to be confused with \type {\everypar} which is a token list that \TEX\
194itself injects before each paragraph (also nested ones).
195
196\getbuffer
197
198This is typically a primitive that will only be used in macros. You can actually
199program it using macros: pickup a token, check and push it back when its not a
200par equivalent token. The primitive is is just nicer (and easier on the log when
201tracing is enabled).
202
203\stopsectionlevel
204
205\startsectionlevel[title=Properties]
206
207A paragraph is just a collection of lines that result from one input line that
208got broken. This process of breaking into lines is influenced by quite some
209parameters. In traditional \TEX\ and also in \LUAMETATEX\ by default the values
210that are in effect when the end of the paragraph is met are used. So, when you
211change them in a group and then ends the paragraph after the group, the values
212youve set in the group are not used.
213
214However, in \LUAMETATEX\ we can optionally store them with the paragraph. When
215that happens the values current at the start are frozen. You can still overload
216them but that has to be done explicitly then. The advantage is that grouping no
217longer interferes with the line break algorithm. The magic primitive is \type
218{\snapshotpar} which takes a number made from categories mentioned below:
219
220\starttabulate[llr]
221\BC variable \BC category \BC code \NC \NR
222\NC \type {\hsize} \NC hsize \NC 0x\uchexnumbers\hsizefrozenparcode \NC \NR
223\NC \type {\leftskip} \NC skip \NC 0x\uchexnumbers\skipfrozenparcode \NC \NR
224\NC \type {\rightskip} \NC skip \NC 0x\uchexnumbers\skipfrozenparcode \NC \NR
225\NC \type {\hangindent} \NC hang \NC 0x\uchexnumbers\hangfrozenparcode \NC \NR
226\NC \type {\hangafter} \NC hang \NC 0x\uchexnumbers\hangfrozenparcode \NC \NR
227\NC \type {\parindent} \NC indent \NC 0x\uchexnumbers\indentfrozenparcode \NC \NR
228\NC \type {\parfillleftskip} \NC par fill \NC 0x\uchexnumbers\parfillfrozenparcode \NC \NR
229\NC \type {\parfillrightskip} \NC par fill \NC 0x\uchexnumbers\parfillfrozenparcode \NC \NR
230\NC \type {\adjustspacing} \NC adjust \NC 0x\uchexnumbers\adjustfrozenparcode \NC \NR
231\NC \type {\adjustspacingstep} \NC adjust \NC 0x\uchexnumbers\adjustfrozenparcode \NC \NR
232\NC \type {\adjustspacingshrink} \NC adjust \NC 0x\uchexnumbers\adjustfrozenparcode \NC \NR
233\NC \type {\adjustspacingstretch} \NC adjust \NC 0x\uchexnumbers\adjustfrozenparcode \NC \NR
234\NC \type {\protrudechars} \NC protrude \NC 0x\uchexnumbers\protrudefrozenparcode \NC \NR
235\NC \type {\pretolerance} \NC tolerance \NC 0x\uchexnumbers\tolerancefrozenparcode \NC \NR
236\NC \type {\tolerance} \NC tolerance \NC 0x\uchexnumbers\tolerancefrozenparcode \NC \NR
237\NC \type {\emergencystretch} \NC stretch \NC 0x\uchexnumbers\stretchfrozenparcode \NC \NR
238\NC \type {\looseness} \NC looseness \NC 0x\uchexnumbers\loosenessfrozenparcode \NC \NR
239\NC \type {\lastlinefit} \NC last line \NC 0x\uchexnumbers\lastlinefrozenparcode \NC \NR
240\NC \type {\linepenalty} \NC line penalty \NC 0x\uchexnumbers\linepenaltyfrozenparcode \NC \NR
241\NC \type {\interlinepenalty} \NC line penalty \NC 0x\uchexnumbers\linepenaltyfrozenparcode \NC \NR
242\NC \type {\interlinepenalties} \NC line penalty \NC 0x\uchexnumbers\linepenaltyfrozenparcode \NC \NR
243\NC \type {\clubpenalty} \NC club penalty \NC 0x\uchexnumbers\clubpenaltyfrozenparcode \NC \NR
244\NC \type {\clubpenalties} \NC club penalty \NC 0x\uchexnumbers\clubpenaltyfrozenparcode \NC \NR
245\NC \type {\widowpenalty} \NC widow penalty \NC 0x\uchexnumbers\widowpenaltyfrozenparcode \NC \NR
246\NC \type {\widowpenalties} \NC widow penalty \NC 0x\uchexnumbers\widowpenaltyfrozenparcode \NC \NR
247\NC \type {\displaywidowpenalty} \NC display penalty \NC 0x\uchexnumbers\displaypenaltyfrozenparcode \NC \NR
248\NC \type {\displaywidowpenalties} \NC display penalty \NC 0x\uchexnumbers\displaypenaltyfrozenparcode \NC \NR
249\NC \type {\brokenpenalty} \NC broken penalty \NC 0x\uchexnumbers\brokenpenaltyfrozenparcode \NC \NR
250\NC \type {\adjdemerits} \NC demerits \NC 0x\uchexnumbers\demeritsfrozenparcode \NC \NR
251\NC \type {\doublehyphendemerits} \NC demerits \NC 0x\uchexnumbers\demeritsfrozenparcode \NC \NR
252\NC \type {\finalhyphendemerits} \NC demerits \NC 0x\uchexnumbers\demeritsfrozenparcode \NC \NR
253\NC \type {\parshape} \NC shape \NC 0x\uchexnumbers\shapefrozenparcode \NC \NR
254\NC \type {\baselineskip} \NC line \NC 0x\uchexnumbers\linefrozenparcode \NC \NR
255\NC \type {\lineskip} \NC line \NC 0x\uchexnumbers\linefrozenparcode \NC \NR
256\NC \type {\lineskiplimit} \NC line \NC 0x\uchexnumbers\linefrozenparcode \NC \NR
257\NC \type {\hyphenationmode} \NC hyphenation \NC 0x\uchexnumbers\hyphenationfrozenparcode \NC \NR
258\stoptabulate
259
260As you can see here, there are more paragraph related parameters than in for
261instance \PDFTEX\ and \LUATEX\ and these are (to be) explained in the
262\LUAMETATEX\ manual. You can imagine that keeping this around with the paragraph
263adds some extra overhead to the machinery but most users wont notice that
264because is is compensated by gains elsewhere.
265
266This is pretty low level and there are a bunch of helpers that support this but
267these are not really user level macros. As with everything \TEX\ you can mess
268around as much as you like, and the code gives plenty of examples but when you do
269this, youre on your own because it can interfere with \CONTEXT\ core
270functionality.
271
272In \LMTX\ taking these snapshots is turned on by default and because it thereby
273fundamentally influences the par builder, users can run into compatibility issues
274but in practice there has been no complaints (and this feature has been in use
275quite a while before this document was written). One reason for users not
276noticing is that one of the big benefits is probably handled by tricks mentioned
277on the mailing list. Imagine that you have this:
278
279\starttyping[option=TEX]
280{\bf watch out:} here is some text
281\stoptyping
282
283In this small example the result will be as expected. But what if something magic
284with the start of a paragraph is done? Like this:
285
286\starttyping[option=TEX]
287\placefigure[left]{A cow!}{\externalfigure[cow.pdf]}
288
289{\bf watch out:} here is some text ... of course much more is needed to
290 get a flow around the figure!
291\stoptyping
292
293The figure will hang at the left side of the paragraph but it is put there when
294the text starts and that happens inside the bold group. It means that the
295properties we set in order to get the shape around the figure are lost as soon as
296were at \quote{\type {here is some text}} and definitely is wrong when the
297paragraph ends and the par builder has to use them to get the shape right. We get
298text overlapping the figure. A trick to overcome this is:
299
300\starttyping[option=TEX]
301\dontleavehmode {\bf watch out:} here is some text ... of course much
302 more is needed to get a flow around the figure!
303\stoptyping
304
305where the first macro makes sure we already start a paragraph before the group is
306entered (using a \type {\strut} also works). Its not nice and I bet users have
307been bitten by this and by now know the tricks. But, with snapshots such fuzzy
308hacks are not needed any more! The same is true with this:
309
310\starttyping[option=TEX]
311{\leftskip 1em some text \par}
312\stoptyping
313
314where we had to explicitly end the paragraph inside the group in order to retain
315the skip. I suppose that users normally use the high level environments so they
316never had to worry about this. Its also why users probably wont notice that
317this new mechanism has been active for a while. Actually, when you now change a
318parameter inside the paragraph its new value will not be applied (unless you
319prefix it with \type {\frozen} or snapshot it) but no one did that anyway.
320
321\stopsectionlevel
322
323\startsectionlevel[title=Wrapping up]
324
325In \CONTEXT\ \LMTX\ we have a mechanism to exercise macros (or content) before a
326paragraph ends. This is implemented using the \type {\wrapuppar} primitive. The
327to be wrapped up material is bound to the current paragraph which in order to
328get this done has to be started when this primitive is used.
329
330Although the high level interface has been around for a while it still needs a
331bit more testing (read: use cases are needed). In the few cases where we already
332use it application can be different because again it relates to snapshots. This
333because in the past we had to use tricks that also influenced the user interface
334of some macros (which made them less natural as one would expect). So the
335question is: where do we apply it in old mechanisms and where not.
336
337{\em todo: accumulation, interference, where applied, limitations}
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359\stopsectionlevel
360
361\startsectionlevel[title=Hanging]
362
363There are two mechanisms for getting a specific paragraph shape: rectangular
364hanging and arbitrary shapes. Both mechanisms work topdown. The first
365mechanism uses a combination of \type {\hangafter} and \type {\hangindent}, and
366the second one depends on \type {\parshape}. In this section we discuss the
367rectangular one.
368
369\startbuffer[demo5]
370\hangafter 4 \hangindent 4cm \samplefile{tufte} \page
371\hangafter 4 \hangindent 4cm \samplefile{tufte} \page
372\hangafter 4 \hangindent 4cm \samplefile{tufte} \page
373\hangafter 4 \hangindent 4cm \samplefile{tufte} \page
374\stopbuffer
375
376\typebuffer[demo5][option=TEX]
377
378As you can see in \in {figure} [fig:hang], the four cases are driven by the sign
379of the values. If you want to hang into the margin you need to use different
380tricks, like messing with the \type {\leftskip}, \type {\rightskip} or \type
381{\parindent} parameters (which then of course can interfere with other mechanisms
382uses at the same time).
383
384\startplacefigure[title=Hanging indentation,reference=fig:hang]
385\startcombination[nx=2,ny=2]
386 {\typesetbuffer[demo5][page=1,width=.4\textwidth,frame=on]} {\type{\hangafter 4 \hangindent 4cm}}
387 {\typesetbuffer[demo5][page=2,width=.4\textwidth,frame=on]} {\type{\hangafter 4 \hangindent 4cm}}
388 {\typesetbuffer[demo5][page=3,width=.4\textwidth,frame=on]} {\type{\hangafter 4 \hangindent 4cm}}
389 {\typesetbuffer[demo5][page=4,width=.4\textwidth,frame=on]} {\type{\hangafter 4 \hangindent 4cm}}
390\stopcombination
391\stopplacefigure
392
393\stopsectionlevel
394
395\startsectionlevel[title=Shapes]
396
397In \CONTEXT\ we dont use \type {\parshape} a lot. It is used in for instance
398side floats but even there not in all cases. Its more meant for special
399applications. This means that in \MKII\ and \MKIV\ we dont have some high level
400interface. However, when \METAFUN\ got upgraded to \LUAMETAFUN, and the manual
401also needed an update, one of the examples in that manual that used shapes also
402got done differently (read: nicer). And that triggered the arrival of a new low
403level shape mechanism.
404
405One important property of the \type {\parshape} mechanism is that it works per
406paragraph. You define a shape in terms of a left margin and width of a line. The
407shape has a fixed number of such pairs and when there is more content, the last
408one is used for the rest of the lines. When the paragraph is finished, the shape
409is forgotten. \footnote {Not discussed here is a variant that might end up in
410\LUAMETATEX\ that works with the progression, i.e.\ takes the height of the
411content so far into account. This is somewhat tricky because for that to work
412vertical skips need to be frozen, which is no real big deal but has to be done
413careful in the code.}
414
415The high level interface is a follow up on the example in the \METAFUN\ manual and
416uses shapes that carry over to the next paragraph. In addition we can cycle over
417a shape. In this interface shapes are defined using keyword. Here are some
418examples:
419
420\starttyping[option=TEX]
421\startparagraphshape[test]
422 left 1mm right 1mm
423 left 5mm right 5mm
424\stopparagraphshape
425\stoptyping
426
427This shape has only two entries so the first line will have a 1mm margin while
428later lines will get 5mm margins. This translates into a \type {\parshape} like:
429
430\starttyping[option=TEX]
431\parshape 2
432 1mm \dimexpr\hsize1mm\relax
433 5mm \dimexpr\hsize5mm\relax
434\stoptyping
435
436Watch the number \type {2}: it tells how many specification lines follow. As you
437see, we need to calculate the width.
438
439\starttyping[option=TEX]
440\startparagraphshape[test]
441 left 1mm right 1mm
442 left 5mm right 5mm
443 repeat
444\stopparagraphshape
445\stoptyping
446
447This variant will alternate between 1mm and 5mm margins. The repeating feature is
448translated as follows. Maybe at some point I will introduce a few more options.
449
450\starttyping[option=TEX]
451\parshape 2 options 1
452 1mm \dimexpr\hsize1mm\relax
453 5mm \dimexpr\hsize5mm\relax
454\stoptyping
455
456A shape can have some repetition, and we can save keystrokes by copying the last
457entry. The resulting \type {\parshape} becomes rather long.
458
459\starttyping[option=TEX]
460\startparagraphshape[test]
461 left 1mm right 1mm
462 left 2mm right 2mm
463 left 3mm right 3mm
464 copy 8
465 left 4mm right 4mm
466 left 5mm right 5mm
467 left 5mm hsize 10cm
468\stopparagraphshape
469\stoptyping
470
471Also watch the \type {hsize} keyword: we dont calculate the hsize from the \type
472{left} and \type {right} values but explicitly set it.
473
474\starttyping[option=TEX]
475\startparagraphshape[test]
476 left 1mm right 1mm
477 right 3mm
478 left 5mm right 5mm
479 repeat
480\stopparagraphshape
481\stoptyping
482
483When a \type {right} keywords comes first the \type {left} is assumed to be zero.
484In the examples that follow we will use a couple of definitions:
485
486\startbuffer[setup0]
487\startparagraphshape[test]
488 both 1mm both 2mm both 3mm both 4mm both 5mm both 6mm
489 both 7mm both 6mm both 5mm both 4mm both 3mm both 2mm
490\stopparagraphshape
491\stopbuffer
492
493\startbuffer[setup0repeat]
494\startparagraphshape[testrepeat]
495 both 1mm both 2mm both 3mm both 4mm both 5mm both 6mm
496 both 7mm both 6mm both 5mm both 4mm both 3mm both 2mm
497 repeat
498\stopparagraphshape
499\stopbuffer
500
501\typebuffer[setup0,setup0repeat][option=TEX]
502
503The last one could also be defines as:
504
505\starttyping[option=TEX]
506\startparagraphshape[testrepeat]
507 \rawparagraphshape{test} repeat
508\stopparagraphshape
509\stoptyping
510
511In the previous code we already introduced the \type {repeat} option. This will
512make the shape repeat at the engine level when the shape runs out of specified
513lines. In the application of a shape definition we can specify a \type {method}
514to be used and that determine if the next paragraph will start where we left off
515and discard afterwards (\type {shift}) or that we move the discarded lines up
516front so that we never run out of lines (\type {cycle}). It sounds complicated
517but just keep in mind that \type {repeat} is part of the \type {\parshape} and
518act within a paragraph while \type {shift} and \type {cycle} are applied when a
519new paragraph is started.
520
521\startbuffer[demo1]
522\startshapedparagraph[list=test]
523 \dorecurse{8}{\showparagraphshape\samplefile{tufte} \par}
524\stopshapedparagraph
525\stopbuffer
526
527\startbuffer[demo1repeat]
528\startshapedparagraph[list=testrepeat]
529 \dorecurse{8}{\showparagraphshape\samplefile{tufte} \par}
530\stopshapedparagraph
531\stopbuffer
532
533In \in {figure} [fig:shape:discard] you see the following applied:
534
535\typebuffer[demo1,demo1repeat][option=TEX]
536
537\startplacefigure[title=Discarded shaping,reference=fig:shape:discard]
538\startcombination[nx=2,ny=2]
539 {\typesetbuffer[setup0,demo1] [page=1,width=.4\textwidth,frame=on]} {discard, finite shape, page 1}
540 {\typesetbuffer[setup0,demo1] [page=2,width=.4\textwidth,frame=on]} {discard, finite shape, page 2}
541 {\typesetbuffer[setup0,demo1repeat][page=1,width=.4\textwidth,frame=on]} {discard, repeat in shape, page 1}
542 {\typesetbuffer[setup0,demo1repeat][page=2,width=.4\textwidth,frame=on]} {discard, repeat in shape, page 2}
543\stopcombination
544\stopplacefigure
545
546In \in {figure} [fig:shape:shift] we use this instead:
547
548\startbuffer[demo2]
549\startshapedparagraph[list=test,method=shift]
550 \dorecurse{8}{\showparagraphshape\samplefile{tufte} \par}
551\stopshapedparagraph
552\stopbuffer
553
554\startbuffer[demo2shift]
555\startshapedparagraph[list=testrepeat,method=shift]
556 \dorecurse{8}{\showparagraphshape\samplefile{tufte} \par}
557\stopshapedparagraph
558\stopbuffer
559
560\typebuffer[demo2,demo2repeat][option=TEX]
561
562\startplacefigure[title=Shifted shaping,reference=fig:shape:shift]
563\startcombination[nx=2,ny=2]
564 {\typesetbuffer[setup0,demo2][page=1,width=.4\textwidth,frame=on]} {shift, finite shape, page 1}
565 {\typesetbuffer[setup0,demo2][page=2,width=.4\textwidth,frame=on]} {shift, finite shape, page 2}
566 {\typesetbuffer[setup0repeat,demo2shift][page=1,width=.4\textwidth,frame=on]} {shift, repeat in shape, page 1}
567 {\typesetbuffer[setup0repeat,demo2shift][page=2,width=.4\textwidth,frame=on]} {shift, repeat in shape, page 2}
568\stopcombination
569\stopplacefigure
570
571Finally, in \in {figure} [fig:shape:cycle] we use:
572
573\startbuffer[demo3]
574\startshapedparagraph[list=test,method=cycle]
575 \dorecurse{8}{\showparagraphshape\samplefile{tufte} \par}
576\stopshapedparagraph
577\stopbuffer
578
579\startbuffer[demo3cycle]
580\startshapedparagraph[list=testrepeat,method=cycle]
581 \dorecurse{8}{\showparagraphshape\samplefile{tufte} \par}
582\stopshapedparagraph
583\stopbuffer
584
585\typebuffer[demo3,demo3repeat][option=TEX]
586
587\startplacefigure[title=Cycled shaping,reference=fig:shape:cycle]
588\startcombination[nx=2,ny=2]
589 {\typesetbuffer[setup0,demo3][page=1,width=.4\textwidth,frame=on]} {cycle, finite shape, page 1}
590 {\typesetbuffer[setup0,demo3][page=2,width=.4\textwidth,frame=on]} {cycle, finite shape, page 2}
591 {\typesetbuffer[setup0repeat,demo3cycle][page=1,width=.4\textwidth,frame=on]} {cycle, repeat in shape, page 1}
592 {\typesetbuffer[setup0repeat,demo3cycle][page=2,width=.4\textwidth,frame=on]} {cycle, repeat in shape, page 2}
593\stopcombination
594\stopplacefigure
595
596These examples are probably too small to see the details but you can run them
597yourself or zoom in on the details. In the margin we show the values used. Here
598is a simple example of (non) poetry. There are other environments that can be
599used instead but this makes a good example anyway.
600
601\startbuffer
602\startparagraphshape[test]
603 left 0em right 0em
604 left 1em right 0em
605 repeat
606\stopparagraphshape
607
608\startshapedparagraph[list=test,method=cycle]
609 verse line 1.1\crlf verse line 2.1\crlf
610 verse line 3.1\crlf verse line 4.1\par
611 verse line 1.2\crlf verse line 2.2\crlf
612 verse line 3.2\crlf verse line 4.2\crlf
613 verse line 5.2\crlf verse line 6.2\par
614\stopshapedparagraph
615\stopbuffer
616
617\typebuffer[option=TEX]
618
619\start \getbuffer \stop
620
621Because the idea for this feature originates in \METAFUN, we will now kick in
622some \METAPOST. The following code creates a shape for a circle. We use a
6232mm offset here:
624
625\startbuffer
626\startuseMPgraphic{circle}
627 path p ; p := fullcircle scaled TextWidth ;
628 build_parshape(p,
629 2mm, 0, 0,
630 LineHeight, StrutHeight, StrutDepth, StrutHeight
631 ) ;
632\stopuseMPgraphic
633\stopbuffer
634
635\typebuffer[option=TEX]
636
637\start \getbuffer \stop
638
639We plug this into the already described macros:
640
641\startbuffer
642\startshapedparagraph[mp=circle]
643 \setupalign[verytolerant,stretch,last]
644 \samplefile{tufte}
645 \samplefile{tufte}
646\stopshapedparagraph
647\stopbuffer
648
649\typebuffer[option=TEX]
650
651And get ourself a circular shape. Watch out, at this moment the shape environment
652does not add grouping so when as in this case you change the alignment it can
653influence the document.
654
655\start \getbuffer \stop
656
657\startbuffer[framed]
658\framed[align=normal,width=\textwidth,offset=2mm,strut=no]\bgroup
659 \getbuffer
660\egroup
661\stopbuffer
662
663Assuming that the shape definition above is in a buffer we can do this:
664
665\typebuffer[option=TEX]
666
667The result is shown in \in {figure} [fig:shape:circle]. Because all action
668happens in the framed environment, we can also use this definition:
669
670\starttyping[option=TEX]
671\startuseMPgraphic{circle}
672 path p ; p := fullcircle scaled \the\dimexpr\framedwidth\framedoffset2\relax ;
673 build_parshape(p,
674 \framedoffset, 0, 0,
675 LineHeight, StrutHeight, StrutDepth, StrutHeight
676 ) ;
677 draw p ;
678\stopuseMPgraphic
679\stoptyping
680
681\startplacefigure[title=A framed circular shape,reference=fig:shape:circle]
682 \getbuffer[framed]
683\stopplacefigure
684
685A mechanism like this is often never completely automatic in the sense that you
686need to keep an eye on the results. Depending on user demands more features can
687be added. With weird shapes you might want to set up the alignment to be \type
688{tolerant} and have some \type {stretch}.
689
690The interface described in the \METAFUN\ manual is pretty old, the time stamp of
691the original code is mid 2000, but the principles didnt change. The examples in
692\type {metaimptxt.mkxl} can now be written as:
693
694\startuseMPgraphic{test 1}
695 begingroup ;
696 save p ; path p ; p := fullcircle scaled 6cm ;
697 lmt_parshape [
698 path = p,
699 offset = BodyFontSize2,
700 dx = 0,
701 dy = 0,
702 lineheight = LineHeight,
703 strutheight = StrutHeight,
704 strutdepth = StrutDepth,
705 topskip = StrutHeight,
706 ] ;
707 draw p withpen pencircle scaled 1pt ;
708 endgroup ;
709\stopuseMPgraphic
710
711\startuseMPgraphic{test 2}
712 begingroup ;
713 save p ; path p ; p := fullsquare rotated 45 scaled 5cm ;
714 lmt_parshape [
715 path = p,
716 offset = BodyFontSize2,
717 trace = true,
718 ] ;
719 draw p withpen pencircle scaled 1pt ;
720 endgroup ;
721\stopuseMPgraphic
722
723\startuseMPgraphic{test 3}
724 begingroup ;
725 save w, h, p ; path p ; w := h := 6cm ;
726 p := (.5w,h) -- ( 0, h) -- (0,0) -- (w,0) &
727 ( w,0) .. (.75w,.5h) .. (w,h) & (w,h) -- cycle ;
728 lmt_parshape [
729 path = p,
730 offset = BodyFontSize2,
731 ] ;
732 draw p withpen pencircle scaled 1pt ;
733 endgroup ;
734\stopuseMPgraphic
735
736\startuseMPgraphic{test 4}
737 begingroup ;
738 save d, p, q ; path p, q ; d := BodyFontSize2;
739 vardef shape(expr w, h, o) =
740 (o,o) -- (wo,o) & (wo,o) .. (.75wo,.5h) ..
741 (w-2o,ho) & (w-2o,ho) -- (o,ho) -- cycle
742 enddef ;
743 p := shape(6cm, 6cm, d) ; q := shape(6cm, 6cm, 0) ;
744 lmt_parshape [
745 path = p,
746 offsetpath = q,
747 dx = d,
748 dy = d,
749 trace = true,
750 ] ;
751 draw q withpen pencircle scaled 1pt ;
752 endgroup ;
753\stopuseMPgraphic
754
755\defineoverlay[test 1][\useMPgraphic{test 1}]
756\defineoverlay[test 2][\useMPgraphic{test 2}]
757\defineoverlay[test 3][\useMPgraphic{test 3}]
758\defineoverlay[test 4][\useMPgraphic{test 4}]
759
760\startbuffer
761 \startshapetext[test 1,test 2,test 3,test 4]
762 \setupalign[verytolerant,stretch,normal]
763 \samplefile{douglas}
764 \stopshapetext
765 \startcombination[2*2]
766 {\framed[offset=overlay,frame=off,background=test 1]{\getshapetext}}
767 {test 1}
768 {\framed[offset=overlay,frame=off,background=test 2]{\getshapetext}}
769 {test 2}
770 {\framed[offset=overlay,frame=off,background=test 3]{\getshapetext}}
771 {test 3}
772 {\framed[offset=overlay,frame=off,background=test 4]{\getshapetext}}
773 {test 4}
774 \stopcombination
775\stopbuffer
776
777\typebuffer[option=TEX]
778
779In \in {figure} [fig:shapes:chain] we see the result. Watch how for two shapes
780we have enabled tracing. Of course you need to tweak till all fits well but were
781talking of special situations anyway.
782
783\startplacefigure[Title=Multiple shapes,reference=fig:shapes:chain]
784 \getbuffer
785\stopplacefigure
786
787Here is a bit more extreme example. Again we use a circle:
788
789\startbuffer
790\startuseMPgraphic{circle}
791 lmt_parshape [
792 path = fullcircle scaled 136mm,
793 offset = 2mm,
794 bottomskip = 1.5LineHeight,
795 ] ;
796\stopuseMPgraphic
797\stopbuffer
798
799\typebuffer[option=TEX]
800
801But we output a longer text:
802
803\startbuffer
804\startshapedparagraph[mp=circle,repeat=yes,method=cycle]
805 \setupalign[verytolerant,stretch,last]\dontcomplain
806 {\darkred \samplefile{tufte}}\par
807 {\darkgreen \samplefile{tufte}}\par
808 {\darkblue \samplefile{tufte}}\par
809 {\darkcyan \samplefile{tufte}}\par
810 {\darkmagenta \samplefile{tufte}}\par
811\stopshapedparagraph
812\stopbuffer
813
814\typebuffer[option=TEX]
815
816We get a multipage shape:
817
818\start \getbuffer \stop
819
820Compare this with:
821
822\startbuffer
823\startshapedparagraph[mp=circle,repeat=yes,method=cycle]
824 \setupalign[verytolerant,stretch,last]\dontcomplain
825 {\darkred \samplefile{tufte}}
826 {\darkgreen \samplefile{tufte}}
827 {\darkblue \samplefile{tufte}}
828 {\darkcyan \samplefile{tufte}}
829 {\darkmagenta \samplefile{tufte}}
830\stopshapedparagraph
831\stopbuffer
832
833\typebuffer[option=TEX]
834
835Which gives:
836
837\start \getbuffer \stop
838
839Here the \type {bottomskip} takes care of subtle rounding issues as well as
840discarding the last line in the shape so that we get nicer continuation. There is
841no full automated solution for all you can come up with.
842
843Mixing a \METAPOST\ specification into a regular one is also possible. The next
844example demonstrates this as well as the option to remove some lines from a
845specification:
846
847\starttyping[option=TEX]
848\startparagraphshape[test]
849 left 0em right 0em
850 left 1em right 0em
851 metapost {circle}
852 delete 3
853 metapost {circle,circle,circle}
854 delete 7
855 metapost {circle}
856 repeat
857\stopparagraphshape
858\stoptyping
859
860You can combine a shape with narrowing a paragraph. Watch the \type {absolute}
861keyword in the next code. The result is shown in \in {figure} [fig:shape:skips].
862
863\startbuffer[demo4]
864\startuseMPgraphic{circle}
865 lmt_parshape [
866 path = fullcircle scaled TextWidth,
867 bottomskip = 1.5LineHeight,
868 ] ;
869\stopuseMPgraphic
870
871\startparagraphshape[test1]
872 metapost {circle} repeat
873\stopparagraphshape
874
875\startparagraphshape[test2]
876 absolute left metapost {circle} repeat
877\stopparagraphshape
878
879\startparagraphshape[test3]
880 absolute right metapost {circle} repeat
881\stopparagraphshape
882
883\startparagraphshape[test4]
884 absolute both metapost {circle} repeat
885\stopparagraphshape
886
887\showframe
888
889\startnarrower[4*left,2*right]
890 \startshapedparagraph[list=test1,repeat=yes,method=repeat]
891 \setupalign[verytolerant,stretch,last]\dontcomplain
892 \dorecurse{3}{\samplefile{thuan}}
893 \stopshapedparagraph
894 \page
895 \startshapedparagraph[list=test2,repeat=yes,method=repeat]
896 \setupalign[verytolerant,stretch,last]\dontcomplain
897 \dorecurse{3}{\samplefile{thuan}}
898 \stopshapedparagraph
899 \page
900 \startshapedparagraph[list=test3,repeat=yes,method=repeat]
901 \setupalign[verytolerant,stretch,last]\dontcomplain
902 \dorecurse{3}{\samplefile{thuan}}
903 \stopshapedparagraph
904 \page
905 \startshapedparagraph[list=test4,repeat=yes,method=repeat]
906 \setupalign[verytolerant,stretch,last]\dontcomplain
907 \dorecurse{3}{\samplefile{thuan}}
908 \stopshapedparagraph
909\stopnarrower
910\stopbuffer
911
912\typebuffer[demo4][option=TEX]
913
914\startplacefigure[title=Skip compensation,reference=fig:shape:skips]
915\startcombination[nx=2,ny=2]
916 {\typesetbuffer[demo4][page=1,width=.4\textwidth,frame=on]} {test 1}
917 {\typesetbuffer[demo4][page=2,width=.4\textwidth,frame=on]} {test 2, left}
918 {\typesetbuffer[demo4][page=3,width=.4\textwidth,frame=on]} {test 3, right}
919 {\typesetbuffer[demo4][page=4,width=.4\textwidth,frame=on]} {test 4, both}
920\stopcombination
921\stopplacefigure
922
923The shape mechanism has a few more tricks but these are really meant for usage
924in specific situations, where one knows what one deals with. The following
925examples are visualized in \in {figure} [fig:flow].
926
927\startbuffer[jano]
928\useMPlibrary[dum]
929\usemodule[articlebasics]
930
931\startbuffer
932 \externalfigure[dummy][width=6cm]
933\stopbuffer
934
935\startshapedparagraph[text=\getbuffer]
936 \dorecurse{3}{\samplefile{ward}\par}
937\stopshapedparagraph
938
939\page
940
941\startshapedparagraph[text=\getbuffer,distance=1em]
942 \dorecurse{3}{\samplefile{ward}\par}
943\stopshapedparagraph
944
945\page
946
947\startshapedparagraph[text=\getbuffer,distance=1em,
948 hoffset=2em]
949 \dorecurse{3}{\samplefile{ward}\par}
950\stopshapedparagraph
951
952\page
953
954\startshapedparagraph[text=\getbuffer,distance=1em,
955 voffset=2ex,hoffset=2em]
956 \dorecurse{3}{\samplefile{ward}\par}
957\stopshapedparagraph
958
959\page
960
961\startshapedparagraph[text=\getbuffer,distance=1em,
962 voffset=2ex,hoffset=2em,lines=1]
963 \dorecurse{3}{\samplefile{ward}\par}
964\stopshapedparagraph
965
966\page
967
968\startshapedparagraph[width=4cm,lines=4]
969 \dorecurse{3}{\samplefile{ward}\par}
970\stopshapedparagraph
971\stopbuffer
972
973\typebuffer[jano]
974
975\startplacefigure[title={Flow around something},reference=fig:flow]
976 \startcombination[nx=3,ny=2]
977 {\typesetbuffer[jano][page=1,frame=on,width=\measure{combination}]}{}
978 {\typesetbuffer[jano][page=2,frame=on,width=\measure{combination}]}{}
979 {\typesetbuffer[jano][page=3,frame=on,width=\measure{combination}]}{}
980 {\typesetbuffer[jano][page=4,frame=on,width=\measure{combination}]}{}
981 {\typesetbuffer[jano][page=5,frame=on,width=\measure{combination}]}{}
982 {\typesetbuffer[jano][page=6,frame=on,width=\measure{combination}]}{}
983 \stopcombination
984\stopplacefigure
985
986\stopsectionlevel
987
988\startsectionlevel[title=Modes]
989
990
991
992
993
994
995
996
997{\em todo: some of the side effects of so called modes}
998
999\stopsectionlevel
1000
1001\startsectionlevel[title=Leaders]
1002
1003Leaders are a basic feature that users probably never run into directly. They
1004repeat content till it fits the specified width which can be stretched out. The
1005content is typeset once and it is the backend that does the real work of
1006repetition.
1007
1008\startbuffer
1009\strut\leaders \hbox{!}\hfill\strut
1010\strut\xleaders\hbox{!}\hfill\strut
1011\strut\cleaders\hbox{!}\hfill\strut
1012\strut\gleaders\hbox{!}\hfill\strut
1013\stopbuffer
1014
1015\typebuffer
1016
1017Here \type {\leaders} starts at the left edge and are repeats the box as long as
1018it fits, \type {\xleaders} spreads till the edges and \type {\cleaders} centers
1019the lot. The \type {\gleaders} primitive (which is not in orginal \TEX) takes the
1020outer box as reference and further behaves like \type {\cleaders}.
1021
1022\startlines \showmakeup[line] \getbuffer \stoplines
1023
1024The leader primitives take box or rule but in \LUAMETATEX\ a glyph can also be
1025specified, which saves wrapping in a box.
1026
1027\startbuffer
1028\ruledvbox \bgroup \hsize 10cm
1029 \strut\cleaders\hbox{!}\hfill\strut
1030\egroup
1031
1032\ruledvbox \bgroup \hsize 10cm
1033 \strut\cleaders\hrule\hfill\strut
1034\egroup
1035
1036\ruledvbox \bgroup \hsize 10cm
1037 \strut\cleaders\glyph!\hfill\strut
1038\egroup
1039\stopbuffer
1040
1041\typebuffer
1042
1043\getbuffer
1044
1045The \LUAMETATEX\ engine also introduced \type {\uleaders}
1046
1047\definecolor[tred] [r=.6,a=1,t=.5]
1048\definecolor[tgreen][g=.6,a=1,t=.5]
1049\definecolor[tblue] [b=.6,a=1,t=.5]
1050
1051\startbuffer[one]
1052 x xx xxx xxxx
1053 \ruledhbox{L\hss R}\space
1054 x xx xxx xxxx
1055\stopbuffer
1056
1057\startbuffer[two]
1058 x xx xxx xxxx
1059 \uleaders\backgroundhbox[gray]{L\hss R}\hskip\zeropoint plus 100pt\relax\space
1060 x xx xxx xxxx
1061\stopbuffer
1062
1063\startbuffer[three]
1064 x xx xxx xxxx
1065 \uleaders\ruledhbox{L\hss R}\hskip\zeropoint plus 100pt\relax\space
1066 x xx xxx xxxx
1067\stopbuffer
1068
1069We show three boxes, a regular one first (red):
1070
1071\typebuffer[one]
1072
1073The second one (blue) is also a box but one that stretches upto 100pt and is in a
1074later stage, when the paragraph has been built, is repackaged to the effective
1075width. The third example (green) leaves out the background.
1076
1077\startlinecorrection
1078\startoverlay
1079 {\vbox{\color[tgreen]{\small\dorecurse {20} {\getbuffer[three]}}}}
1080 {\vbox{\color[tblue] {\small\dorecurse {20} {\getbuffer [two]}}}}
1081 {\vbox{\color[tred] {\small\dorecurse {20} {\getbuffer [one]}}}}
1082\stopoverlay
1083\stoplinecorrection
1084
1085In \CONTEXT\ we have wrapped this feature in the adaptive box mechanism, so here
1086a few a few examples:
1087
1088\setupexternalfigures[location={default,local,global}]
1089
1090\startbuffer
1091\startsetups adaptive:test:a
1092 \setbox\usedadaptivebox\vbox to \usedadaptivetotal \bgroup
1093 \externalfigure
1094 [cow.pdf]
1095 [width=\framedmaxwidth,
1096 frame=on,
1097 height=\usedadaptivetotal]
1098 \egroup
1099\stopsetups
1100
1101\startsetups adaptive:test:b
1102 \setbox\usedadaptivebox\vbox to \usedadaptivetotal \bgroup
1103 \externalfigure
1104 [cow.pdf]
1105 [width=\usedadaptivewidth,
1106 frame=on,
1107 height=\usedadaptivetotal]
1108 \egroup
1109\stopsetups
1110\stopbuffer
1111
1112\typebuffer \getbuffer
1113
1114We use this as follows (see \in {figure} [fig:adaptive] for the result):
1115
1116\startbuffer
1117\framed[height=18cm,align=middle,adaptive=yes,top=,bottom=] {
1118 \begstrut \samplefile{tufte} \endstrut
1119 \par
1120 \adaptivevbox
1121 [strut=yes,setups=adaptive:test:a]
1122 {\showstruts\strut\hsize5cm\hss}
1123 \par
1124 \adaptivevbox
1125 [strut=yes,setups=adaptive:test:b]
1126 {\showstruts\strut\hsize5cm\hss}
1127 \par
1128 \begstrut \samplefile{tufte} \endstrut
1129}
1130\stopbuffer
1131
1132\typebuffer
1133
1134\startplacefigure[reference=fig:adaptive]
1135 \getbuffer
1136\stopplacefigure
1137
1138Here is one that you can test yourself:
1139
1140\starttyping
1141\startsetups adaptive:test
1142 \setbox\usedadaptivebox\vbox to \usedadaptivetotal \bgroup
1143 \externalfigure
1144 [cow.pdf]
1145 [width=\usedadaptivewidth,
1146 height=\usedadaptivetotal]
1147 \egroup
1148\stopsetups
1149
1150\ruledvbox to \textheight {
1151 \par \begstrut \samplefile{tufte} \endstrut \par
1152 \adaptivevbox[strut=yes,setups=adaptive:test]{\hsize\textwidth\hss}
1153 \par \begstrut \samplefile{tufte} \endstrut
1154}
1155\stoptyping
1156
1157The next example comes from the test suite (where it runs over many pages in
1158order to illustrate the idea):
1159
1160\startbuffer
1161\startMPdefinitions
1162 def TickTock =
1163 interim linecap := squared;
1164 save p ; path p ;
1165 p := fullsquare xysized(AdaptiveWidth,.9(AdaptiveHeightAdaptiveDepth)) ;
1166 fill p withcolor AdaptiveColor ;
1167 draw bottomboundary (p enlarged (AdaptiveThickness) )
1168 withdashes (3AdaptiveThickness)
1169 withpen pencircle scaled AdaptiveThickness
1170 withcolor white ;
1171 enddef ;
1172\stopMPdefinitions
1173
1174\startsetups adaptive:test
1175 \setbox\usedadaptivebox\hbox
1176 to \usedadaptivewidth
1177 yoffset .9\usedadaptivedepth
1178 \bgroup
1179 \hss
1180 \startMPcode
1181 TickTock ;
1182 \stopMPcode
1183 \hss
1184 \egroup
1185\stopsetups
1186
1187\definecolor[adaptive:tick][.25(blue,green)]
1188\definecolor[adaptive:tock][.75(blue,green)]
1189
1190\defineadaptive
1191 [tick]
1192 [setups=adaptive:test,
1193 color=adaptive:tick,
1194 foregroundcolor=white,
1195 foregroundstyle=\infofont,
1196 strut=yes]
1197
1198\defineadaptive
1199 [tock]
1200 [tick]
1201 [color=adaptive:tock]
1202
1203\dostepwiserecurse{8}{12}{1}{
1204 \dostepwiserecurse{5}{15}{1}{
1205 this#1.##1 is#1.##1 test#1.##1
1206 \ifodd##1\relax
1207 \adaptivebox[tick]{\hss tick #1.##1\hss}
1208 \else
1209 \adaptivebox[tock]{\hss tock #1.##1\hss}
1210 \fi
1211 }
1212}
1213\stopbuffer
1214
1215\typebuffer \getbuffer
1216
1217In the next example the graphics adapt to the available space:
1218
1219\startbuffer
1220\startsetups adaptive:test
1221 \setbox\usedadaptivebox\hbox
1222 to \usedadaptivewidth
1223 yoffset \usedadaptivedepth
1224 \bgroup
1225 \externalfigure
1226 [cow.pdf]
1227 [width=\usedadaptivewidth,
1228 height=\dimexpr\usedadaptivetotal\relax]
1229 \egroup
1230\stopsetups
1231
1232\dostepwiserecurse{1}{50}{1}{
1233 this#1 is#1 test#1
1234 {\adaptivebox[strut=yes,setups=adaptive:test]{}}
1235}
1236\stopbuffer
1237
1238\typebuffer \getbuffer
1239
1240\stopsectionlevel
1241
1242\startsectionlevel[title=Prevdepth]
1243
1244The depth of a box is normally positive but rules can have a negative depth in
1245order to get a rule above the baseline. When \TEX\ was written the assumption was
1246that a negative depth of more than 1000 point made no sense at all. The last
1247depth on a vertical list is registered in the \type {\prevdepth} variable. This
1248is basically a reference into the current list. In order to illustrate some
1249interesting side effects of setting this \type {\prevdepth} and especially when
1250we set it to $\tf 1000pt$. In order to illustrate this this special value can be set
1251to a different value in \LUAMETATEX. However, as dealing with the property is
1252somewhat special in the engine you should not set it unless you know that the
1253macro package is ware of it.
1254
1255\startbuffer
1256line 1\par line 2 \par \nointerlineskip line 3 \par
1257\stopbuffer
1258
1259\typebuffer
1260
1261Assuming that we havent set any inter paragraph spacing this gives:
1262
1263\startlinecorrection
1264\ruledvbox{\setupwhitespace[none]\showmakeup[line]\getbuffer}
1265\stoplinecorrection
1266
1267Here \type {\nointerlineskip} is (normally) defined as:
1268
1269\starttyping
1270\prevdepth1000pt
1271\stoptyping
1272
1273although in \CONTEXT\ we use \type {\ignoredepthcriterium} instead of the hard
1274coded dimension. We now give a more extensive example:
1275
1276\startbuffer[definition1]
1277\def\PrevTest#1
1278 {\setbox0\ruledhbox{\strut$\tf#1$}
1279 \dp0=#1
1280 \vbox\bgroup\hsize4em
1281 FIRST\par
1282 \unhbox0\par
1283 LAST\par
1284 \egroup}
1285\stopbuffer
1286
1287\startbuffer[definition2]
1288\def\PrevTest#1
1289 {\setbox0\ruledhbox{\strut$\tf#1$}
1290 \dp0=#1
1291 \vbox\bgroup
1292 \ruledhbox{FIRST}\par
1293 \box0\par
1294 \ruledhbox{LAST}\par
1295 \egroup}
1296\stopbuffer
1297
1298\startbuffer[example]
1299\ruledhbox \bgroup
1300 \PrevTest{10.0pt}\quad
1301 \PrevTest{20.0pt}\quad
1302 \PrevTest{49.9pt}\quad
1303 \PrevTest{50.0pt}\quad
1304 \PrevTest{50.1pt}\quad
1305 \PrevTest{60.0pt}\quad
1306 \PrevTest{80.0pt}
1307\egroup
1308\stopbuffer
1309
1310\typebuffer[example][option=TEX]
1311
1312In this example we set \type {\ignoredepthcriterium} to $\tf 50.0pt$ instead of the
1313normal $\tf 1000pt$. The helper is defined as:
1314
1315\typebuffer[definition1][option=TEX]
1316
1317or
1318
1319\typebuffer[definition2][option=TEX]
1320
1321The result is shown in \in {figures} [fig:prevdepth1] \in {and}
1322[fig:prevdepth2]. The first case is what we normally have in text and we havent
1323set \type {prevdepth} explicitly between lines so \TEX\ will just look at the
1324depth of the lines. In the second case the depth is ignored when less than the
1325criterium which is why, when we set the depth of the box to a negative value we
1326get somewhat interesting skips.
1327
1328\startplacefigure[reference=fig:prevdepth1]
1329 \showmakeup[line]
1330 \ignoredepthcriterium50pt
1331 \setupwhitespace[none]
1332 \getbuffer[definition1,example]
1333\stopplacefigure
1334
1335\startplacefigure[reference=fig:prevdepth2]
1336 \showmakeup[line]
1337 \ignoredepthcriterium50pt
1338 \setupwhitespace[none]
1339 \getbuffer[definition2,example]
1340 \blank[5*line]
1341\stopplacefigure
1342
1343Im sure one can use this effect otherwise than intended but I doubt is any user
1344is willing to do this but the fact that we can lower the criterium makes for nice
1345experiments. Just for the record, in \in {figure} [fig:prevdepth3] you see what
1346we get with positive values:
1347
1348\startbuffer[example]
1349\ruledhbox \bgroup
1350 \PrevTest{10.0pt}\quad
1351 \PrevTest{20.0pt}\quad
1352 \PrevTest{49.9pt}\quad
1353 \PrevTest{50.0pt}\quad
1354 \PrevTest{50.1pt}\quad
1355 \PrevTest{60.0pt}\quad
1356 \PrevTest{80.0pt}
1357\egroup
1358\stopbuffer
1359
1360\typebuffer[example][option=TEX]
1361
1362\startplacefigure[reference=fig:prevdepth3]
1363 \showmakeup[line]
1364 \ignoredepthcriterium50pt
1365 \setupwhitespace[none]
1366 \getbuffer[definition2,example]
1367\stopplacefigure
1368
1369Watch the interline skip kicking in when we make the depth larger than in
1370\type {\ignoredepthcriterium} being $\tf 50pt$.
1371
1372\stopsectionlevel
1373
1374\startsectionlevel[title=Normalization]
1375
1376{\em todo: users dont need to bother about this but it might be interesting anyway}
1377
1378\stopsectionlevel
1379
1380\startsectionlevel[title=Dirty tricks]
1381
1382{\em todo: explain example for combining paragraphs}
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396\stopsectionlevel
1397
1398\stopdocument
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512 |