math-spacing.tex /size: 19 Kb    last modification: 2021-10-28 13:50
1% language=us runpath=texruns:manuals/math
2
3\environment math-layout
4
5\startcomponent math-spacing
6
7\startchapter[title=Vertical spacing]
8
9The low level way to input inline math in \TEX\ is
10
11\starttyping
12$ e = mc^2 $
13\stoptyping
14
15while display math can be entered like:
16
17\starttyping
18$$ e = mc^2 $$
19\stoptyping
20
21The inline method is still valid, but for display math the \type {$$} method
22should not be used. This has to do with the fact that we want to control spacing
23in a consistent way. In \CONTEXT\ the vertical spacing model is rather stable
24although in \MKIV\ the implementation is quite different. It has always been a
25challenge to let this mechanism work well with space round display formulas. This
26has to do with the fact that (in the kind of documents that we have to produce)
27interaction with already present spacing is somewhat tricky.
28
29Of course much can be achieved in \TEX\ but in \CONTEXT\ we need to have control
30over the many mechanisms that can interact. Given the way \TEX\ handles space
31around display math there is no real robust solution possible that gives visually
32consistent space in all cases so that is why we basically disable the existing
33spacing model. Disabling is easier in \LUATEX\ and recent versions of \MKIV\ have
34been adapted to that.
35
36In pure \TEX\ what happens is this:
37
38\startbuffer
39$$ x $$
40\stopbuffer
41
42\typebuffer \par \start \showboxes \getbuffer \par \stop
43
44A horizontal box (visualized by the thin rule on its baseline) get added which
45triggers a baselineskip. Then the formula is put below it. We can get rid of that
46box with \type {\noindent}:
47
48\startbuffer
49\noindent $$ x $$
50\stopbuffer
51
52\typebuffer \par \start \showboxes \getbuffer \par \stop
53
54In addition (not shown here) vertical space is added before and after the formula
55and left- and rightskip on the edges. In fact typesetting display math goes like this:
56
57\startitemize[packed]
58    \startitem
59        typeset the formula using display mode and wrap it in a box
60    \stopitem
61    \startitem
62        add an equation number, if possible in the same line, otherwise on a line
63        below
64    \stopitem
65    \startitem
66        in the process center the formula using the available display width and
67        required display indentation
68    \stopitem
69    \startitem
70        add vertical space above and below (depending also in displays being
71        short in relation to the previous line
72    \stopitem
73    \startitem
74        at the same time also add penalties that determine the break across
75        pages
76    \stopitem
77\stopitemize
78
79Apart from the spacing around the formula and the equation number, typesetting is
80not different from:
81
82\starttyping
83\hbox {$ \displaystyle x $}
84\stoptyping
85
86So this is what we will use by default in \CONTEXT\ in order to better control
87spacing as spacing around math is a sensitive issue. Because math itself can have
88a narrow band, for instance a lone $x$, or relative much depth, as with $y$, or
89both depth and height as in $(1,2)$ and $x^2 + y_2$ and because a preceding line
90can have no or little depth and a following line little height, the visual
91appearance can become inconsistent. The default approach is to force consistent
92spacing, but when needed we can implement variants.
93
94Spacing around display math is set up with \type {\setupformulas}:
95
96\starttyping
97  \setupformulas
98    [spacebefore=big,
99     spaceafter=big]
100\stoptyping
101
102When the whitespace is larger that setting wins because as usual the larger
103of blanks or whitespace wins.
104
105% \showdefinition[setupformula]
106% \showdefinition[setupmathematics]
107
108In \in {figures} [whitespace-no], \in {figures} [whitespace-medium] \in {and}
109[whitespace-big] we see how things interact. We show lines with and without
110maximum line height and depth (enforced by struts) alongside.
111
112% no whitespace
113
114\startbuffer[demo-1]
115\disablemode[with-struts]
116\showmakeup
117\setupformulas[spacebefore=none,spaceafter=none]
118\setupwhitespace[none]
119\input math-spacing-001.tex
120\stopbuffer
121
122\startbuffer[demo-2]
123\enablemode[with-struts]
124\showmakeup
125\setupformulas[spacebefore=none,spaceafter=none]
126\setupwhitespace[none]
127\input math-spacing-001.tex
128\stopbuffer
129
130\startbuffer[demo-3]
131\disablemode[with-struts]
132\showmakeup
133\setupformulas[spacebefore=medium,spaceafter=medium]
134\setupwhitespace[none]
135\input math-spacing-001.tex
136\stopbuffer
137
138\startbuffer[demo-4]
139\enablemode[with-struts]
140\showmakeup
141\setupformulas[spacebefore=medium,spaceafter=medium]
142\setupwhitespace[none]
143\input math-spacing-001.tex
144\stopbuffer
145
146\startplacefigure[location=page,reference=whitespace-no,title={No whitespace.}]
147    \startcombination[2*2]
148        {\typesetbuffer[demo-1][height=.45\textheight]} {\tttf natural + none   + ws none}
149        {\typesetbuffer[demo-2][height=.45\textheight]} {\tttf strut   + none   + ws none}
150        {\typesetbuffer[demo-3][height=.45\textheight]} {\tttf natural + medium + ws none}
151        {\typesetbuffer[demo-4][height=.45\textheight]} {\tttf strut   + medium + ws none}
152    \stopcombination
153\stopplacefigure
154
155% whitespace medium same as medium spacing around math
156
157\startbuffer[demo-1]
158\disablemode[with-struts]
159\showmakeup
160\setupformulas[spacebefore=none,spaceafter=none]
161\setupwhitespace[medium]
162\input math-spacing-001.tex
163\stopbuffer
164
165\startbuffer[demo-2]
166\enablemode[with-struts]
167\showmakeup
168\setupformulas[spacebefore=none,spaceafter=none]
169\setupwhitespace[medium]
170\input math-spacing-001.tex
171\stopbuffer
172
173\startbuffer[demo-3]
174\disablemode[with-struts]
175\showmakeup
176\setupformulas[spacebefore=medium,spaceafter=medium]
177\setupwhitespace[medium]
178\input math-spacing-001.tex
179\stopbuffer
180
181\startbuffer[demo-4]
182\enablemode[with-struts]
183\showmakeup
184\setupformulas[spacebefore=medium,spaceafter=medium]
185\setupwhitespace[medium]
186\input math-spacing-001.tex
187\stopbuffer
188
189\startplacefigure[location=page,reference=whitespace-medium,title={Whitespace the same as display spacing.}]
190    \startcombination[2*2]
191        {\typesetbuffer[demo-1][height=.45\textheight]} {\tttf natural + none   + ws medium}
192        {\typesetbuffer[demo-2][height=.45\textheight]} {\tttf strut   + none   + ws medium}
193        {\typesetbuffer[demo-3][height=.45\textheight]} {\tttf natural + medium + ws medium}
194        {\typesetbuffer[demo-4][height=.45\textheight]} {\tttf strut   + medium + ws medium}
195    \stopcombination
196\stopplacefigure
197
198% whitespace big wins from medium spacing around math
199
200\startbuffer[demo-1]
201\disablemode[with-struts]
202\showmakeup
203\setupformulas[spacebefore=none,spaceafter=none]
204\setupwhitespace[big]
205\input math-spacing-001.tex
206\stopbuffer
207
208\startbuffer[demo-2]
209\enablemode[with-struts]
210\showmakeup
211\setupformulas[spacebefore=none,spaceafter=none]
212\setupwhitespace[big]
213\input math-spacing-001.tex
214\stopbuffer
215
216\startbuffer[demo-3]
217\disablemode[with-struts]
218\showmakeup
219\setupformulas[spacebefore=medium,spaceafter=medium]
220\setupwhitespace[big]
221\input math-spacing-001.tex
222\stopbuffer
223
224\startbuffer[demo-4]
225\enablemode[with-struts]
226\showmakeup
227\setupformulas[spacebefore=medium,spaceafter=medium]
228\setupwhitespace[big]
229\input math-spacing-001.tex
230\stopbuffer
231
232\startplacefigure[location=page,reference=whitespace-big,title={Whitespace larger than display spacing.}]
233    \startcombination[2*2]
234        {\typesetbuffer[demo-1][height=.45\textheight]} {\tttf natural + none   + ws big}
235        {\typesetbuffer[demo-2][height=.45\textheight]} {\tttf strut   + none   + ws big}
236        {\typesetbuffer[demo-3][height=.45\textheight]} {\tttf natural + medium + ws big}
237        {\typesetbuffer[demo-4][height=.45\textheight]} {\tttf strut   + medium + ws big}
238    \stopcombination
239\stopplacefigure
240
241Because we want to have control over the placement of the formula number but also
242want to be able to align the formula with the left or right edge of the text
243area, we don't use the native display handler by default. We still have a way to
244force this, but this is only for testing purposes. By default a formula is placed
245centered relative to the current text, including left and right margins.
246
247\startbuffer
248\fakewords{20}{40}
249
250\startitemize
251    \startitem
252        \fakewords{20}{40}
253        \placeformula
254            \startformula
255                \fakeformula
256            \stopformula
257    \stopitem
258    \startitem
259        \fakewords{20}{40}
260    \stopitem
261\stopitemize
262
263\fakewords{20}{40}\epar
264\stopbuffer
265
266\typebuffer
267
268\start \getbuffer \stop
269
270In the next examples we explicitly align formulas to the left (\type
271{flushleft}), center (\type {middle}) and right (\type {flushright}):
272
273\startbuffer[demo]
274\setupformulas[align=flushleft]
275\startformula\fakeformula\stopformula
276\setupformulas[align=middle]
277\startformula\fakeformula\stopformula
278\setupformulas[align=flushright]
279\startformula\fakeformula\stopformula
280\stopbuffer
281
282\typebuffer[demo]
283
284The three cases show up as:
285
286\start \getbuffer[demo] \stop
287
288You can also set a left and|/|or right margin:
289
290\startbuffer[setting]
291\setupformulas
292  [leftmargin=3cm,
293   rightmargin=3cm]
294\stopbuffer
295
296\start \getbuffer[setting] \getbuffer[demo] \stop
297
298With formula numbers these formulas look as follows:
299
300\startbuffer[demo]
301\setupformulas[align=flushleft]
302\placeformula \startformula\fakeformula\stopformula
303\setupformulas[align=middle]
304\placeformula \startformula\fakeformula\stopformula
305\setupformulas[align=flushright]
306\placeformula \startformula\fakeformula\stopformula
307\stopbuffer
308
309\start \getbuffer[demo] \stop
310
311and the same with margins:
312
313\start \getbuffer[setting] \getbuffer[demo] \stop
314
315\page
316
317When the \type {margin} option is set to \type {standard} or \type {yes} the
318current indentation (when set) or left skip is added to the left side.
319
320\startbuffer
321\setupformulas[align=flushleft]
322\startformula \fakeformula \stopformula
323\placeformula \startformula \fakeformula \stopformula
324\stopbuffer
325
326\typebuffer \start \getbuffer \stop
327
328\startbuffer
329\setupformulas[align=flushleft,margin=standard]
330\startformula \fakeformula \stopformula
331\placeformula \startformula \fakeformula \stopformula
332\stopbuffer
333
334\typebuffer \start \getbuffer \stop
335
336The distance between the formula and the number is only applied when the formula
337is left or right aligned.
338
339\startbuffer
340\setupformulas[align=flushright,distance=0pt]
341\startformula \fakeformula \stopformula
342\placeformula \startformula \fakeformula \stopformula
343\stopbuffer
344
345\typebuffer \start \getbuffer \stop
346
347\startbuffer
348\setupformulas[align=flushright,distance=2em]
349\startformula \fakeformula \stopformula
350\placeformula \startformula \fakeformula \stopformula
351\stopbuffer
352
353\typebuffer \start \getbuffer \stop
354
355\stopsection
356
357\startsection[title=Scripts]
358
359Spacing is a trade off because there is no way to predict all usage. Of course a
360font can be very detailed in where italic correction is to be applied and how
361advanced stepwise kerns are used, but not many fonts have extensive information.
362Here are some differences in rendering. In \OPENTYPE\ the super- and subscript of
363an integral are moved right and left half of the italic correction.
364
365\startlinecorrection
366    \startcombination[6*1]
367        {\switchtobodyfont  [modern]\math{F_j = \int\nolimits _a^b}} {Latin Modern}
368        {\switchtobodyfont [pagella]\math{F_j = \int\nolimits _a^b}} {Pagella}
369        {\switchtobodyfont  [dejavu]\math{F_j = \int\nolimits _a^b}} {Dejavu}
370        {\switchtobodyfont [cambria]\math{F_j = \int\nolimits _a^b}} {Cambria}
371        {\switchtobodyfont[lucidaot]\math{F_j = \int\nolimits _a^b}} {Lucida OT}
372        {\switchtobodyfont    [xits]\math{F_j = \int\nolimits _a^b}} {Xits}
373    \stopcombination
374\stoplinecorrection
375
376\stopsection
377
378\startsection[title=Bad fonts]
379
380There might be fonts out there where the italic correction is supposed to be
381added to the width of a glyph. In that case the following trick can be tried:
382
383\starttyping
384\definefontfeature[mathextra][italicwidths=yes] % fix latin modern
385\stoptyping
386
387in which case the following might look better:
388
389\starttyping
390$\left|V\right| = \left|W\right|$
391\stoptyping
392
393Of course better is to fix the font.
394
395\stopsection
396
397\startsection[title=Multiline]
398
399Inline formulas can span lines but display math normally sits on one line unless
400one uses alignment mechanisms. Take this:
401
402\startbuffer[demo]
403\startformula
404    x\dorecurse{30}{ + #1x^{#1x}} = 10
405\stopformula
406\stopbuffer
407
408\typebuffer[demo]
409
410\par \start \setupformula[split=no]  \getbuffer[demo] \stop \par
411
412You can set \type {split} to \type {yes} using \type {\setupformula} and get the
413following:
414
415\par \start \setupformula[split=yes] \getbuffer[demo] \stop \par
416
417Maybe nicer is to also set \type {align} to \type {flushleft}:
418
419\par \start \setupformula[split=yes,align=flushleft] \getbuffer[demo] \stop \par
420
421If you want the binary operators to start the lines you can set this:
422
423\startbuffer[setup]
424\setupmathematics[setups=math:spacing:split]
425\setupformulas[split=yes,align=flushleft]
426\stopbuffer
427
428\typebuffer[setup]
429
430\par \start \getbuffer[setup,demo] \stop \par
431
432You can prevent a split with a large penalty. Here is a test that yuou can run
433to play with this feature:
434
435\starttyping
436\dostepwiserecurse {30} {100} {1} {
437    \hsize \dimexpr 40pt + #1pt \relax
438    \startformula
439        y = a \dorecurse {50} {
440            \penalty 10000 {\bf + ##1b}
441             + ##1c^2
442        }
443    \stopformula
444    \page
445}
446\stoptyping
447
448There is an experimental alignment mechanism available. Watch the following
449examples:
450
451\startbuffer[demo]
452before
453    \startformula
454        z + 3y = \alignhere x
455                 \dorecurse{20}{ + #1x^{#1x}}
456    \stopformula
457inbetween
458    \startformula
459        z + 3y \alignhere = 1
460               \dorecurse{4}{
461                    \dorecurse{#1}{+ #1x^{##1x}}
462                    \ifnum#1<4\breakhere\fi
463               }
464    \stopformula
465after
466\stopbuffer
467
468\typebuffer[demo]
469
470\startbuffer[setup]
471\setupformula
472  [split=no]
473\stopbuffer
474
475\typebuffer[setup] \start \getbuffer[setup,demo] \stop
476
477\startbuffer[setup]
478\setupformula
479  [split=yes,
480   align=flushleft]
481\stopbuffer
482
483\typebuffer[setup] \start \getbuffer[setup,demo] \stop
484
485\startbuffer[setup]
486\setupformula
487  [split=yes,
488   align=flushleft,
489   hang=auto]
490\stopbuffer
491
492\typebuffer[setup] \start \getbuffer[setup,demo] \stop
493
494\startbuffer[setup]
495\setupformula
496  [split=yes,
497   align=flushleft,
498   hang=auto,
499   distance=1em]
500\stopbuffer
501
502\typebuffer[setup] \start \getbuffer[setup,demo] \stop
503
504\startbuffer[setup]
505\setupformula
506  [split=yes,
507   align=flushleft,
508   hang=yes,
509   distance=2em]
510\stopbuffer
511
512\typebuffer[setup] \start \getbuffer[setup,demo] \stop
513
514\startbuffer[setup]
515\setupformula
516  [split=yes,
517   align=flushleft,
518   hang=yes,
519   distance=2em,
520   interlinespace=1.5\lineheight]
521\stopbuffer
522
523\typebuffer[setup] \start \getbuffer[setup,demo] \stop
524
525If you want to split over pages, you can say:
526
527\starttyping
528\setupformula
529  [split=page,
530   align=middle]
531\stoptyping
532
533but that is rather experimental (especially in combination with other
534number placement related options).
535
536\stopsection
537
538\startsection[title=Scripts]
539
540Superscripts and subscripts are typeset in a smaller size than their nucleus. You
541can influence that as follows:
542
543\startbuffer
544\startformula
545x^{2} = x^{\textstyle 2}
546      = x^{\scriptstyle 2}
547      = x^{\scriptscriptstyle 2}
548\stopformula
549\stopbuffer
550
551\typebuffer \getbuffer
552
553You can also use macros instead of a \type {^} and \type {_}, as in:
554
555\startbuffer
556\startformula
557x \superscript   {2} =
558x \superscript   {\textstyle 2} =
559x \superscript   {\scriptstyle 2} =
560x \superscript   {\scriptscriptstyle 2} =
561x \nosuperscript {2}
562\stopformula
563\stopbuffer
564
565\typebuffer \getbuffer
566
567The \type {\nosuperscript} primitive makes sure that we get the same size as the
568nucleus.
569
570\startbuffer
571\startformula
572x \superscript   {2} \subscript   {i} =
573x \nosuperscript {2} \subscript   {i} =
574x \superscript   {2} \nosubscript {i} =
575x \nosuperscript {2} \nosubscript {i}
576\stopformula
577\stopbuffer
578
579\typebuffer \getbuffer
580
581\stopsection
582
583\startsection[title=Text accents]
584
585You can put an accent over a character:
586
587\startbuffer
588$\grave{x} \neq \grave{i}$\quad
589$\ddot {x} \neq \ddot {i}$\quad
590$\bar  {x} \neq \bar  {i}$\quad
591$\acute{x} \neq \acute{i}$\quad
592$\hat  {x} \neq \hat  {i}$\quad
593$\check{x} \neq \check{i}$\quad
594$\breve{x} \neq \breve{i}$\quad
595$\dot  {x} \neq \dot  {i}$\quad
596$\ring {x} \neq \ring {i}$\quad
597$\tilde{x} \neq \tilde{i}$\quad
598$\dddot{x} \neq \dddot{i}$\quad
599\stopbuffer
600
601\typebuffer
602
603This comes out as: \inlinebuffer. For regular text you can better use proper composed
604\UTF\ encoded characters.
605
606\stopsection
607
608\startsection[title=Directions]
609
610Math has its own direction control:
611
612\starttexdefinition unexpanded MathTest #1#2#3
613    \ruledvbox \bgroup
614        \mathdirection#1\relax
615        \textdirection#2\relax
616        \pardirection #3\relax
617        \hsize=30mm
618        \startformula
619            a^2+b^2=c^2
620        \stopformula
621   \egroup
622\stoptexdefinition
623
624\starttexdefinition unexpanded MathShow #1#2#3#4
625    \hbox \bgroup
626        \infofont #1 : m=#2 t=#3 p=#4
627    \egroup
628\stoptexdefinition
629
630\startbuffer
631\startcombination[nx=4,ny=2,distance=1cm]
632    {\MathTest{0}{0}{0}} {\MathShow1{0}{0}{0}}
633    {\MathTest{0}{0}{1}} {\MathShow2{0}{0}{1}}
634    {\MathTest{0}{1}{0}} {\MathShow3{0}{1}{0}}
635    {\MathTest{0}{1}{1}} {\MathShow4{0}{1}{1}}
636    {\MathTest{1}{0}{0}} {\MathShow5{1}{0}{0}}
637    {\MathTest{1}{0}{1}} {\MathShow6{1}{0}{1}}
638    {\MathTest{1}{1}{0}} {\MathShow7{1}{1}{0}}
639    {\MathTest{1}{1}{1}} {\MathShow8{1}{1}{1}}
640\stopcombination
641\stopbuffer
642
643\typebuffer
644
645Normally you will not control directions this way but use the proper parameters
646in layout related setup commands.
647
648\startlinecorrection
649\getbuffer
650\stoplinecorrection
651
652\stopsection
653
654\startsection[title=Surround]
655
656The spacing around inline formulas is consistent with other
657spacing but it can be enlarged. We just show a few examples:
658
659\startbuffer[demo]
660\hsize 20em
661We have
662\dorecurse {8} {%
663    \ifcase#1\or\else and \fi
664    $x+#1$ and $x-#1$ and $x \times #1$
665}
666\removeunwantedspaces .
667\par
668\stopbuffer
669
670\typebuffer[demo]
671
672\blank \start \getbuffer[demo] \stop
673
674\startbuffer[setup]
675\setupmathematics
676  [textdistance=2pt plus 1pt minus 1pt]
677\stopbuffer
678
679\typebuffer[setup]
680
681\blank \start \getbuffer[setup,demo] \stop
682
683\startbuffer[setup]
684\setupmathematics
685  [textdistance=4pt plus 2pt minus 2pt]
686\stopbuffer
687
688\typebuffer[setup]
689
690\blank \start \getbuffer[setup,demo] \stop
691
692\stopsection
693
694\startsection[title=Choices]
695
696The next examples are generated using this macro:
697
698\startbuffer
699\starttexdefinition unexpanded Test#1#2
700
701    \begingroup
702
703    \showmakeup[depth]
704
705    \def\TestA{\dontleavehmode\ruledhbox{\dorecurse{8}{before }}}
706    \def\TestB{\dontleavehmode\ruledhbox{\dorecurse{8}{after }}}
707    \def\TestC{\dorecurse{18}{x+}x}
708
709    \setdisplaymathspacemodel[3]
710    \setupalign[flushleft]  1\space:\space\TestA \par
711    \startformula #2 \TestC \stopformula \par
712    \setupalign[flushleft]  2\space:\space\TestB \par
713
714    \setdisplaymathspacemodel[4]
715
716    \vskip#1\lineheight
717
718    \setupalign[flushright] \TestA\space:\space2 \par
719    \startformula #2 \TestC \stopformula \par
720    \setupalign[flushright] \TestB\space:\space2 \par
721
722    \endgroup
723
724\stoptexdefinition
725\stopbuffer
726
727\typebuffer \getbuffer
728
729It demonstrates the often hard decisions that we have to make with regards to
730spacing. On the one hand we want to be adaptive, on the other hand we want to be
731consistent, for instance in the depth of lines. These examples overlay the two
732variants (which is of course font and style dependent).
733
734\Test{-4.70}{}                      \blank[2*line]
735\Test{-6.00}{\frac{1}{2}}           \blank[2*line]
736\Test{-6.55}{\frac{1}{\frac{1}{2}}}
737
738One side effect of these options is that at some point we need to choose a
739default and then easily forget about the other variants.
740
741\stopsection
742
743\stopchapter
744
745\stopcomponent
746