still-opentypemath.tex /size: 31 Kb    last modification: 2023-12-21 09:43
1% language=us
2
3\environment still-environment
4
5\starttext
6
7\startchapter[title=Opentype math]
8
9\startsection[title=Introduction]
10
11When \TEX\ typesets mathematics it makes some assumptions about the properties of
12fonts and dimensions of glyphs. Due to practical limitations in the traditional
13eight|-|bit fonts, such as the number of available characters in a font and a
14limited number of heights and depths, some juggling takes place. For instance,
15\TEX\ sometimes uses dimensions as a signal to treat some characters as special.
16This is not a problem as long as one knows how to make a font and in practice
17that was done by looking at the properties of Computer Modern to implement
18similar shapes. After all, there are not that many math fonts around and
19basically there is only one engine that can deal with them properly.
20
21However, when Microsoft set the standard for \OPENTYPE\ math fonts it also
22steered the direction of their use in rendering mathematics. This means that the
23\LUATEX\ engine, which handles \OPENTYPE\ fonts, has to implement some
24alternative code paths. At the start, this involved a bit of gambling because
25there was no real specification; since then we now have a better picture. One of
26the more complex changes that took place is in the way italic correction is
27applied. A dirty way out of this dilemma would be to turn the math fonts into
28virtual ones that match traditional \TEX\ properties, but this would not be a
29nice solution.
30
31It must be noted that in the process of implementing support for the new fonts,
32Taco (Hoekwater) turned some noad types (see below) into a generic noad with a subtype. This
33simplified the transition. At the same time, a lot of detailed control was added
34in the way successive characters are spaced.
35
36In \LUATEX\ before 0.85, the italic correction was always added when a character got
37boxed (a frequently used preparation in the math builder). Now this is only done
38for the traditional fonts because, concerning italic correction, the \OPENTYPE\
39standard states: \footnote {Recently version 1.8 has been published on the Microsoft
40website.}
41
42\startitemize[n]
43    \startitem
44        When a run of slanted characters is followed by a straight character
45        (such as an operator or a delimiter), the italics correction of the last
46        glyph is added to its advance width.
47    \stopitem
48    \startitem
49        When positioning limits on an N-ary operator (e.g., integral sign), the
50        horizontal position of the upper limit is moved to the right by half of the
51        italics correction, while the position of the lower limit is moved to the
52        left by the same distance.
53    \stopitem
54    \startitem
55        When positioning superscripts and subscripts, their default horizontal
56        positions are also different by the amount of the italics correction of
57        the preceding glyph.
58    \stopitem
59\stopitemize
60
61And, with respect to kerning:
62
63\startitemize[continue]
64    \startitem
65        Set the default horizontal position for the superscript as shifted
66        relative to the position of the subscript by the italics correction of
67        the base glyph.
68    \stopitem
69\stopitemize
70
71I must admit that when the first implementation showed up, my natural reaction to
72unexpected behaviour was just to compensate for it. One such solution was simply not
73to pass the italic correction to the engine and deal with it in \LUA. In
74practice, that didn't work well for all cases; one reason was that the engine
75saw the combination of old fonts as a new one and followed a mixed code path.
76\footnote {\CONTEXT\ employed \UNICODE\ math right from the start of \LUATEX.}
77Another approach I tried was a mix of manipulated italic values and \LUA, but
78finally, as specifications settled I decided to leave it to the engine completely,
79if only because successive versions of \LUATEX\ behaved much better.
80
81So, as we were closing in on the first stable release of \LUATEX\ (1.0.0
82was released on September~27, 2016; this note was mostly written in the
83early part of 2016), I decided to fix the
84pending issues and sat down to look at the math|-|related code. I must admit that I
85had never looked in depth into that part of the machinery. In the next sections I
86will discuss some of the outcomes of this exercise.
87
88I will also discuss some extensions that have been on the agenda for years. They
89are rather generic and handy, but I must also admit that the \MKIV\ code related
90to math has so many options to control rendering that I'm not sure if they will
91ever be used in \CONTEXT. Nevertheless, these generic extensions fit well into
92the set of basic features of \LUATEX.
93
94\stopsection
95
96\startsection[title=Italic correction]
97
98As stated above, the normal code path included italic correction in all the math
99boxes made. This meant that, in some places, the correction had to be
100removed and/or moved to another place in the chain. This is a natural side effect
101of the fact that \TEX\ runs over the intermediate list of math nodes (noads) and
102turns them into regular nodes, mostly glyphs, kerns, glue and boxes.
103
104The complication is not so much the italic corrections themselves, because we
105could just continue to do the same, but the fact that these corrections are to be
106interpreted differently in case of integrals. There, the problem is that we have
107to (kind of) look backward at what is done in order to determine what italic
108corrections are to be applied.
109
110The original solution was to keep track of the applied correction via variables
111but that still made some analysis necessary. In the new implementation, more
112information is stored in the processed noads. This is a logical choice given that
113we have already added other information. It also makes it possible to fix cases
114that will (for sure) show up in the future.
115
116\startbuffer[ic-1]
117\ruledhbox\bgroup
118    \showglyphs\showboxes
119    \hbox{$\int ^2  $}\quad
120    \hbox{$\int   _2$}\quad
121    \hbox{$\int ^2_2$}\quad
122    \hbox{$f    ^2  $}\quad
123    \hbox{$f      _2$}\quad
124    \hbox{$f    ^2_2$}%
125\egroup
126\stopbuffer
127
128\startbuffer[ic-2]
129\ruledhbox\bgroup
130    \showglyphs\showboxes
131    \hbox{$\normalint ^2  $}\quad
132    \hbox{$\normalint   _2$}\quad
133    \hbox{$\normalint ^2_2$}\quad
134    \hbox{$\int       ^2  $}\quad
135    \hbox{$\int         _2$}\quad
136    \hbox{$\int       ^2_2$}%
137\egroup
138\stopbuffer
139
140\placefigure
141  [here]
142  [fig:italic-correction-1]
143  {Italic correction examples (1): superscripts shifted right and subscripts left.}
144  {\scale[width=\textwidth]{\getbuffer[ic-1]}}
145
146In \in {figure} [fig:italic-correction-1] we show two examples of inline italic
147correction. The superscripts are shifted to the right and the subscripts to the
148left. In the case of an integral sign, we need to move half the correction. This
149is triggered by the \type {\nolimits} primitive. In \in {figure}
150[fig:italic-correction-2] we show the difference between just an integral
151character and one tagged as having limits. \footnote {We show some boxes so that
152you can get an idea what \TEX\ is doing. Essentially, \TEX\ puts superscripts and
153subscripts on top of each other with some kern in between and then corrects the
154dimensions.}
155
156\placefigure
157  [here]
158  [fig:italic-correction-2]
159  {Italic correction examples (2): plain integral vs.\ integral with limits}
160  {\scale[width=\textwidth]{\getbuffer[ic-2]}}
161
162The amount of correction, if present at all, depends on the font, and in this
163document we use DejaVu math. \in {Figure} [fig:italic-correction-3] shows a few
164variants. As you can see, the amount of correction is highly font dependent.
165
166\placefigure
167  [here]
168  [fig:italic-correction-3]
169  {Italic correction examples (3): correction amounts are font-dependent.}
170  {\startcombination[1*4]
171     {\switchtobodyfont [pagella]\scale[width=\textwidth]{\getbuffer[ic-1]}} {cambria}
172     {\switchtobodyfont [cambria]\scale[width=\textwidth]{\getbuffer[ic-1]}} {pagella}
173     {\switchtobodyfont  [modern]\scale[width=\textwidth]{\getbuffer[ic-1]}} {latin modern}
174     {\switchtobodyfont[lucidaot]\scale[width=\textwidth]{\getbuffer[ic-1]}} {lucida ot}
175   \stopcombination}
176
177\startsection[title=Vertical delimiters]
178
179When we go into display math, there is a good chance that an integral has to be
180enlarged. The integral sign in \UNICODE\ has slot \type {0x222B}, so we can
181define a bigger one as follows:
182
183\startbuffer[nocontext]
184\let\int\normalint
185\stopbuffer
186
187\startbuffer[cambria]
188\switchtobodyfont[cambria]%
189\stopbuffer
190
191\startbuffer[pagella]
192\switchtobodyfont[pagella]%
193\stopbuffer
194
195\startbuffer[modern]
196\switchtobodyfont[modern]%
197\stopbuffer
198
199\startbuffer[lucidaot]
200\switchtobodyfont[lucidaot]%
201\stopbuffer
202
203\startbuffer[xits]
204\switchtobodyfont[xits]%
205\stopbuffer
206
207\startbuffer[largerint]
208\def\standardint{
209    \Umathchar "1 "0 "222B
210}
211\def\wrappedint{\mathop{
212    \Umathchar "1 "0 "222B
213}}
214\def\biggerint{\mathop{
215    \Uleft  height 3ex depth 3ex axis \Udelimiter "0 "0 "222B
216    \Uright .
217}}
218\def\evenbiggerint{\mathop{
219    \Uleft  height 6ex depth 6ex axis \Udelimiter "0 "0 "222B
220    \Uright .
221}}
222\stopbuffer
223
224\typebuffer[largerint]
225
226\startbuffer[demoint]
227$
228\displaystyle\standardint  ^a_b\enspace
229\displaystyle\wrappedint   ^a_b\enspace
230\displaystyle\biggerint    ^a_b\enspace
231\displaystyle\evenbiggerint^a_b\enspace
232$
233\stopbuffer
234
235The \type {axis} keyword will apply a shift up over the size of the current
236styles math axis. We use this in some examples as:
237
238\typebuffer[demoint]
239
240In \in {figure} [fig:demoint] you can see some subtle differences. The wrapped
241version doesn't shift the superscript and subscript. The reason is that the
242operator is hidden in its own wrapper and the scripts attach at an outer level.
243So, unless we start analyzing the innermost noad and apply that to the outer, we
244cannot know the shift. Such analyzing is asking for problems: where do we stop
245and what slight variations do we take into account? It's better to be
246predictable.
247
248\startbuffer
249    \ruledhbox \bgroup
250        \showglyphs \showboxes
251        \getbuffer[nocontext,pagella, largerint,demoint]
252        \getbuffer[nocontext,cambria, largerint,demoint]
253        \getbuffer[nocontext,modern,  largerint,demoint]
254        \getbuffer[nocontext,lucidaot,largerint,demoint]
255    \egroup
256\stopbuffer
257
258\placefigure
259  [here]
260  [fig:demoint]
261  {Comparison of integral variants (standard, wrapped, bigger, even
262   bigger) among fonts: \TeX\ Gyre Pagella, Cambria, Latin Modern, and
263   Lucida OT.}
264  {\scale[width=\textwidth]{\getbuffer}}
265
266Another observation is that Latin Modern does not provide (at least not yet)
267large integrals at all.
268
269The following four cases are equivalent:
270
271\starttyping
272\Uleft   height 3ex depth 3ex axis \Udelimiter "0 "0 "222B
273\Uright .
274
275\Uleft  .
276\Uright  height 3ex depth 3ex axis \Udelimiter "0 "0 "222B
277
278\Uleft   .
279\Umiddle height 3ex depth 3ex axis \Udelimiter "0 "0 "222B
280\Uright  .
281
282\Uleft   .
283\Umiddle height 3ex depth 3ex axis \Udelimiter "0 "0 "222B
284\Uright  .
285\stoptyping
286
287However, because this all looks a bit clumsy, we now provide a new
288primitive:
289
290\starttyping
291\Uvextensible
292    height <dimension>
293    depth <dimension>
294    axis
295    exact
296    <delimiter>
297\stoptyping
298
299The symbol to be constructed will have size \type {height} plus \type {depth}.
300When an \type {axis} is specified, the symbol will be shifted up, which is
301normally the case for such symbols. The keyword \type {exact} will correct the
302dimensions when no exact match is made, and this can be the case as long as we
303use the stepwise larger glyphs and before we end up using the composed shapes.
304When no dimensions are specified, the normal construction takes place and the
305only keyword that can be used then is \type {noaxis} which keeps the axis out of
306the calculations. After about a week of experimenting and exploring options, this
307combination made most sense, read: no fuzzy heuristics but predictable behaviour.
308After all, one might need different solutions for different fonts or
309circumstances and the applied logic (and expectations) can (and will, for sure)
310differ per macro package.
311
312\def\SampleRule#1#2%
313  {\blackrule[height=#1,depth=#2,width=1mm,color=maincolor]}
314
315% \def\SampleDelimiterSpec#1#2%
316%   {\ruledhbox \bgroup
317%       \SampleRule{20mm}{20mm}\enspace
318%       \ruledhbox{$\maincolor\char"#1$}\enspace
319%       \ruledhbox{$\Uleft height  1mm depth  1mm #2 \Udelimiter 0 0 "#1\Uright .$}\enspace
320%       \ruledhbox{$\Uleft height  2mm depth  2mm #2 \Udelimiter 0 0 "#1\Uright .$}\enspace
321%       \ruledhbox{$\Uleft height  5mm depth  5mm #2 \Udelimiter 0 0 "#1\Uright .$}\enspace
322%       \ruledhbox{$\Uleft height 20mm depth 20mm #2 \Udelimiter 0 0 "#1\Uright .$}\enspace
323%       \ruledhbox{$\Uleft height 20mm depth 10mm #2 \Udelimiter 0 0 "#1\Uright .$}%
324%    \egroup}
325
326\def\SampleDelimiterSpec#1#2%
327  {\ruledhbox \bgroup
328      \SampleRule{20mm}{20mm}\enspace
329      \ruledhbox{$\maincolor\char"#1$}\enspace
330      \ruledhbox{$\Uvextensible height  1mm depth  1mm #2 \Udelimiter 0 0 "#1$}\enspace
331      \ruledhbox{$\Uvextensible height  2mm depth  2mm #2 \Udelimiter 0 0 "#1$}\enspace
332      \ruledhbox{$\Uvextensible height  5mm depth  5mm #2 \Udelimiter 0 0 "#1$}\enspace
333      \ruledhbox{$\Uvextensible height 20mm depth 20mm #2 \Udelimiter 0 0 "#1$}\enspace
334      \ruledhbox{$\Uvextensible height 20mm depth 10mm #2 \Udelimiter 0 0 "#1$}%
335   \egroup}
336
337\startbuffer[delimiter-integral-spec]
338\startcombination[4*1]
339    {\SampleDelimiterSpec{222B}{}}           {}
340    {\SampleDelimiterSpec{222B}{axis}}       {axis}
341    {\SampleDelimiterSpec{222B}{exact}}      {exact}
342    {\SampleDelimiterSpec{222B}{axis exact}} {axis exact}
343\stopcombination
344\stopbuffer
345
346\startbuffer[delimiter-leftparent-spec]
347\startcombination[4*1]
348    {\SampleDelimiterSpec{0028}{}}           {}
349    {\SampleDelimiterSpec{0028}{axis}}       {axis}
350    {\SampleDelimiterSpec{0028}{exact}}      {exact}
351    {\SampleDelimiterSpec{0028}{axis exact}} {axis exact}
352\stopcombination
353\stopbuffer
354
355\placefigure
356  [here]
357  [fig:integral-spec]
358  {Cambria integrals, with dimensions.}
359  {\getbuffer[nocontext,cambria,delimiter-integral-spec]}
360
361\placefigure
362  [here]
363  [fig:leftparent-spec]
364  {Cambria left parenthesis, with dimensions.}
365  {\getbuffer[nocontext,cambria,delimiter-leftparent-spec]}
366
367\def\SampleDelimiterAuto#1#2%
368  {\ruledhbox \bgroup
369      \ruledhbox{$\maincolor\char"#1$}\enspace
370      \ruledhbox{$\Uleft #2 \Udelimiter 0 0 "#1\SampleRule{ 1mm}{ 1mm}\Uright .$}\enspace
371      \ruledhbox{$\Uleft #2 \Udelimiter 0 0 "#1\SampleRule{ 2mm}{ 2mm}\Uright .$}\enspace
372      \ruledhbox{$\Uleft #2 \Udelimiter 0 0 "#1\SampleRule{ 5mm}{ 5mm}\Uright .$}\enspace
373      \ruledhbox{$\Uleft #2 \Udelimiter 0 0 "#1\SampleRule{10mm}{10mm}\Uright .$}\enspace
374      \ruledhbox{$\Uleft #2 \Udelimiter 0 0 "#1\SampleRule{15mm}{15mm}\Uright .$}\enspace
375      \ruledhbox{$\Uleft #2 \Udelimiter 0 0 "#1\SampleRule{20mm}{20mm}\Uright .$}\enspace
376      \ruledhbox{$\Uleft #2 \Udelimiter 0 0 "#1\SampleRule{20mm}{10mm}\Uright .$}%
377   \egroup}
378
379\startbuffer[delimiter-integral-auto]
380\startcombination[2*1]
381    {\SampleDelimiterAuto{222B}{}}       {}
382    {\SampleDelimiterAuto{222B}{noaxis}} {noaxis}
383\stopcombination
384\stopbuffer
385
386\startbuffer[delimiter-leftparent-auto]
387\startcombination[4*1]
388    {\SampleDelimiterAuto{0028}{}}       {}
389    {\SampleDelimiterAuto{0028}{noaxis}} {noaxis}
390\stopcombination
391\stopbuffer
392
393\placefigure
394  [here]
395  [fig:integral]
396  {Cambria integrals, adaptive: \type {axis} left and \type {noaxis} right.}
397  {\getbuffer[nocontext,cambria,delimiter-integral-auto]}
398
399\placefigure
400  [here]
401  [fig:leftparent]
402  {Cambria left parenthesis, adaptive: \type {axis} left and \type {noaxis} right.}
403  {\getbuffer[nocontext,cambria,delimiter-leftparent-auto]}
404\stopsection
405
406\startsection[title=Horizontal delimiters]
407
408Horizontal extenders also have some new options. Although one can achieve similar
409results with macros, the following might look a bit more natural. Also, some
410properties are lost once the delimiter is constructed, so macros can become
411complex when trying to determine the original dimensions involved.
412
413We start with the new \type {\Uhextensible} primitive that accepts a dimension.
414It's just a variant of the over and under delimiters with no content part.
415
416\starttyping
417\Uhextensible
418    height <dimension>
419    depth <dimension>
420    left | middle | right
421    <family>
422    <slot>
423\stoptyping
424
425So for example you can say:
426
427\starttyping
428$\Uhextensible width 30pt 0 "2194$
429\stoptyping
430
431The \type {left}, \type {middle} and \type {right} keywords are only interpreted
432when the requested size can't be met due to stepwise larger glyph selection
433(i.e., before we start using arbitrary sizes made of snippets). \in {Figure}
434[fig:hextensible] shows what we get when we step from 2--20 points by
435increments of 2 points in Cambria.
436
437\unexpanded\def\ExtensibleFunA#1%
438  {\switchtobodyfont[cambria,17.3pt]%
439   \hbox\bgroup
440     \dostepwiserecurse{2}{20}{2}
441       {\backgroundline
442          [maincolor]
443          {\white$\Uhextensible width \recurselevel pt #1 0 "2194$}%
444        \quad}%
445     \unskip
446   \egroup}
447
448\unexpanded\def\ExtensibleFunB#1%
449  {\switchtobodyfont[cambria,17.3pt]%
450   \hbox\bgroup
451     \dostepwiserecurse{2}{20}{2}
452       {\ruledhbox
453          {$\Uhextensible width \recurselevel pt #1 0 "2194$}%
454        \quad}%
455     \unskip
456   \egroup}
457
458\startbuffer
459\starttabulate[|l|p|]
460    \NC (default)     \NC \ExtensibleFunA{}       \par \ExtensibleFunB{}       \NC \NR
461    \NC \type{left}   \NC \ExtensibleFunA{left}   \par \ExtensibleFunB{left}   \NC \NR
462    \NC \type{middle} \NC \ExtensibleFunA{middle} \par \ExtensibleFunB{middle} \NC \NR
463    \NC \type{right}  \NC \ExtensibleFunA{right}  \par \ExtensibleFunB{right}  \NC \NR
464\stoptabulate
465\stopbuffer
466
467\placefigure
468    [here]
469    [fig:hextensible]
470    {Stepwise wider \type {\Uhextensible} with options (cambria).}
471    {\getbuffer}
472
473The dimensions and options can also be given to the four primitives \type {\Uoverdelimiter},
474\type {\Uunderdelimiter}, \type {\Udelimiterover} and \type {\Udelimiterunder}. \in {Figure} [fig:delimiterunder] shows what happens when the
475delimiter is smaller than requested. The samples look like this:
476
477\starttyping
478$\Udelimiterunder width 1pt 0 "2194 {\hbox{\strut !}}
479\stoptyping
480
481When no dimension is given the keywords are ignored as it makes no sense to
482mess with the extensible in that case.
483
484\unexpanded\def\DelimiterFunA#1%
485  {\switchtobodyfont[cambria,20.7pt]%
486   \hbox\bgroup
487     \dostepwiserecurse{1}{10}{1}
488        {\backgroundline
489           [maincolor]
490           {\white$\Udelimiterunder width ##1pt #1 0 "2194 {\hbox{\strut !}}$}%
491         \quad}%
492     \unskip
493   \egroup}
494
495\unexpanded\def\DelimiterFunB#1%
496  {\switchtobodyfont[cambria,20.7pt]%
497   \hbox\bgroup
498     \dostepwiserecurse{1}{10}{1}
499        {\ruledhbox
500           {$\Udelimiterunder width ##1pt #1 0 "2194 {\hbox{\strut !}}$}%
501          \quad}%
502     \unskip
503   \egroup}
504
505\startbuffer
506\starttabulate[|l|p|]
507    \NC (default)     \NC \DelimiterFunA{}       \par \DelimiterFunB{}       \NC \NR
508    \NC \type{left}   \NC \DelimiterFunA{left}   \par \DelimiterFunB{left}   \NC \NR
509    \NC \type{middle} \NC \DelimiterFunA{middle} \par \DelimiterFunB{middle} \NC \NR
510    \NC \type{right}  \NC \DelimiterFunA{right}  \par \DelimiterFunB{right}  \NC \NR
511    \NC \NR
512\stoptabulate
513\stopbuffer
514
515\placefigure
516    [here]
517    [fig:delimiterunder]
518    {Stepwise wider \type {\Udelimiterunder} with options (cambria).}
519    {\getbuffer}
520
521\stopsection
522
523\startsection[title=Accents]
524
525Many years ago, I observed that overlaying characters (which happens when
526we negate an operator which has no composed negation glyph) didn't always give nice results
527and, therefore, a tracker item was created. When going over the todo list, I ran
528across a suggested patch by Khaled Hosny that added an overlay accent type. As
529the suggested solution fits in with the other extensions, a variant has been
530implemented.
531
532The results definitely depend on the quality and completeness of the font, so here we
533will show \type {xits}. The placement of an \type {overlay} also depends on the top
534accent shift as specified in the font for the used glyph. Instead of a fixed
535criterion for trying to find the best match, an additional \type {fraction}
536(numerator) parameter can be specified. A value of $800$ means that the target
537width is $800/1000$.
538
539The \type {\Umathaccent} command now has the following syntax:
540
541\starttyping
542\Umathaccent
543    [top|bottom|overlay]
544    [fixed]
545    [fraction <number>]
546    <delimiter>
547    {content}
548\stoptyping
549
550When we have an overlay, the fraction concerns the height; otherwise it concerns
551the width of the nucleus. In both cases, it is only applied when searching for
552stepwise larger glyphs, as extensibles are not influenced. An example of a
553specification is:
554
555\starttyping
556\Umathaccent
557    overlay "0 "0 "0338
558    fraction 950
559    {\Umathchar"1"0"2211}
560\stoptyping
561
562\in {Figure} [fig:accent-1] shows what we get when we use different fractions
563(from 800 up to 1500 with a step of 100). We see that \type {\overlay} is not
564always useful.
565
566\startbuffer[accents-1]
567\dostepwiserecurse{800}{1500}{100}{%
568$\Umathaccent
569    overlay "0 "0 "0338
570    fraction #1
571    {\Umathchar"1"0"2211} #1
572$\quad
573}\unskip
574\stopbuffer
575
576\startbuffer
577\startcombination[1*3]
578    {\getbuffer[xits,accents-1]}    {xits    \endash\ has   variants}
579    {\getbuffer[cambria,accents-1]} {cambria \endash\ lacks variants}
580    {\getbuffer[pagella,accents-1]} {pagella \endash\ lacks variants}
581\stopcombination
582\stopbuffer
583
584\placefigure
585    [here]
586    [fig:accent-1]
587    {Using \type {overlay} in \type {\Umathaccent}.}
588    {\getbuffer}
589
590\startbuffer[accents-2]
591$\Umathaccent overlay "0 "0 "0338 {x}$
592$\Umathaccent overlay "0 "0 "0338 {\tf x}$
593$\Umathaccent overlay "0 "0 "0338 {\tf xxx}$
594\stopbuffer
595
596Normally you can forget about the factor because overlays make most sense for
597inline math, which uses relatively small glyphs, so we can get \getbuffer
598[accents-2] with the following code:
599
600\typebuffer[accents-2]
601
602A normal accent can also be influenced by \type {fraction}:
603
604\startbuffer[accents-4]
605\dostepwiserecurse{500}{1500}{250}{%
606$
607    \Umathaccent
608        top "0 "0 "23DE
609        fraction #1
610        {a\times b}
611$\quad
612}\unskip
613\stopbuffer
614
615\blank \start \getbuffer[accents-4] \stop \blank
616
617\stopsection
618
619\startsection[title=Fractions]
620
621A normal fraction has a reasonable thick rule but as soon as you make it bigger you
622will notice a peculiar effect:
623
624\startlinecorrection
625\startcombination[5*1]
626   {$\displaystyle x + {{a} \abovewithdelims() 1pt {b}}$} {1pt}
627   {$\displaystyle x + {{a} \abovewithdelims() 2pt {b}}$} {2pt}
628   {$\displaystyle x + {{a} \abovewithdelims() 3pt {b}}$} {3pt}
629   {$\displaystyle x + {{a} \abovewithdelims() 4pt {b}}$} {4pt}
630   {$\displaystyle x + {{a} \abovewithdelims() 5pt {b}}$} {5pt}
631\stopcombination
632\stoplinecorrection
633
634Such a fraction is specified as:
635
636\starttyping
637x + { {a} \abovewithdelims () 5pt {b} }
638\stoptyping
639
640A new keyword \type {exact} avoids the excessive spacing:
641
642\starttyping
643x + { {a} \abovewithdelims () exact 5pt {b} }
644\stoptyping
645
646Now we get:
647
648\startlinecorrection
649\startcombination[5*1]
650   {$\displaystyle x + {{a} \abovewithdelims() exact 1pt {b}}$} {1pt}
651   {$\displaystyle x + {{a} \abovewithdelims() exact 2pt {b}}$} {2pt}
652   {$\displaystyle x + {{a} \abovewithdelims() exact 3pt {b}}$} {3pt}
653   {$\displaystyle x + {{a} \abovewithdelims() exact 4pt {b}}$} {4pt}
654   {$\displaystyle x + {{a} \abovewithdelims() exact 5pt {b}}$} {5pt}
655\stopcombination
656\stoplinecorrection
657
658One way to get consistent spacing in such fractions is to use struts:
659
660\starttyping
661x + { {\strut a} \abovewithdelims () exact 5pt {\strut b} }
662\stoptyping
663
664Now we get:
665
666\startlinecorrection
667\startcombination[5*1]
668   {$\displaystyle x + {{\strut a} \abovewithdelims() exact 1pt {\strut b}}$} {1pt}
669   {$\displaystyle x + {{\strut a} \abovewithdelims() exact 2pt {\strut b}}$} {2pt}
670   {$\displaystyle x + {{\strut a} \abovewithdelims() exact 3pt {\strut b}}$} {3pt}
671   {$\displaystyle x + {{\strut a} \abovewithdelims() exact 4pt {\strut b}}$} {4pt}
672   {$\displaystyle x + {{\strut a} \abovewithdelims() exact 5pt {\strut b}}$} {5pt}
673\stopcombination
674\stoplinecorrection
675
676Yet another way to increase the distance between the rule and text a bit is:
677
678\starttyping
679\Umathfractionnumvgap  \displaystyle4pt
680\Umathfractiondenomvgap\displaystyle4pt
681\stoptyping
682
683This looks quite consistent:
684
685\startlinecorrection
686\Umathfractionnumvgap  \displaystyle4pt
687\Umathfractiondenomvgap\displaystyle4pt
688\startcombination[5*1]
689   {$\displaystyle x + {{a} \abovewithdelims() exact 1pt {b}}$} {1pt}
690   {$\displaystyle x + {{a} \abovewithdelims() exact 2pt {b}}$} {2pt}
691   {$\displaystyle x + {{a} \abovewithdelims() exact 3pt {b}}$} {3pt}
692   {$\displaystyle x + {{a} \abovewithdelims() exact 4pt {b}}$} {4pt}
693   {$\displaystyle x + {{a} \abovewithdelims() exact 5pt {b}}$} {5pt}
694\stopcombination
695\stoplinecorrection
696
697Here we use code like:
698
699\starttyping
700$\displaystyle x + {{a} \abovewithdelims() exact 2pt {b}}$
701\stoptyping
702
703Using struts, it is best to zero the gap:
704
705\startlinecorrection
706\Umathfractionnumvgap  \displaystyle0pt
707\Umathfractiondenomvgap\displaystyle0pt
708\startcombination[5*1]
709   {$\displaystyle x + {{\strut a} \abovewithdelims() exact 1pt {\strut b}}$} {1pt}
710   {$\displaystyle x + {{\strut a} \abovewithdelims() exact 2pt {\strut b}}$} {2pt}
711   {$\displaystyle x + {{\strut a} \abovewithdelims() exact 3pt {\strut b}}$} {3pt}
712   {$\displaystyle x + {{\strut a} \abovewithdelims() exact 4pt {\strut b}}$} {4pt}
713   {$\displaystyle x + {{\strut a} \abovewithdelims() exact 5pt {\strut b}}$} {5pt}
714\stopcombination
715\stoplinecorrection
716
717Here we use code like:
718
719\starttyping
720$\displaystyle x + {{\strut a} \abovewithdelims() exact 2pt {\strut b}}$
721\stoptyping
722
723\stopsection
724
725\startsection[title=Skewed fractions]
726
727The math parameter table contains values specifying horizontal and
728vertical gaps for skewed fractions. Some guessing is needed in order to implement
729something that uses them, so we now provide a primitive similar to the other
730fraction related ones but with a few options that one can use to influence the
731rendering. Of course, a user can mess around directly with the parameters \type
732{\Umathskewedfractionhgap} and \type {\Umathskewedfractionvgap}.
733
734The syntax used here is:
735
736\starttyping
737{ {1} \Uskewed / <options> {2} }
738{ {1} \Uskewedwithdelims / () <options> {2} }
739\stoptyping
740
741The options can be \type {noaxis} and \type {exact}, a combination of them or
742just nothing. By default we add half the axis to the shifts and also by default
743we zero the width of the middle character. For Latin Modern, the result looks as
744follows:
745
746\def\ShowA#1#2#3{$x + { {#1} \Uskewed           /    #3 {#2} } + x$}
747\def\ShowB#1#2#3{$x + { {#1} \Uskewedwithdelims / () #3 {#2} } + x$}
748
749\start
750    \switchtobodyfont[modern]
751    \starttabulate[||||||]
752        \NC \NC
753            \ShowA{a}{b}{} \NC
754            \ShowA{1}{2}{} \NC
755            \ShowB{a}{b}{} \NC
756            \ShowB{1}{2}{} \NC
757        \NR
758        \NC \type{exact} \NC
759            \ShowA{a}{b}{exact} \NC
760            \ShowA{1}{2}{exact} \NC
761            \ShowB{a}{b}{exact} \NC
762            \ShowB{1}{2}{exact} \NC
763        \NR
764        \NC \type{noaxis} \NC
765            \ShowA{a}{b}{noaxis} \NC
766            \ShowA{1}{2}{noaxis} \NC
767            \ShowB{a}{b}{noaxis} \NC
768            \ShowB{1}{2}{noaxis} \NC
769        \NR
770        \NC \type{exact noaxis} \NC
771            \ShowA{a}{b}{exact noaxis} \NC
772            \ShowA{1}{2}{exact noaxis} \NC
773            \ShowB{a}{b}{exact noaxis} \NC
774            \ShowB{1}{2}{exact noaxis} \NC
775        \NR
776    \stoptabulate
777\stop
778
779\stopsection
780
781\startsection[title=Side effects]
782
783Not all bugs reported as such are really bugs. Here is one that came from a
784misunderstanding: In Eijkhout's \quotation {\TEX\ by Topic}, the rules for
785handling styles in scripts are described as follows:
786
787\startitemize
788\startitem
789    In any style superscripts and subscripts are taken from the next smaller
790    style. Exception: in display style they are taken in script style.
791\stopitem
792\startitem
793    Subscripts are always in the cramped variant of the style; superscripts are
794    only cramped if the original style was cramped.
795\stopitem
796\startitem
797    In an \type {..\over..} formula in any style the numerator and denominator
798    are taken from the next smaller style.
799\stopitem
800\startitem
801    The denominator is always in cramped style; the numerator is only in cramped
802    style if the original style was cramped.
803\stopitem
804\startitem
805    Formulas under a \type {\sqrt} or \type {\overline} are in cramped style.
806\stopitem
807\stopitemize
808
809In \LUATEX, one can set the styles in more detail, which means that you sometimes
810have to set both normal and cramped styles to get the effect you want. If we
811force styles in the script using \type {\scriptstyle} and \type
812{\crampedscriptstyle} we get the following (all render the same):
813
814\startbuffer[demo]
815\starttabulate
816\NC default       \NC $b_{x=xx}^{x=xx}$ \NC \NR
817\NC script        \NC $b_{\scriptstyle x=xx}^{\scriptstyle x=xx}$ \NC \NR
818\NC crampedscript \NC $b_{\crampedscriptstyle x=xx}^{\crampedscriptstyle x=xx}$ \NC \NR
819\stoptabulate
820\stopbuffer
821
822\getbuffer[demo]
823
824This is coded like:
825
826\starttyping
827$b_{x=xx}^{x=xx}$
828$b_{\scriptstyle x=xx}^{\scriptstyle x=xx}$
829$b_{\crampedscriptstyle x=xx}^{\crampedscriptstyle x=xx}$
830\stoptyping
831
832Now we set the following parameters:
833
834\startbuffer[setup]
835\Umathordrelspacing\scriptstyle=30mu
836\Umathordordspacing\scriptstyle=30mu
837\stopbuffer
838
839\typebuffer[setup]
840
841This gives:
842
843\start\getbuffer[setup,demo]\stop
844
845Since the result is not what is expected (visually), we should say:
846
847\startbuffer[setup]
848\Umathordrelspacing\scriptstyle=30mu
849\Umathordordspacing\scriptstyle=30mu
850\Umathordrelspacing\crampedscriptstyle=30mu
851\Umathordordspacing\crampedscriptstyle=30mu
852\stopbuffer
853
854\typebuffer[setup]
855
856Now we get:
857
858\start\getbuffer[setup,demo]\stop
859
860\stopsection
861
862\startsection[title=Fixed scripts]
863
864We have three parameters that are used for anchoring superscripts and subscripts,
865alone or in combinations.
866
867\starttabulate[|l|l|]
868\NC $d$ \NC \type {\Umathsubshiftdown}    \NC \NR
869\NC $u$ \NC \type {\Umathsupshiftup}      \NC \NR
870\NC $s$ \NC \type {\Umathsubsupshiftdown} \NC \NR
871\stoptabulate
872
873When we set \type {\mathscriptsmode} to a value other than zero, these are used
874for calculating fixed positions. This is something that is needed in, for
875instance, chemical equations. You can manipulate the mentioned variables to
876achieve different effects, and the specifications are shown in the following table. In
877order to see the differences in more detail, they are enlarged in \in {figure}
878[fig:mathscriptsmode].
879
880\def\SampleMath#1%
881  {\ruledhbox{$\mathscriptsmode#1\mathupright CH_2 + CH^+_2 + CH^2_2$}}
882
883\starttabulate[|c|c|c|l|]
884    \NC \bf mode \NC \bf down      \NC \bf up        \NC                \NC \NR
885    \NC 0        \NC dynamic       \NC dynamic       \NC \SampleMath{0} \NC \NR
886    \NC 1        \NC $d$           \NC $u$           \NC \SampleMath{1} \NC \NR
887    \NC 2        \NC $s$           \NC $u$           \NC \SampleMath{2} \NC \NR
888    \NC 3        \NC $s$           \NC $u + s - d$   \NC \SampleMath{3} \NC \NR
889    \NC 4        \NC $d + (s-d)/2$ \NC $u + (s-d)/2$ \NC \SampleMath{4} \NC \NR
890    \NC 5        \NC $d$           \NC $u + s - d$   \NC \SampleMath{5} \NC \NR
891\stoptabulate
892
893\placefigure
894  [here]
895  [fig:mathscriptsmode]
896  {The effect of setting \type {\mathscriptsmode}.}
897  {\startcombination[nx=3,ny=2,distance=1em]
898     {\scale[width=\dimexpr(\textwidth-2em)/3\relax]{\SampleMath{0}}} {0}
899     {\scale[width=\dimexpr(\textwidth-2em)/3\relax]{\SampleMath{1}}} {1}
900     {\scale[width=\dimexpr(\textwidth-2em)/3\relax]{\SampleMath{2}}} {2}
901     {\scale[width=\dimexpr(\textwidth-2em)/3\relax]{\SampleMath{3}}} {3}
902     {\scale[width=\dimexpr(\textwidth-2em)/3\relax]{\SampleMath{4}}} {4}
903     {\scale[width=\dimexpr(\textwidth-2em)/3\relax]{\SampleMath{5}}} {5}
904   \stopcombination}
905
906\stopsection
907
908\startsection[title=Remark]
909
910The changes that we have made are hopefully not too intrusive. Instead of
911extending existing commands, new ones were introduced so that compatibility
912should not be a significant problem. To some extent, these extensions violate the
913principle that extensions should be done in \LUA, but \TEX\ being a math renderer
914and \OPENTYPE\ replacing old font technology, we felt that we should make an
915exception here. Hopefully, not too many bugs were introduced.
916
917\stopsection
918
919\stopchapter
920
921\stoptext
922