% language=us runpath=texruns:manuals/ontarget

% \profilemacro\scaledfontdimen

% \usebodyfont[modern]
% \usebodyfont[cambria]
% \usebodyfont[termes]
% \usebodyfont[pagella]
% \usebodyfont[bonum]

\startcomponent ontarget-math

\environment ontarget-style

\startchapter[title={A different approach to math spacing}]

\startsubject[title=Introduction]

The \TEX\ engine is famous for its rendering of math and even after decades there
is no real contender. And so there also is no real pressure to see if we can do
better. However, when Mikael Sundqvist ran into a Swedish math rendering
specification and we started discussing a possible support for that in \CONTEXT,
it quickly became clear that the way \TEX\ does spacing is a bit less flexible
than one wishes for. We already have much of what is needed in place but it also
has to work well with how \TEX\ sees things:

\startitemize[packed,n]
\startitem
    Math is made from a sequence of atoms: a quantity with a nucleus, superscript
    subscript. \footnote {I suddenly realize why in the engine noads have a
    nucleus field: they are atoms \unknown\ but what does that make super and
    subscripts.} Atoms are spaced by \type {\thinmuskip}, \type {\medmuskip} and
    \type {\thickmuskip} or nothing, and that is sort of hard coded.
\stopitem
\startitem
    Atoms are organized by class and there are seven (or eight, depending on how
    you look at it) of them visible: binary symbols, relations, etc. The
    invisible ones, composites like fractions and fenced material (we call them
    molecules) are at some point mapped onto the core set. Molecules like fences
    have a different class left and right of the fenced material.
\stopitem
\startitem
    In addition the engine itself has all kind of spacing related parameters and
    these kick in automatically and sometimes have side effects. The same is
    true for penalties.
\stopitem
\stopitemize

The normal approach to spacing other than imposed by the engine is to use
correction space, like \type {\,} and I think that quite some \TEX\ users think
that this is how it is supposed to be. The standard way to enter math relates to
scientific publishing and there the standards are often chiseled in stone so why
should users tweak anyway. However, in \CONTEXT\ we tend to start from the users
and not the publishers end so there we can decide to follow different routes.
Users can always work around something they don't like but we focus on reliable
input giving predictable output. Also, when reading on, it is good to realize
that it is all about the user experience here: it should look nice (which then of
course makes one become aware of issues elsewhere) and we don't care much about
specific demands of publishers in the scientific field: the fact that they often
re|-|key content doesn't go well with users paying attention themselves, let
alone the fact that nowadays they can demand word processor formats.

The three mentioned steps are fine for the average case but sometimes make no
sense. It was definitely the best approach given time and resources but when
\LUATEX\ went \OPENTYPE\ a lot of parameters were added and at that time we
therefore added spacing by class pair. That not only decoupled the relation
between the three (configurable) muskip parameters but also made it possible to
use plenty of them. Now it must be said that for consistency having these three
skips works great but given the tweaking expected from users consistency is
not always what comes out.

This situation is very well comparable to the proclaimed qualities of the
typesetting of text by \TEX. Yes, it can do a great job, and often does, but users
can mess up quite well. I remember that when we did tests with \HZ\ the outcomes
were pretty unimpressive. When you give an audience a set of sample renderings,
where each sample is slightly different and each user gets a randomized subset,
the sudden lack of being able to compare (and agree) with another \TEX ie makes
for interesting conclusions. They look for the opposites of what is claimed to be
perfect. So, two lines with hyphens rate low, even if not doing it would look
worse. The same for a few short words in the last line of a paragraph. Excessive
spacing is also seen as bad. So, when asked why some paragraphs looked okay
noticing (excessive and troublesome) expansion was not seen as a problem; instead
it were hyphens that got the attraction.

The same is probably true for math: the input with lots of correction spaces or
commands where characters would do can be horrible but it's just the way it is
supposed to be. The therefore expected output can only be perfect, right,
independent of how one actually messed up spacing. But personally I think that it
is often spacing messed up by users that make a \TEX\ document recognizable. It
compares to word processor results that one can sometimes identify by multiple
consecutive spaces in the typeset text instead of using a glue model like \TEX.
Reaching perfection is not always trivial, but fortunately we can also find
plenty of nice looking documents done with \TEX.

The \TEX book has an excellent and intriguing chapter on the fine points of math
and it definitely shows why Don Knuth wrote \TEX\ as a tool for his books. He
pays a lot of attention to detail and that is also why it all works out so well.
If you need to render from unseen sources (as happens in an \XML\ workflow)
coming from several authors and have time nor money to check everything, you're
off worse. And I'm not even talking of input where invisible \UNICODE\ spacing
characters are injected. It is the \TEX\ book(s) that has drawn me to this
program and believe it or not, in the first project I was involved in that
demanded typeset (quantum mechanics) math the \IBM\ typewriter with changing
bulbs ruled the scenery. In fact, our involvement was quickly cut off when we
dared to show a chapter done in \TEX\ that looked better.

Apart from an occasional tweak, in \CONTEXT\ we never really used this opened up
math atom pair spacing mechanism available in \LUATEX\ extensively. So, when I
was pondering how to proceed it stroke me that it would make sense to generalize
this mechanism. It was already possible (via a mode parameter) to bypass the
second step mentioned above, but we definitely needed more than the visible
classes that the engine had. In \CONTEXT\ we already had more classes but those
were meant for assigning characters and commands to specific math constructs
(think of fences, fractions and radicals) so in the end they were not really
classes. Considering this option was made easier by the fact that Mikael would do
the testing and help configuring the defaults, which all will result in a new
math user manual.

There are extensions introduced in \LUATEX\ and later \LUAMETATEX\ that are not
discussed here. In this expose we concentrate on the features that were explored,
extended and introduced while we worked on updating math support in \LMTX.

\stopsubject

\startsubject[title=An example]

Before we go into details, let's give an example of unnoticed spacing effects. We
use three simple formulas all using fractions:

\startbuffer[one]
\ruledhbox{$\frac{x^2}{a+1}$}
\stopbuffer

\startbuffer[two]
\ruledhbox{$x + \frac{x^2}{a+1} = 10$}
\stopbuffer

\startbuffer[three]
\ruledhbox{$\frac{1}{2}\frac{1}{2}x$}
\stopbuffer

\typebuffer[one]

and:

\typebuffer[two]

as well as:

\typebuffer[three]

\startbuffer[all]
\dontleavehmode
\scale[scale=4000]{\getbuffer[one]}
\scale[scale=4000]{\getbuffer[two]}
\scale[scale=4000]{\getbuffer[three]}
\stopbuffer

\startlinecorrection
\nulldelimiterspace=1.2pt\getbuffer[all]
\stoplinecorrection

If you look closely you see that the fraction has a little space at the left and
right. Where does that come from? Because we normally don't put a tight frame
around a fraction, we are not really aware of it. The spacing between what are
called ordinary, operator, binary, relation and other classes of atoms is
explained in the \TEX book (or \quotation {\TEX\ by Topic} if you want a summary)
and basically we have a class by class matrix that is built into \TEX. The
engine looks at successive items and spacing depends on their (perceived) class.
Because the number of classes is limited, and because the spacing pairs are hard
coded, the engine cheats a little. Depending on what came before or comes next
the class of an atom is adapted to suit the spacing matrix. One can say that a
\quotation {reading mathematician} is built in. And most of the decisions are
okay. If needed one can always wrap something in e.g.\ \type {\mathrel} but of
course that also can interfere with grouping. All this is true for \TEX, \PDFTEX,
\XETEX\ and \LUATEX, but a bit different in \LUAMETATEX\ as we will see.

The little spacing on both edges of the fraction is a side effect of the way they
are built internally: fractions are actually a generalized form of \quotation
{stuff put on top of other stuff} and they can have left and|/|or right
delimiters: this is driven by primitives that have names like \type {\atop} and
\type {\atopwithdelims}. The way the components are placed is (especially in the
case of \OPENTYPE) driven by lots of parameters and I will leave that out of the
discussion.

When there are no delimiters, a so called \type {\nulldelimiterspace} will be
injected. That parameter is set to 1.2 points and I have to admit that in
\CONTEXT\ I never considered letting that one adapt to the body font size, which
means that, as we default to a 12 point body font, the value there should have
been 1.44 points: mea culpa. When we set this parameter to zero point, we get
this:

\startlinecorrection
\nulldelimiterspace=0pt\getbuffer[all]
\stoplinecorrection

As intermezzo and moment of contemplation I show some examples of fractions mixed
into text. When we have the delimiter space set we get this:

\start \nulldelimiterspace=1.2pt \dorecurse{100}{test $\frac{1}{#1}$ } \stop

While with zero it looks like this, quite a different outcome:

\start \nulldelimiterspace=0pt   \dorecurse{100}{test $\frac{1}{#1}$ } \stop

A little tracing shows it more clearly:

\start \showboxes \nulldelimiterspace=1.2pt \dorecurse{100}{test $\frac{1}{#1}$ } \stop

You can zoom in and see where it interferes with margin alignment.

\start \showboxes \nulldelimiterspace=0pt   \dorecurse{100}{test $\frac{1}{#1}$ } \stop

So, if you ever meet a user who claims perfection and superiority of typesetting,
check out her|/|his work which might have inline fractions done the spacy way. It
might make other visually typesetting claims less trustworthy. And yes, one can
wonder if margin kerning could help here but as this content is wrapped in boxes it
is unlikely to work out well (and not worth the effort).

In order to get a better picture of the spacing, two more renderings are shown.
This time we show the bounding boxes of the characters too (you might need to zoom
in to see it):

\startlinecorrection
\showglyphs\nulldelimiterspace=1.2pt\getbuffer[all]
\stoplinecorrection

Again we also show the zero case

\startlinecorrection
\showglyphs\nulldelimiterspace=0pt\getbuffer[all]
\stoplinecorrection

This makes clear why there actually is this extra space around a fraction:
regular operators have side bearings and thereby have some added space. And when
we put a fraction in front of a symbol we need that little extra space. Of course
a proper class pair spacing value could do the job but there is no fraction
class. The engine cheats by changing the class depending on what follows or came
before and this is why on the average it looks okay. However, these examples
demonstrate that there are some assumptions with regard to for instance fonts
and this is one of the reasons why the more or less official expected \OPENTYPE\
behavior as dictated by the Cambria font doesn't always work out well for fonts
that evolved from the ones used in the \TEX\ community. Also imagine how this
interferes with the fact that traditional \TEX\ fonts and the machinery do magic
with cheating about width combined with italic correction (all plausible and
quite clever but somewhat tricky with respect to \OPENTYPE).

Because here we discuss the way \LUAMETATEX\ and \CONTEXT\ deal with this, the
following examples show a probably unexpected outcome. Again first the non|-|zero
case:

\startlinecorrection
\showglyphs\showmakeup[mathglue]\nulldelimiterspace=1.2pt\getbuffer[all]
\stoplinecorrection

And here the zero case:

\startlinecorrection
\showglyphs\showmakeup[mathglue]\nulldelimiterspace=0pt\getbuffer[all]
\stoplinecorrection

I will not go into details about the way fractions are supported in the engine
because some extensions are already around for quite a while. The main
observation here is that in \LUAMETATEX\ we have alternative primitives that
assume forward scanning, as if the numerator and denominator are arguments. The
engine also supports skewed (vulgar) fractions natively where numerator and
denominator are raised and lowered relative to the (often) slash. Many aspects
of the rendering can be tuned in the so called font goodie files, which is also
the place where we define the additional font parameters.

\stopsubject

\startsubject[title=Atom spacing]

If you are familiar with traditional \TEX\ you know that there is some built in
\type {ordbin} spacing. But there is no such pair for a fraction and a relation,
simply because there is no fraction class. However, in \LUAMETATEX\ there is one,
and we'd better set it up if we zero the margins of a fraction.

It is worth noticing that fractions are sort of special anyway. The official
syntax is \type {n \over m} and numerator and denominator can be sub formulas.
This is the one case where the parser sort of has to look back, which is tricky
because the machinery is a forward looking one. Therefore, in order to get the
expected styling (or avoid unexpected side effects) one will normally wrap all in
braces as in: \type {{ {n} \over {m} }} which of course kind defeats the simple
syntax which probably is supported for \type {1\over2} kind of usage, so a next
challenge is to make \type {1/2} come out right. All this means that in practice
we have wrappers like \type {\frac} which accidentally in \LUAMETATEX\ can be
defined using forward looking primitives with plenty extra properties driven by
keywords. It also means that fractions as expected by the engine due to wrapping
actually can be a different kind of atom, which can have puzzling side effects
with respect to spacing (because the remapping happens unseen).

Interesting is that adapting \LUAMETATEX\ to a more extensive model was quite
doable, also because the code base had already been made more configurable. Of
course it involved quite a bit of tedious editing and throwing out already nice
and clean code that had taken some effort, but that's the way it is. Of course
more classes also means that some storage properties had to be adapted within the
available space but by sacrificing families that was possible. With 64 potential
classes we now are back to 64 families compared to 7 classes and 256 families in
\LUATEX\ and 7 classes and 16 families in traditional \TEX.

Also interesting is that the new implementation is actually somewhat simpler and
therefore the binary is a tad smaller too. But does all that mean that there were
no pitfalls? Sure there were! It is worth noticing that doing all this reminded
me of the early days of \LUATEX\ development, where Taco and I exchanged binaries
and \TEX\ code in a more or less constant way using Skype. For \LUAMETATEX\ we
used good old mail for files and Mojca's build farm for binaries and Mikael and I
spent many months exchanging information and testing out alternatives on a daily
basis: it is in my opinion the only way to do this and it's fun too. It has been
a lot of work but once we got going there was nothing that could stop us. A side
effect was that there were no updates during this period, which was something
users noticed.

In the spacing matrix there is \type {inner} and internally there's also some
care to be taken of \type {vcenter}. The \type {inner} class is actually shared
with the \type {variable} class which is not so much a real class but more a
signal to the engine that when an alphabetic or numeric character is included
it has to come from a specific family: upright family zero or math italic family
one in traditional speak. But, what if we don't have that setup? Well, then one
has to make sure that this special class number is not associated (which is no
big deal). It does mean that when we extend the repertoire of classes we
cannot use slot seven. Always keep in mind that classes (and thereby signals) get
assigned to characters (some defaults by the engine, others by the macro
package). It is why in \CONTEXT\ we use abstract class numbers, just in case the
engine gets adapted.

We also cannot use slot eight because that one is a signal too: for a possible
active math character, a feature somewhat complicated by the fact that it should
not interfere with passing around such active characters in arguments. In math
mode where we have lots of macros passing around content, this special class works
around these side effects. We don't need this feature in \CONTEXT\ because
contrary to other macro packages we don't handle primes, pseudo superscripts
potentially followed by other super and subscripts by making the \type {'} an
active character and thereby a macro in math mode. This trickery again closely
relates to preferable input, font properties, and limitations of memory and such
at the time \TEX\ showed up (much has to fit into 8, 16 or 32 bits, so there is
not much room for e.g.\ more than 8 classes). Since we started with \MKIV\ the way
math is dealt with is a bit different than normally done in \TEX\ anyway.

\stopsubject

\startsubject[title=Atom rules]

We can now control the spacing between every atom but unfortunately that is not
good enough. Therefore, we arrive at yet another feature built into the engine:
turning classes into other classes depending on neighbors. And this is precisely
why we have certain classes. Let's quote \quotation {\TEX\ by Topic}: {\em The
cases \type {*} (in the atom spacing matrix) cannot occur, because a \type {bin}
object is converted to \type {ord} if it is the first in the list, preceded by
\type {bin}, \type {op}, \type {open}, \type {punct}, \type {rel}, or followed by
\type{close}, \type {punct}, or \type {rel}; also, a \type{rel} is converted to
\type{ord} when it is followed by \type {close} or \type {punct}.}

We can of course keep these hard coded heuristics but can as well make that bit
of code configurable, which we did. Below is demonstrated how one can set up the
defaults at the \TEX\ end. We use symbolic names for the classes.

\starttyping
\setmathatomrule  \mathbegincode         \mathbinarycode       % old
  \allmathstyles    \mathordinarycode      \mathordinarycode   % new

\setmathatomrule  \mathbinarycode        \mathbinarycode
  \allmathstyles    \mathbinarycode        \mathordinarycode
\setmathatomrule  \mathoperatorcode      \mathbinarycode
  \allmathstyles    \mathoperatorcode       \mathordinarycode
\setmathatomrule  \mathopencode          \mathbinarycode
  \allmathstyles    \mathopencode          \mathordinarycode
\setmathatomrule  \mathpunctuationcode   \mathbinarycode
  \allmathstyles    \mathpunctuationcode   \mathordinarycode
\setmathatomrule  \mathrelationcode      \mathbinarycode
  \allmathstyles    \mathrelationcode      \mathordinarycode

\setmathatomrule  \mathbinarycode        \mathclosecode
  \allmathstyles    \mathordinarycode      \mathclosecode
\setmathatomrule  \mathbinarycode        \mathpunctuationcode
  \allmathstyles    \mathordinarycode      \mathpunctuationcode
\setmathatomrule  \mathbinarycode        \mathrelationcode
  \allmathstyles    \mathordinarycode      \mathrelationcode

\setmathatomrule  \mathrelationcode      \mathclosecode
  \allmathstyles    \mathordinarycode      \mathclosecode
\setmathatomrule  \mathrelationcode      \mathpunctuationcode
  \allmathstyles    \mathordinarycode      \mathpunctuationcode
\stoptyping

Watch the special class with \type {\mathbegincode}. This is actually class 62 so
you don't need much fantasy to imagine that class 63 is \type {\mathendcode}, but
that one is not yet used. In a similar fashion we can initialize the spacing
itself: \footnote {Constant, engine specific, numbers like these are available in
tables at the \LUA\ end so we can change them and users can check that.}

\starttyping
\setmathspacing \mathordcode   \mathopcode     \allmathstyles  \thinmuskip
\setmathspacing \mathordcode   \mathbincode    \allsplitstyles \medmuskip
\setmathspacing \mathordcode   \mathrelcode    \allsplitstyles \thickmuskip
\setmathspacing \mathordcode   \mathinnercode  \allsplitstyles \thinmuskip

\setmathspacing \mathopcode    \mathordcode    \allmathstyles  \thinmuskip
\setmathspacing \mathopcode    \mathopcode     \allmathstyles  \thinmuskip
\setmathspacing \mathopcode    \mathrelcode    \allsplitstyles \thickmuskip
\setmathspacing \mathopcode    \mathinnercode  \allsplitstyles \thinmuskip

\setmathspacing \mathbincode   \mathordcode    \allsplitstyles \medmuskip
\setmathspacing \mathbincode   \mathopcode     \allsplitstyles \medmuskip
\setmathspacing \mathbincode   \mathopencode   \allsplitstyles \medmuskip
\setmathspacing \mathbincode   \mathinnercode  \allsplitstyles \medmuskip

\setmathspacing \mathrelcode   \mathordcode    \allsplitstyles \thickmuskip
\setmathspacing \mathrelcode   \mathopcode     \allsplitstyles \thickmuskip
\setmathspacing \mathrelcode   \mathopencode   \allsplitstyles \thickmuskip
\setmathspacing \mathrelcode   \mathinnercode  \allsplitstyles \thickmuskip

\setmathspacing \mathclosecode \mathopcode     \allmathstyles  \thinmuskip
\setmathspacing \mathclosecode \mathbincode    \allsplitstyles \medmuskip
\setmathspacing \mathclosecode \mathrelcode    \allsplitstyles \thickmuskip
\setmathspacing \mathclosecode \mathinnercode  \allsplitstyles \thinmuskip

\setmathspacing \mathpunctcode \mathordcode    \allsplitstyles \thinmuskip
\setmathspacing \mathpunctcode \mathopcode     \allsplitstyles \thinmuskip
\setmathspacing \mathpunctcode \mathrelcode    \allsplitstyles \thinmuskip
\setmathspacing \mathpunctcode \mathopencode   \allsplitstyles \thinmuskip
\setmathspacing \mathpunctcode \mathclosecode  \allsplitstyles \thinmuskip
\setmathspacing \mathpunctcode \mathpunctcode  \allsplitstyles \thinmuskip
\setmathspacing \mathpunctcode \mathinnercode  \allsplitstyles \thinmuskip

\setmathspacing \mathinnercode \mathordcode    \allsplitstyles \thinmuskip
\setmathspacing \mathinnercode \mathopcode     \allmathstyles  \thinmuskip
\setmathspacing \mathinnercode \mathbincode    \allsplitstyles \medmuskip
\setmathspacing \mathinnercode \mathrelcode    \allsplitstyles \thickmuskip
\setmathspacing \mathinnercode \mathopencode   \allsplitstyles \thinmuskip
\setmathspacing \mathinnercode \mathpunctcode  \allsplitstyles \thinmuskip
\setmathspacing \mathinnercode \mathinnercode  \allsplitstyles \thinmuskip
\stoptyping

And because we have a few more atom classes this also needs to happen:

\starttyping[style=\tt]
\letmathspacing  \mathactivecode   \mathordinarycode
\letmathspacing  \mathvariablecode \mathordinarycode
\letmathspacing  \mathovercode     \mathordinarycode
\letmathspacing  \mathundercode    \mathordinarycode
\letmathspacing  \mathfractioncode \mathordinarycode
\letmathspacing  \mathradicalcode  \mathordinarycode
\letmathspacing  \mathmiddlecode   \mathopencode
\letmathspacing  \mathaccentcode   \mathordinarycode

\letmathatomrule \mathactivecode   \mathordinarycode
\letmathatomrule \mathvariablecode \mathordinarycode
\letmathatomrule \mathovercode     \mathordinarycode
\letmathatomrule \mathundercode    \mathordinarycode
\letmathatomrule \mathfractioncode \mathordinarycode
\letmathatomrule \mathradicalcode  \mathordinarycode
\letmathatomrule \mathmiddlecode   \mathopencode
\letmathatomrule \mathaccentcode   \mathordinarycode
\stoptyping

With \type {\resetmathspacing} we get an all|-|zero state but that might become
more refined in the future. What is not clear from the above is that there is
also an inheritance mechanism. The three special muskip registers are actually
shortcuts so that changing the register value is reflected in the spacing. When a
regular muskip value is (verbose or as register) that value is sort of frozen.
However, the \type {\inherited} prefix will turn references to registers and
constants into a delayed value: as with the predefined we now have a more dynamic
behavior which means that we can for instance use reserved muskip registers as we
can use the predefined. A bonus is that one can also use regular glue or
dimensions, just in case one wants the same spacing in all styles (a muskip
adapts to the size).

When you look at all of the above you might wonder how users are supposed to deal
with math spacing. The answer is that often they can just assume that \TEX\ does
the right thing. If something somehow doesn't feel right, looking at solutions by
others will probably lead a new user to just copy a trick, like injecting a \type
{\thinmuskip}. But it can be that atoms depend on the already applied (or not)
spacing, which in turn depends on values in the atom spacing matrix that probably
only a few users have seen. So, in the end it all boils down to trust in the
engine and one's eyesight combined with hopefully some consistency in adding
space directives and often with \TEX\ it is consistency that makes documents look
right. In \CONTEXT\ we have many more classes even if only a few characters fit in,
like differential, exponential and imaginary.

\stopsubject

\startsubject[title=Fractions again]

We now return to the fraction molecule. With the mechanisms at our disposal we
can change the fixed margins to more adaptive ones:

\starttyping
\inherited\setmathspacing \mathbinarycode   \mathfractioncode
    \allmathstyles \thickermuskip
\inherited\setmathspacing \mathfractioncode \mathbinarycode
    \allmathstyles \thickermuskip
\nulldelimiterspace\zeropoint
$x + \frac{1}{x+2} + x$
\stoptyping

Here \typ {\thickermuskip} is defined as \type {7mu plus 5mu} where the stretch
is the same as a \typ {\thickmuskip} and the width \type {2mu} more. We start out
with three variants, where the last two have \typ {\nulldelimiterspace} set to
\type {0pt} and the first one uses the \type {1.2pt}.

\definecolor[tred]  [r=1,a=1,t=.5]
\definecolor[tgreen][g=1,a=1,t=.5]
\definecolor[tblue] [b=1,a=1,t=.5]

\startlinecorrection
\scale[scale=4000]\bgroup\vbox\bgroup \forgetall
    \bgroup \tgreen \nulldelimiterspace=1.2pt $x + \frac{1}{x+2} + x$\egroup\par
    \bgroup \tred   \nulldelimiterspace=0.0pt $x + \frac{1}{x+2} + x$\egroup\par
    \bgroup \tblue  \nulldelimiterspace=0.0pt $x + \frac{1}{x+2} + x$\egroup\par
\egroup\egroup
\stoplinecorrection

When we now apply the new settings to the last one, and overlay them we get the
following output: the first and last case are rather similar which is why this
effort was started in the first place.

\startlinecorrection
\scale[scale=4000]\bgroup
    \startoverlay
        \bgroup
            \inherited\setmathspacing \mathbinarycode   \mathfractioncode \allmathstyles \thickmuskip
            \inherited\setmathspacing \mathfractioncode \mathbinarycode   \allmathstyles \thickmuskip
            \tgreen \nulldelimiterspace=1.2pt $x + \frac{1}{x+2} + x$
        \egroup
        \bgroup
            \inherited\setmathspacing \mathbinarycode   \mathfractioncode \allmathstyles \thickmuskip
            \inherited\setmathspacing \mathfractioncode \mathbinarycode   \allmathstyles \thickmuskip
            \tred \nulldelimiterspace=0.0pt $x + \frac{1}{x+2} + x$
        \egroup
        \bgroup
            \inherited\setmathspacing \mathbinarycode   \mathfractioncode \allmathstyles \thickermuskip
            \inherited\setmathspacing \mathfractioncode \mathbinarycode   \allmathstyles \thickermuskip
            \tblue \nulldelimiterspace=0.0pt $x + \frac{1}{x+2} + x$
        \egroup
    \stopoverlay
\egroup
\stoplinecorrection

Of course these changes are not upward compatible but as they are tiny they are
not that likely to change the number of lines in a paragraph. In display mode
changes in horizontal dimensions also have little effect.

\startsubject[title=Penalties]

An inline formula can be broken across lines, and for sure there are places where
you don't want to break or prefer to break. In \TEX\ line breaks can be
influenced by using penalties. At the outer level of an inline math formula, we
can have a specific penalty before and after a binary and|/|or relation. The
defaults are such that there are no penalties set, but most macro packages set
the so called \type {\relpenalty} and \type {\binoppenalty} (the \type {op} in
this name does not relate to the operator class) so a value between zero and
1000. In \LUATEX\ we also have \type{\pre} variants of these, so we have four
penalties that can be set, but that is not enough in our new approach.

These penalties are class bound and don't relate to styles, like atom spacing
does. That means that while atom spacing involves $64 \times 64 \times 8$
potential values, an amount that we can manage by using the discussed
inheritance. The inheritance takes less values because which store 4 style values
per class in one number. For penalties we only need to keep $64 \times 2$ in
mind, plus a range of inheritance numbers. Therefore it was decided to also
generalize penalties so that each class can have them. The magic commands are
shown with some useless examples:

\starttyping
\letmathparent \mathdigitcode
    \mathbincode   % pre penalty
    \mathbincode   % post penalty
    \mathdigitcode % options
    \mathdigitcode % reserved
\stoptyping

By default the penalties are on their own, like:

\starttyping
\letmathparent \mathdigitcode
  \mathdigitcode % pre penalty
  \mathdigitcode % post penalty
  \mathdigitcode % options
  \mathdigitcode % reserved
\stoptyping

The options and reserved parent mapping are not (yet) discussed here. Unless
values are assigned they are ignored.

\starttyping
\setmathprepenalty  \mathordcode 100
\setmathpostpenalty \mathordcode 600
\setmathprepenalty  \mathbincode 200
\setmathpostpenalty \mathbincode 700
\setmathprepenalty  \mathrelcode 300
\setmathpostpenalty \mathrelcode 800
\stoptyping

As with spacing, when there is no known value, the parent will be consulted. An unset
penalty has a value of 10000.

After discussing the implications of inline math crossing lines, Mikael and I
decided there can be two solutions. Both can of course be implemented in \LUA,
but on the other hand, they make good extensions, also because it sort of
standardized it. The first advanced control feature tweaks penalties:

\starttyping
\mathforwardpenalties  2  200 100
\mathbackwardpenalties 2  100  50
\stoptyping

This will add 200 and 100 to the first two math related penalties, and 100 and 50
to the last two (watch out: the 100 will be assigned to the last one found, the
50 to the one before it). As with all things penalty and line break related, you
need to have some awareness of how non|-|linear the badness calculation is as
well of the fact that the tolerance and stretch related parameters play a role
here.

The second tweak is setting \type {\maththreshold} to some value. When set to for
instance \type {40pt}, formulas that take less space than this will be wrapped in
a \type {\hbox} and thereby will never break across a page. \footnote {A future
version might inject severe penalties instead, time will learn.} Actually that
second tweak has a variant so we have three tweaks! Say that we have this sample
formula wrapped in some bogus text and repeat that snippet a lot of times:

\startbuffer[demo]
x xx xxx xxxx $1 + x$ x xx xxx xxxx
\stopbuffer

\typebuffer[demo]

Now look at the example on the next page. You will notice that the red and blue
text have different line breaks. This is because we have given the threshold some
stretch and shrink. The red text has a zero threshold so it doesn't do any magic
at all, while the second has this setup:

\startbuffer
\setupmathematics[threshold=medium]
\stopbuffer

\typebuffer

That setting set the threshold to \typ {4em plus 0.75em minus 0.50em} and when
the formula size exceeds the four quads the line break code will use the real
formula width but with the given stretch and shrink. Eventually the calculated
size will be used to repackage the formula. In the future we will also provide a
way to define slack more relative to the size and|/|or number of atoms.

\startpostponing
\startlinecorrection \small
\startoverlay
    {\setupmathematics[threshold=none]%
     \vbox\bgroup
        \darkred
        \dorecurse {40} {\getbuffer[demo]}
     \egroup}
    {\setupmathematics[threshold=medium]%
     \vbox\bgroup
        \darkblue
        \dorecurse {40} {\getbuffer[demo]}
     \egroup}
\stopoverlay
\stoplinecorrection
\stoppostponing

Another way to influence line breaks is to use the two inline math related
penalties that have been added at Mikael's suggestion:

\startbuffer \setupalign[verytolerant]
{\dorecurse{25}{test $\darkred   #1^{#1} + x_{#1}^{#1}$ test }\blank}
{\preinlinepenalty  500 \postinlinepenalty -500
 \dorecurse{25}{test $\darkgreen #1^{#1} + x_{#1}^{#1}$ test }\blank}
{\postinlinepenalty 500 \preinlinepenalty  -500
 \dorecurse{25}{test $\darkblue  #1^{#1} + x_{#1}^{#1}$ test }\blank}
\stopbuffer

\typebuffer

To get an example that shows the effect takes a bit of trial and error because
\TEX\ does a very good job in line breaking. This is why we've set the tolerance
and also use negative penalties.

In addition to the \type {\mathsurround} (kern) and \type {\mathsurroundskip}
(glue) parameters this is a property of the nodes that mark the beginning and end
of an inline math formula.

\blank \getbuffer \blank

\stopsubject

\startsubject[title=Flattening]

The traditional engine has some code for flattening math constructs that in the
end are just one character. So in the end, \type {\tilde {u}} and \type {\tilde
{uu}} become different objects even if both are in fact accents. In fact, when an
accent is constructed there is a special code path for single characters so that
script placement adapts to the shape of that character.

However because of interaction with primes, which themselves are sort of
superscripts and due to the somewhat weird way fonts provide them when it comes
to positioning and sizes, in \CONTEXT\ we already are fooling around a bit with
these characters. For understandable reasons of memory usage, complexity and
eightbitness primes are not a native \TEX\ thing but more something that is
handled at the macro level (although not in \MKIV\ and \LMTX).

In the end it was script placements on (widely) accented math characters that
made us introduce a dedicated \type {\Umathprime} primitive that adds a prime to
a math atom. It permits an uninterupted treatment of scripts while in the final
assembly of the molecule the prime, superscript, subscript and maybe even
prescripts that prime gets squeezed in. Because the concept of primes is missing
in \OPENTYPE\ math an additional font parameter \type {PrimeTopRaisePercent} has
been introduced as well as an \type {\Umathprimeraise} primitive. In retrospect I
should have done that earlier but one tends to stick to the original as much as
possible. However, at some point Mikael and I reached a state where we decided
that proper (clean) engine extensions make way more sense than struggling with
border cases and explaining users why things are so complicated.

The input \type {$ X \Uprimescript{'} ^2 _3 $} gives this:

\startlinecorrection
\startcombination[nx=4,distance=3em,inbetween={\blank[3*medium]}]
    {\switchtobodyfont [modern]\removeunwantedspaces\scale[s=5]{\strut$\showboxes\showglyphs X\Uprimescript{'}^2_3$}} {Latin Modern}
    {\switchtobodyfont[cambria]\removeunwantedspaces\scale[s=5]{\strut$\showboxes\showglyphs X\Uprimescript{'}^2_3$}} {Cambria}
    {\switchtobodyfont[pagella]\removeunwantedspaces\scale[s=5]{\strut$\showboxes\showglyphs X\Uprimescript{'}^2_3$}} {Pagella}
    {\switchtobodyfont [dejavu]\removeunwantedspaces\scale[s=5]{\strut$\showboxes\showglyphs X\Uprimescript{'}^2_3$}} {Dejavu}
\stopcombination
\stoplinecorrection

With \type {\tracingmath = 1} this nicely traces as:

\starttyping
> \inlinemath=
\noad[ord][...]
.\nucleus
..\mathchar[ord] family "0, character "58
.\superscript
..\mathchar[dig] family "0, character "32
.\subscript
..\mathchar[dig] family "0, character "32
.\primescript
..\mathchar[ord] family "0, character "27
\stoptyping

Of course this feature can also be used for other prime like ornaments and who
knows how it will evolve over time.

You can influence the positioning with \type {\Umathprimesupshift} which adds
some kern between a prime and superscript. The \type {\Umathextraprimeshift}
moves a prime up. The \type {\Umathprimeraise} is a font parameter that defaults
to 25 which means a raise of 25\percent of the height. These are all (still)
experimental parameters.

\stopsubject

\startsubject[title=Fences]

Fences can be good for headaches. Because the math that I (or actually my
colleague) deal with is mostly school math encoded in presentation \MATHML\ (sort
or predictable) or some form of sequential \ASCII\ based input (often rather
messy and therefore unpredictable due to ambiguity) fences are a pain. A \TEX ie
can make sure that left and right fences are matched. A \TEX ie also knows when
something is an inline parenthesis or when a more high level structure is needed,
for instance when parentheses have to scale with what they wrap. In that case the
\type {\left} and \type {\right} mechanism is used. In arbitrary input missing
one of those is fatal. Therefore, handling of fences in \CONTEXT\ is one of the
more complex sub mechanisms: we not only need to scale when needed, but also
catch asymmetrical usage.

A side effect of the encapsulating fencing construct is that it wraps the content
in a so called inner (as in \type {\mathinner}) which means that we get a box,
and it is a well known property of boxes that they don't break across lines. With
respect to fences, a way out is to not really fence content, but do something
like this:

\starttyping
\left(\strut\right. x + 1 \left.\strut\right)
\stoptyping

and hope for the best. Both pairs are coupled in the sense that their sizes will
match and the strut is what determines the size. So, as long as there is a proper
match of struts all is well, but it is definitely a decent hack. The drawback is
in the size of the strut: if a formula needs a higher one, larger struts have to
be used. This is why in plain \TEX\ we have these commands:

\starttyping[style=\small\tt]
\def\bigl {\mathopen \big } \def\bigm {\mathrel\big } \def\bigr {\mathclose\big }
\def\Bigl {\mathopen \Big } \def\Bigm {\mathrel\Big } \def\Bigr {\mathclose\Big }
\def\biggl{\mathopen \bigg} \def\biggm{\mathrel\bigg} \def\biggr{\mathclose\bigg}
\def\Biggl{\mathopen \Bigg} \def\Biggm{\mathrel\Bigg} \def\Biggr{\mathclose\Bigg}

\def\big #1{{\hbox{$\left#1\vbox to  8.5pt{}\right.\nomathspacing$}}}
\def\Big #1{{\hbox{$\left#1\vbox to 11.5pt{}\right.\nomathspacing$}}}
\def\bigg#1{{\hbox{$\left#1\vbox to 14.5pt{}\right.\nomathspacing$}}}
\def\Bigg#1{{\hbox{$\left#1\vbox to 17.5pt{}\right.\nomathspacing$}}}

\def\nomathspacing{\nulldelimiterspace0pt\mathsurround0pt} % renamed
\stoptyping

The middle is kind of interesting because it has relation properties, while the
\type {\middle} introduced in \ETEX\ got open properties, but we leave that
aside.

In \CONTEXT\ we have plenty of alternatives, including these commands, but they
are defined differently. For instance they adapt to the font size. The hard coded
point sizes in the plain \TEX\ code relates to the font and steps available in
there (either by next larger or by extensible). The values thereby need to be
adapted to the chosen body font as well as the body font size. In \MKIV\ and even
better in \LMTX\ we can actually consult the font and get more specific sizes.

But, this section is not about how to get these fixed sizes. Actually, the need
to choose explicitly is not what we want, especially because \TEX\ can size
delimiters so well. So, take this code snippet:

\startbuffer
$ x = \left( \dorecurse{40}{\frac{x}{x+#1} +} x \right) $
\stopbuffer

\typebuffer

% \dostepwiserecurse{0}{25}{1}{
% \begingroup \showmakeup[mathglue] \showglyphs
% \advance\hsize-#1pt\relax \inleftmargin{#1pt}%
% $ x = \left( \dorecurse{20}{\frac{x}{x+##1} +} x \right) $
% \blank \endgroup
% }
When we typeset this inline, as in \inlinebuffer, we get nicely scaled fences but
in a way that permits line breaks. The reason is that the engine has been
extended with a \type {fenced} class so that we can recognize later on,
when \TEX\ comes to injecting spaces and penalties, that we need to unpack the
construct. It is another beneficial side effect of the generalization.

The Plain \TEX\ code can be used to illustrate some of what we discussed before
about fractions. In the next code we use excessive delimiter spacing:

\starttyping
\def\Bigg#1{%  watch the wrapping in a box
  {%
    \hbox {%
        $\normalleft#1\vbox to 17.5pt{}\normalright.\nomathspacing$%
    }%
  }%
}

\nulldelimiterspace0pt
\def\nomathspacing{\nulldelimiterspace0pt\mathsurround0pt}

$\Bigg( 1 + x\Bigg) \quad \Bigg( \frac{1}{x}\Bigg)$\par

\nulldelimiterspace10pt
\def\nomathspacing{\nulldelimiterspace0pt\mathsurround0pt}

$\Bigg( 1 + x\Bigg) \quad \Bigg( \frac{1}{x}\Bigg)$\par

\nulldelimiterspace10pt
\def\nomathspacing{\mathsurround0pt}

$\Bigg( 1 + x\Bigg) \quad \Bigg( \frac{1}{x}\Bigg)$\par
\stoptyping

This renders as follows. We explicitly set \type {\nulldelimiterspace} to values
because in \CONTEXT\ it is now zero by default.

\startlinecorrection
    \pushoverloadmode
    \def\Bigg#1{{\hbox{$\normalleft#1\vbox to 17.5pt{}\normalright.\nomathspacing$}}}
    \popoverloadmode
    \startcombination[nx=3,ny=1,distance=3em]
        {\showboxes
         \nulldelimiterspace0pt
         \def\nomathspacing{\nulldelimiterspace0pt\mathsurround0pt}
         $\Bigg( 1 + x\Bigg) \quad \Bigg( \frac{1}{x}\Bigg)$}
        {\tttf 0pt with reset at end}
        {\showboxes
         \nulldelimiterspace10pt
         \def\nomathspacing{\nulldelimiterspace0pt\mathsurround0pt}
         $\Bigg( 1 + x\Bigg) \quad \Bigg( \frac{1}{x}\Bigg)$}
        {\tttf 10pt with reset at end}
        {\showboxes
         \nulldelimiterspace10pt
         \def\nomathspacing{\mathsurround0pt}
         $\Bigg( 1 + x\Bigg) \quad \Bigg( \frac{1}{x}\Bigg)$}
        {\tttf 10pt without reset at end}
    \stopcombination
\stoplinecorrection

\stopsubject

\startsubject[title=Radicals]

In traditional \TEX\ a radical with degree is defined as macro. That macro does
some measurements and typesets the result in four sizes for a choice. The macro
typesets the degree in a box that contains the degree as formula. There is a less
guesswork going on than with respect to how the radical symbol is shaped but as
we're talking plain \TEX\ here it works out okay because the default font is well
known.

Radicals are a nice example of a two dimensional \quote {extender} but only the
vertical dimension uses the extension mechanism, which itself operates either
horizontally or vertically, although in principle it could go both ways. The
horizontal extension is a rule and the fact that the shape is below the baseline
(as are other large symbols) will make the rule connect well: the radical shape
sticks out a little, so one can think of the height reflecting the rule height.
\footnote {When you zoom in you will notice that this is not always optimal
because of the way the slope touched the rule.} In \OPENTYPE\ fonts there is a
parameter and in \LUATEX\ we use the default rule thickness for traditional
fonts, which is correct for Latin Modern. There are more places in the fonts
where the design relates to this thickness, for instance fraction rules are
supposed to match the minus, but this is a bit erratic if you compare fonts. This
is one of the corrections we apply in the goodie files.

In \OPENTYPE\ the specification of the radical also includes spacing properties
of the degree and that is why we have a primitive in \LUATEX\ that also handles
the degree. It is what we used in \CONTEXT\ \MKIV. But \unknown\ we actually end
up with a situation that compares to the already discussed fraction: there is
space added before a radical when there is a degree. However, because we now have
a radical atom class, we can avoid using that one and use the new pairwise
spacing. Some fuzzy spacing logic in the engine could therefore be removed and we
assume that \type {\Umathradicaldegreebefore} is zero. For the record: the \type
{\Umathradicaldegreeafter} sort of tells how much space there is above the low
part of the root, which means that we can compensate for multi|-|digit degrees.

Zeroing a parameter is something that relates to a font which means that it has
to happen for each math font which in turn can mean a family|-|style combination. In
order to avoid that complication (or better: to avoid tracing clutter) we have a
way to disable a parameter:

\startbuffer
\ruledhbox{$x + \sqrt[123]{b}^1_2$}
\ruledhbox{$x + \sqrt[12] {b}^1_2$}
\ruledhbox{$x + \sqrt[1]  {b}^1_2$}
\ruledhbox{$x + \sqrt     {b}^1_2$}
\stopbuffer

\typebuffer

\startlinecorrection
\startcombination[1*4]
    {\switchtobodyfont[modern]\scale[height=10mm]{\showglyphs\setmathignore\Umathradicaldegreebefore0\getbuffer}}{}
    {\type {\setmathignore \Umathradicaldegreebefore 0}}{}
    {\switchtobodyfont[modern]\scale[height=10mm]{\showglyphs\setmathignore\Umathradicaldegreebefore1\getbuffer}}{}
    {\type {\setmathignore \Umathradicaldegreebefore 1}}{Latin Modern}
\stopcombination
\stoplinecorrection

One problem with these spacing parameters is that they are inconsistent across
fonts. The Latin Modern has a rather large space before the degree, while Cambria
and Pagella have little. That means that when you prototype a mechanism the
chosen solution can look great but not so much when at some point you use another
font.

\startlinecorrection
\startcombination[1*4]
    {\switchtobodyfont[pagella]\scale[height=10mm]{\showglyphs\setmathignore\Umathradicaldegreebefore0\getbuffer}}{}
    {\type {\setmathignore \Umathradicaldegreebefore 0}}{}
    {\switchtobodyfont[pagella]\scale[height=10mm]{\showglyphs\setmathignore\Umathradicaldegreebefore1\getbuffer}}{}
    {\type {\setmathignore \Umathradicaldegreebefore 1}}{Cambria}
\stopcombination
\stoplinecorrection

\stopsubject

\startsubject[title=More fences]

One of the reasons why the \MKII\ and \MKIV\ fence related mechanism is somewhat
complex is that we want a clean solution for filtering fences like parenthesis by
size, something that in the traditional happens via a fake fence pair that
encapsulates a strut of a certain size. In \LMTX\ we use the same approach but
have made the sequence more configurable. In practice that means that the values
1 up to 4 are just that but for some fonts we use the sequence \type {1 3 5 7}.
There was no need to adapt the engine as it already worked quite well.

\stopsubject

\startsubject[title=Integrals]

The Latin Modern fonts have only one size of big operators and one reason can be
that there is no need for more. Another reason can be that there was just no
space in the font. However, an \OPENTYPE\ font has plenty slots available and the
reference font Cambria has integral signs in sizes as well as extensibles.

In \LUATEX\ we already have generic vertical extensibles but that only works well
with specified sizes. And, cheating with delimiters has the side effect that we
get the wrong spacing. In \LUAMETATEX\ however we have ways to adapt the size to
what came or what comes. In fact, it is a mechanism that is available for any atom
that we support. However, it doesn't play well with script and this whole \type {\limits}
and \type {\nolimits} is a bit clumsy so Mikael and I decided that different route had
to be followed. For adaptive large operators we provide this interface:

\startbuffer[sample-1]
$ x + \integral [color=darkred,top={t},bottom={b}] {\frac{1}{x}} = 10 $
\stopbuffer

\startbuffer[sample-2]
$ x + \startintegral [color=darkblue,top={t},bottom={b}]
    \frac{1}{x}
\stopintegral = 10 $
\stopbuffer

\startbuffer[sample-3]
$ x + \startintegral [color=darkgreen,top={t},bottom={b},method=vertical]
    \frac{1}{x}
\stopintegral= 10 $
\stopbuffer

\typebuffer [sample-1,sample-2,sample-3]

This text is not about the user interface so we won't discuss how to define additional
large operators using one|-|liners.

\startlinecorrection
\startcombination[nx=3,ny=1,distance=2em]
    {\scale[s=2]{\getbuffer[sample-1]}} {}
    {\scale[s=2]{\getbuffer[sample-2]}} {}
    {\scale[s=2]{\getbuffer[sample-3]}} {}
\stopcombination
\stoplinecorrection

The low level \LUAMETATEX\ implementation handles this input:

\starttyping
\Uoperator          \Udelimiter "0 \fam "222B {top} {bottom} {...}
\Uoperator   limits \Udelimiter "0 \fam "222B {top} {bottom} {...}
\Uoperator nolimits \Udelimiter "0 \fam "222B {top} {bottom} {...}
\stoptyping

plus the usual keywords that fenced accept, because after all, this is just a
special case of fencing.

Currently these special left operators are implemented as a special case of
fences because that mechanism does the scaling. It means that we need a (bogus)
right fence, or need to brace the content (basically create an atom). When no
right fence is found one is added automatically. Because there is no real
fencing, right fences are removed when processing takes place. When you specify a
\type {class} that one will be used for the left and right spacing, otherwise we
have open|/|close spacing.

\stopsubject

\startsubject[title=Going details]

When the next feature was explored Mikael tagged it as math micro typography and
the reason is that you need not only to set up the engine for it but also need to
be aware of this kind of spacing. Because we wanted to get rid of this script spacing
that the font imposes we configured \CONTEXT\ with:

\starttyping
\setmathignore\Umathspacebeforescript\plusone
\setmathignore\Umathspaceafterscript \plusone
\stoptyping

This basically nils all these tiny spaces. But the latest configuration has this
instead:

\starttyping
% \setmathignore \Umathspacebeforescript\zerocount % default
% \setmathignore \Umathspaceafterscript \zerocount % default

\mathslackmode \plusone

\setmathoptions\mathopcode      \plusthree
\setmathoptions\mathbinarycode  \plusthree
\setmathoptions\mathrelationcode\plusthree
\setmathoptions\mathopencode    \plusthree
\setmathoptions\mathclosecode   \plusthree
\setmathoptions\mathpunctcode   \plusthree
\stoptyping

This tells the engine to convert these spaces into what we call slack: disposable
kerns at the edges. But it also converts these kerns into a glue component when
possible. As with all these extensions it complicates the machinery but users
will never see that. Now, the last six lines do the magic that made us return to
honoring the spaces: we can tell the engine to ignore this slack when there are
specific classes at the edges. These options are a bitset and \type {1} means
\quotation {no slack left} and \type {2} means \quotation {no slack right} so
\type {3} sets both.

\startbuffer
\def\TestSlack#1%
  {\vbox\bgroup
      \mathslackmode\zerocount
      \hbox\bgroup
         \setmathignore\Umathspacebeforescript\zerocount
         \setmathignore\Umathspaceafterscript \zerocount
         #1
      \egroup
      \vskip-.9\lineheight
      \hbox\bgroup\red
        \setmathignore\Umathspacebeforescript\plusone
        \setmathignore\Umathspaceafterscript \plusone
         #1
      \egroup
   \egroup}

\startcombination[nx=3]
    {\showglyphs\TestSlack{$f^2 >      $}} {}
    {\showglyphs\TestSlack{$    > f^^^2$}} {}
    {\showglyphs\TestSlack{$f^2 > f^^^2$}} {}
\stopcombination
\stopbuffer

\typebuffer

\startlinecorrection
\scale[width=\textwidth]{\getbuffer}
\stoplinecorrection

Because this overall removal of slack is not granular enough a while later we
introduced a way to set this per class, as is demonstrated in the following
example.

\startbuffer
\def\TestSlack#1%
  {\vbox\bgroup
      \mathslackmode\plusone
      \hbox\bgroup\red
        \setmathignore\Umathspacebeforescript\zerocount
        \setmathignore\Umathspaceafterscript \zerocount
        #1
      \egroup
      \vskip-.9\lineheight
      \hbox\bgroup\green
        \setmathoptions\mathrelationcode \zerocount
        #1
      \egroup
      \vskip-.9\lineheight
      \hbox\bgroup\blue
        \setmathoptions\mathrelationcode \plusthree
        #1
      \egroup
   \egroup}

\startcombination[nx=3]
    {\showglyphs\TestSlack{$f^2 >      $}} {}
    {\showglyphs\TestSlack{$    > f^^^2$}} {}
    {\showglyphs\TestSlack{$f^2 > f^^^2$}} {}
\stopcombination
\stopbuffer

\typebuffer

\startlinecorrection
\scale[width=\textwidth]{\getbuffer}
\stoplinecorrection

Of course we need to experiment a lot with real documents and it might take a
while before all this is stable (in the engine and in \CONTEXT). And as we don't
need to conform to the decades old golden \TEX\ math standards we have some
degrees of freedom in this: for Mikael and me it is pretty much a visual thing
where we look closely at large samples. Of course in practice details get lost
when we print at 10 point but that doesn't mean we can't provide the best
experience. \footnote {Whenever I look at (my) old (math) school books I realize
that Don Knuth had very good reasons to come up with \TEX\ and, it being hard to
beat, \TEX\ still sets the standard!}

As we mention class specific options, we also need to mention the special case
where we have for instance simple formulas like single atoms (for instance
digits) are preceded by a sign (binary). These special spacing cases are handled
by a lookahead flag that can be set \typ {\setmathoptions <class>}, like the
slack flags. More options might become available in due time. When set the
lookahead will check for the automatically injected end class atom and use that
for spacing when found. The mentioned lookahead is one of the hard coded
heuristics in the traditional engine but here we need to explicitly configure it.

\stopsubject

\startsubject[title=Ghosts]

As plain \TEX\ has macros like \type {\vphantom} you also find them in macro
packages that came later. These create a boxes that have their content removed
after the dimensions are set. They take space and are invisible but there's also
nothing there.

A variant in the upgraded math machinery are ghosts: these are visible in the
sense that they show up but ignored when it comes to spacing. Here is an example.
The option bit set here tells the engine that we ghost at the right, so we have
ghosts around the relation (it controls where the spacing ends up).

\startbuffer
$
  x
  \mathatom class \mathghostcode                   {!!}
  >
  \mathatom class \mathghostcode options "00000020 {!!}
  1
  \quad
  x
  \mathatom class \mathghostcode                   {\hbox{\smallinfofont ord}}
  >
  \mathatom class \mathghostcode options "00000020 {\hbox{\smallinfofont dig}}
  1
$
\stopbuffer

\typebuffer

You never know when this comes in handy but it fits in the new, more granular
approach to spacing. The code above shows that it's just a class, this time with
number \number\mathghostcode.

\startlinecorrection
    \scale[width=\textwidth]{\showglyphs\showmakeup[mathglue]\getbuffer}
\stoplinecorrection

\stopsubject

\startsubject[title=Struts]

In order to get consistent spacing the \CONTEXT\ macro package makes extensive
use of struts in text mode as well as math mode. The normal way to implement that is
either an empty box or a zero width rule, both with a specifically set height
and depth. In \CONTEXT\ \MKII\ and \MKIV\ (and for a long time in \LMTX\ too) they
were rules so that we could visualize them: they get some width and kerns
around them to compensate for that.

In order to not let them interfere with spacing we could wrap them into a ghost
atom but it is kind of ugly. Anyway, before we had these ghost atoms an
alternative to struts was already implemented: a special kind of rule. The reason is
that I wanted a cleaner and more predictable way to adapt struts to the math style
uses and sometimes predicting that is fragile. What we want is a delayed assignment of
dimensions.

We have two solutions. The first one uses two math parameters that themselves
adapt to the style, as do other parameters: \type {\Umathruleheight} and \type
{\Umathruledepth}. The other solution relates a font (or family) and character
with the strut rule which is then used as measure for the height and depth. Just
for the record: this also works in text mode, which is why a recent \LMTX\ also
does use that for struts now. The optional visualization is just part of the
regular visualization mechanism in \CONTEXT\ which already had provisions for
struts. A side effect of this is that the rule primitives now accept three more
keywords: \type {font}, \type {fam} and \type {char}, in addition to the already
present traditional ones \type {width}, \type {height} and \type {depth}, the
(backend) margin ones \type {left} (or \type {top}) and \type {right} (or \type
{bottom}) options, as well as \type {xoffset} and \type {yoffset}). The command
that creates a rule with subtype \type {strut} is simply \type {\srule}. Because
struts are rather macro package specific I leave it to this.

One positive side effect is that we could simplify the \CONTEXT\ fraction mechanism
a bit. Over time control over the (font driven) gaps was introduced but that is
not really needed because we zero the gaps anyway. There was also a tolerance
mechanism which again was not used. However, for skewed fractions we do use the new
tolerance mechanism as well as gap control.

\stopsubject

\startsubject[title=Atoms]

Now that we have generic atoms (\type {\mathatom}) another, sometimes confusing aspect
of the math parsing can be solved. Take this:

\starttyping
\def\MyBin{\mathbin{\tt mybin}}
$ x ^ \MyBin _ \MyBin $
\stoptyping

The parser just doesn't like that which means that one has to use

\starttyping
\def\MyBin{\mathbin{\tt mybin}}
$ x ^ {\MyBin} _ {\MyBin} $
\stoptyping

or:

\starttyping
\def\MyBin{{\mathbin{\tt mybin}}}
$ x ^ \MyBin _ \MyBin $
\stoptyping

But the later has side effects: it creates a list that can influence spacing. It
is for that reason that we do accept atoms where they were not accepted before.
Of course that itself can have side effects but at least we don't get an error
message. It fits well into the additional (user) classes model. And, given that
in \CONTEXT\ the \type {\frac} command is actually wrapped as \type {\mathfrac}
the next will work too:

\starttyping
$ x^\frac{1}{2} + x^{\frac{1}{2}} $
\stoptyping

but in practice you should probably use the braced version here for clarity.

\stopsubject

\startsubject[title=The \type {vcenter} primitive]

Traditionally this primitive is bound to math but it had already been adapted to also
work in text mode. As part of the upgrade of math we can now also pass all the options
that normal boxed take and we can also cheat with the axis. Here is an example:

\startbuffer
\def\TEST{\hbox\bgroup
    \darkred   \vrule width  2pt height 4pt
    \darkgreen \vrule width 10pt depth  2pt
\egroup}
$
    x  - \mathatom \mathvcentercode {!!!} -
    + \ruledvcenter                           {\TEST}
    + \ruledvcenter                           {\TEST}
    + \ruledvcenter axis 1                    {\TEST}
    + \ruledvcenter xoffset  2pt yoffset  2pt {\TEST}
    + \ruledvcenter xoffset -2pt yoffset -2pt {\TEST}
    + x
$
\stopbuffer

\typebuffer

There was already a vcenter class available before we did this:

\startlinecorrection
    \scale[width=\textwidth]{\showglyphs\showmakeup[mathglue]\getbuffer}
\stoplinecorrection

\stopsubject

\startsubject[title=Text]

Sometimes you want text in math, for instance \type {sin} or \type {cos} but
text in math is not really text:

\startbuffer
$ \setmathspacing\mathordinarycode\mathordinarycode\textstyle 10mu fin(x) $
\stopbuffer

\typebuffer

The result demonstrates that what looks like a word actually becomes three
math atoms:

\startlinecorrection
    \scale[width=\textwidth]{\showglyphs\showmakeup[mathglue]\getbuffer}
\stoplinecorrection

Okay, so how about then wrapping it into a text box:

\startbuffer
$
    \setmathspacing\mathordinarycode\mathordinarycode\textstyle 10mu
    fin(x) \quad \hbox{fin}(x)
$
\stopbuffer

\typebuffer

Here we get:

\startlinecorrection
    \scale[width=\textwidth]{\showglyphs\showmakeup[mathglue]\getbuffer}
\stoplinecorrection

We even get a ligature which might be an indication that we're not using a math
font which indeed is the case: the box is typeset in the regular text font.

\startbuffer
\def\Test#1%
  {\setmathspacing\mathordinarycode\mathordinarycode\textstyle 5mu
   $\showglyphs
   #1% style
   {\tf fin} \quad
   \hbox{fin} \quad
   \mathatom class \mathordinarycode textfont {fin}
   \mathatom class \mathordinarycode textfont {\tf fin}
   \mathatom class \mathordinarycode textfont {\hbox{fin}}
   \mathatom class \mathordinarycode mathfont {\hbox{fin}}
   $}
\stopbuffer

\typebuffer \getbuffer

When we feed this macro with the \type {\textstyle}, \type {\scriptstyle} and \type
{\scriptscriptstyle} we get:

\startlinecorrection
    \startcombination[1*3]
        {\scale[scale=3000]{\Test\textstyle        }} {text}
        {\scale[scale=3000]{\Test\scriptstyle      }} {script}
        {\scale[scale=3000]{\Test\scriptscriptstyle}} {scriptscript}
    \stopcombination
\stoplinecorrection

Here you see a new atom option action: \type {textfont} which does as much as
setting the font to the current family font and the size to the one used in the
style. For the record: you only get ligatures when they are configured and
provided by the font (and as math is a script itself it is unlikely to work).
\footnote {The existing mechanisms in \CONTEXT\ already dealt with this but it is
nevertheless nice to have it as a clean engine feature.}

\stopsubject

\startsubject[title=Tracing]

I won't discuss the tracing features in \CONTEXT\ here but for sure the
visualizer helps a lot in figuring out all this. In \LUAMETATEX\ we carry a bit
more information with the resulting nodes so we can provide more details, for
instance about the applied spacing and penalties. Some is shown in the examples.
A more recent tracing feature is this:

\starttyping
\tracingmath   1
\tracingonline 1
$
    \mathord (
    \mathord {(}
    \mathord \Udelimiter"4 0 `(
    \Udelimiter"4 0 `(
$
\stoptyping

That gives us on the console (the dots represent detailed attribute info that we
omit here):

\starttyping
7:3: > \inlinemath=
7:3: \noad[ord][...]
7:3: .\nucleus
7:3: ..\mathchar[open] family "0, character "28
7:3: \noad[ord][...]
7:3: .\nucleus
7:3: ..\mathlist
7:3: ...\noad[open][...]
7:3: ....\nucleus
7:3: .....\mathchar[open] family "0, character "28
7:3: \noad[ord][...]
7:3: .\nucleus
7:3: ..\mathchar[open] family "0, character "28
7:3: \noad[open][...]
7:3: .\nucleus
7:3: ..\mathchar[open] family "0, character "28
\stoptyping

A tracing level of 2 will spit out some information about applied spacing and
penalties between atoms (when set) and level 3 will show the math list before the
first and second pass (a mix of nodes and noads) we well as the result (nodes) plus
return some details about rules, spacing and penalties applied.

\stopsubject

\startsubject[title=Is there more?]

The engine already provides the option to circumvent the side effect of a change
in a parameter acting sort of global: the last value given is also the one that a
second pass starts with. The \type {\frozen} prefix will turn settings into local
ones but that's another (already old) topic. There are many such improvements and
options not mentioned here but you can find them mentioned and explained in older
development stories. A lot has been around for a while but not been applied in
\CONTEXT\ yet.

When \TEX\ was written one important property (likely related to memory
consumption) is that node lists have only forward pointers. That means that the
state of preceding material has to be kept track of: there is no going (or
looking) back. In \LUATEX\ we have double linked lists so in principle we can try
to be more clever but so far I decided not to touch the math machinery in that
way. But who knows what comes next.

\stopsubject

\startsubject[title=Those italics]

Right from the start of \LUATEX\ it became clear that the fact that \TEX\ assumes
the actual width of glyphs to be incremented by the italic correction that then
selectively is removed has been an issue. It made for successive attempts to
improve spacing in \CONTEXT\ by providing pseudo features. But, when we moved
from assembled \UNICODE\ math fonts to \quote {real} ones that became messy: what
trick to apply when and even worse where? In the end there are only a very few
shapes that actually are affected in the sense that when we don't deal with them
it looks bad. It also happens that one of those shapes is the italic \quote {f},
a letter that is used frequently in math. It might even be safe to say that the
simple fact that the math italic f has this excessively wrong width and thereby
pretty large italic correction is the cause of many problems.

In the \LMTX\ approach Mikael and I settled on patching shapes in the so called
font goodie files, aka \type {lfg} files and only a handful of entries needed a
treatment. This makes a good case for removing the traditional font code path
from \LUAMETATEX.

\startbuffer
   \dontleavehmode {\tt\fontclass}:
    \start
        \showglyphs \setupinterlinespace[1.2]
        \dostepwiserecurse{`a}{`z}{1}{$\Uchar#1^1_2$ }
        \dostepwiserecurse{`a}{`z}{1}{$\bi\Uchar#1^1_2$ }
        \par
    \stop
\stopbuffer

\start
    \switchtobodyfont[modern]  \getbuffer\blank
    \switchtobodyfont[cambria] \getbuffer\blank
    \switchtobodyfont[pagella] \getbuffer\blank
    \switchtobodyfont[termes]  \getbuffer\blank
    \switchtobodyfont[bonum]   \getbuffer\blank
\stop

One of the other very sloped symbol is the integral, although most fonts have
them more upright than tex has. Of course there are many variants of these
integrals in a math font. Here we also have some font parameters that we can
tune, which is what we do.

\stopsubject

\startsubject[title=Accents]

Accents are common in languages other than English and it's English that \TEX\
was made for. Although the seven bit variant became eight bit handling accents
never was sophisticated and one of the main reasons is of course that one could
use pre|-|built composed characters. The \OPENTYPE\ format brought proper
anchoring (aka marks) to font formats and when \LUATEX\ deals with text those
kick in. In \OPENTYPE\ math however, anchoring is kind of limited to the top
position only. Because the \TEXGYRE\ fonts are based on traditional \TEX\ fonts,
their accents have not become better suited.

\startbuffer
$ \hat{x} \enspace \widehat{x} \enspace \widehat{xx} \enspace \widehat{xxx}
  \enspace \hat{f} \enspace \widehat{f} $
\stopbuffer

\typebuffer

When looking at examples you need to be aware of the fact hat fonts can have been
adapted in the goodie files. \footnote {Extreme examples can be found for Lucida
Bright where we not only have to fix the extensible parts of horizontal braces
but also have to provide horizontal brackets.} So, for instance bounding boxes
and such can differ from the original. Anyway, the previous code in Cambria looks
as follows.

\startlinecorrection
\scale[height=18mm]{\showglyphs\switchtobodyfont[cambria]\inlinebuffer}
\stoplinecorrection

With Latin Modern we get:

\startlinecorrection
\scale[height=18mm]{\showglyphs\switchtobodyfont[modern]\inlinebuffer}
\stoplinecorrection

And Dejavu comes out as:

\startlinecorrection
\scale[height=18mm]{\showglyphs\switchtobodyfont[dejavu]\inlinebuffer}
\stoplinecorrection

As you can see there are some differences. In for instance Latin Modern the shape
of the hat and smallest wide hat are different and the first wide one has zero
dimensions combined with a negative anchor. When an accented character is
followed by a superscript or prime the italic correction of the base kicks in but
that cannot be enough to not let this small wide hat overflow into the script. We
could compensate for it but then we need to know the dimensions. Of course we can
consult the bounding box but it makes no sense to let heuristics enter the
machinery here while we're in the process generalization. One option is to have
two extra parameters that can be used when the width of the accent comes close to
the width of the base (we then assume that zero accent width means that it has
base width) we add an additional kern. In the end we settled for a (semi automatic)
correction option in the goodie files.

There are actually three categories of extensible accents to consider: those that
resemble the ones used in text (like tildes and hats), those wrapping something
(like braces and bracket but also arrows) and rules (that in traditional \TEX\
indeed are rules). In \CONTEXT\ we have different interfaces for each of these
in order to have a more extensive control. The text related ones are the
simplest and closest to what the engine supports out of the box but even there we
use tweaked glyphs to get better spacing because (of course) fonts have different
and inconsistent spacing in the boundingbox above and below the real shape. This
is again some tweak that we moved from being {\em automatic} to being {\em under
goodie file control}. But this is all too \CONTEXT\ specific to discuss here in
more detail.

\stopsubject

\startsubject[title=Decision time]

After lots of tests Mikael and I came to the conclusion that we're facing the
following situation. When typesetting math most single characters are italic and
we already knew from the start of the \LUATEX\ project that the italics shapes
are problematic when it comes to typesetting math. But it looks like even some
upright characters can have italic correction: in TexGyreBonum for instance the
bold upright \type {f} has italic correction, probably because it then can
(somehow) kern with a following \type {i}. It anyhow assumes no italic correction
to be applied between these characters.

In the end the mixed math font model model got more and more stressed so one
decision was to simply assume fonts to be used that are either Cambria like
\OPENTYPE, or mostly traditional in metrics, or a hybrid of both. It then made
more sense to change the engine control options that we have into ones that
simply enable certain code paths, independent of the fact if a font is \OPENTYPE\
or not. It then become a bit \quotation {crap in, crap out}, but because we
already tweak fonts in the goodie files it's quite okay. Some fonts have bad
metrics anyway or miss characters and it makes no sense to support abandoned
fonts either. Also, when a traditional font is assembled one can set up the
engine with different flags and we can deal with it as we wish. In the end it is
all up to the macro package to configure things right, which is what we tried to
do for months when rooting out all the artifacts that fonts bring. \footnote {In
previous versions one could configure this per font but that has been dropped.}

That said, the reason why some (fuzzy) mixed model works out okay (also in
\LUATEX) is that proper \OPENTYPE\ fonts use staircase kerns instead of italic
correction. They also have no ligatures and kerns. We also suspect that not that
much attention is paid to the rendering. It's a bit like these \quotation {How
many f's do you count in this sentence?} tests where people tend to overlook
\type {of}, \type {if} and similar short words. Mathematicians loves \type {f}'s
but probably also overlook the occasionally weird spacing and kerning.

A side effect is that mixing \OPENTYPE\ and traditional fonts is also no longer
assumed which in turn made a few (newly introduced) state variables obsolete. Once
everything is stable (including extensions discussed before) some further cleanup
can happen. Another side effect is that one needs to tell the engine what to apply
and where, like this:

\starttyping
\mathfontcontrol\numexpr \zerocount
   +\overrulemathcontrolcode
   +\underrulemathcontrolcode
   +\fractionrulemathcontrolcode
   +\radicalrulemathcontrolcode
   +\accentskewhalfmathcontrolcode
   +\accentskewapplymathcontrolcode
 % + checkligatureandkernmathcontrolcode
   +\applyverticalitalickernmathcontrolcode
   +\applyordinaryitalickernmathcontrolcode
   +\staircasekernmathcontrolcode
 % +\applycharitalickernmathcontrolcode
 % +\reboxcharitalickernmathcontrolcode
   +\applyboxeditalickernmathcontrolcode
   +\applytextitalickernmathcontrolcode
   +\checktextitalickernmathcontrolcode
 % +\checkspaceitalickernmathcontrolcode
   +\applyscriptitalickernmathcontrolcode
   +\italicshapekernmathcontrolcode
\relax
\stoptyping

There might be more control options (also for tracing purposes) and some of the
symbolic (\CONTEXT) names might change for the better. As usual it will take some
years before all is stable but because most users use the latest greatest version
it will be tested well.

After this was decided and effective I also decided to drop the mapping from
traditional font parameters to the \OPENTYPE\ derives engine ones: we now assume
that the latter ones are set. After all, we already did that in \CONTEXT\ for the
virtual assemblies that we started out with in the beginning of \LUATEX\ and
\MKIV.

\stopsubject

\startsubject[title=Dirty tricks]

Once you start playing with edge cases you also start wondering if some otherwise
complex things can be done easier. The next macro brings together a couple of
features discussed in previous sections. It also uses two state variables:
\type {\lastleftclass} and \type {\lastrightclass} that hold the most recent
edge classes.

\startbuffer
\tolerant\permanent\protected\def\NiceHack[#1]#:#2% special argument parsing
  {\begingroup
   \setmathatomrule
     \mathbegincode\mathbincode % context constants
     \allmathstyles
     \mathbegincode\mathbincode
   \normalexpanded
     {\setbox\scratchbox\hpack
        ymove \Umathaxis\Ustyle\mathstyle % an additional box property
        \bgroup
          \framed % a context macro
            [location=middle,#1]
            {$\Ustyle\mathstyle#2$}%
        \egroup}%
   \mathatom
     class 32 % an unused class
     \ifnum\lastleftclass <\zerocount\else leftclass  \lastleftclass\fi
     \ifnum\lastrightclass<\zerocount\else rightclass \lastrightclass\fi
     \bgroup
       \box\scratchbox
     \egroup
   \endgroup}
\stopbuffer

\typebuffer \getbuffer

\startbuffer
\def\MyTest#1%
  {$              x #1                        x $\quad
   $              x \NiceHack[offset=0pt]{#1} x $\quad
   $\displaystyle x #1                        x $\quad
   $\displaystyle x \NiceHack[offset=0pt]{#1} x $}

\scale[scale=2000]{\MyTest{>}}            \blank
\scale[scale=2000]{\MyTest{+}}            \blank
\scale[scale=2000]{\MyTest{!}}            \blank
\scale[scale=2000]{\MyTest{+\frac{1}{2}+}}\blank
\scale[scale=2000]{\MyTest{\frac{1}{2}}}  \blank
\stopbuffer

\typebuffer

Of course this is not code you immediately come up with after reading this text,
also because you need to know a bit of \CONTEXT.

\startlinecorrection
\showmakeup[mathglue]\getbuffer
\stoplinecorrection

There are a few control options, like \type {\noatomruling} that can be used to
prevent rules being applied to the next atom. We can use these in order to
achieve more advanced alignment results, but discussing math alignments would
demand many more pages than make sense here.

\stopsubject

\startsubject[title=Tuned kerning]

The \CONTEXT\ distribution has dedicated code for typesetting units that dates
back to the mid nineties of the previous century but was (code wise) upgraded
from \MKII\ to \MKIV\ which made it end up in the physics name space. There is
not much reason to redo that code but when we talk new spacing classes it might
make sense at some point to see if we can use less code for spacing by using a
\quote {unit} class. When Mikael pointed out that, for instance in Pagella:

\startlinecorrection
\switchtobodyfont[pagella]\showglyphs
\scale[height=1cm]{\setmathoptions\mathdivisioncode\zerocount\m{m^3/s__2}}
\stoplinecorrection

doesn't space well the obvious answer is: use the units mechanism because this
kind of rendering was why it was made in the first place. However, the question
is of course, can we do better anyway. The chosen solution uses a combination
of class options and tweaked shape kerning:

\startlinecorrection
\switchtobodyfont[pagella]\showglyphs
\scale[height=1cm]{\m{m^3/s__2}}
\stoplinecorrection

An example of a class setup in \CONTEXT\ is:

\starttyping
\setmathoptions\mathdivisioncode\numexpr
    \nopreslackclassoptioncode     +\nopostslackclassoptioncode
   +\lefttopkernclassoptioncode    +\righttopkernclassoptioncode
   +\leftbottomkernclassoptioncode +\rightbottomkernclassoptioncode
\relax
\stoptyping

and, although we don't go into the details of tweaking here, this is the kind
if code you will find in the goodie file:

\starttyping
{
    tweak = "kerns",
    list  = {
        [0x2F] = {
            topleft     = -0.3,
            bottomright =  0.2,
       }
    }
}
\stoptyping

where the numbers are a percentage of the width. This specification translates in
a math staircase kerning recipe.

\stopsubject

\startsubject[title=More font tweaks]

Once you start looking into the details of these fonts you are likely to notice
more issues. For instance, in the nice looking Lucida math fonts the relations
have inconsistent widths and even shapes. This can partially be corrected by
using a stylistic alternate but even that forced us to come up with a mechanism
to selectively replace \quote {bad} shapes because there is not that much
granularity in the alternates. And once we looked at these alternates we noticed
that the definition of of script versus calligraphic is also somewhat fuzzy and
font dependent. That made for yet another tweak where we can swap alphabets and
let the math machinery choose the expected shape. In \UNICODE\ this is handled by
variant selectors which is rather cumbersome. Because these two styles are used
mixed in the same document, a proper additional alphabet would have made more
sense. As we already support variant selectors it was no big deal to combine that
mechanism with a variant selector features over a range of calligraphic or script
characters, which indeed is what mathematicians use (Mikael can be very
convincing). With this kind of tweaks the engine doesn't really play a role: we
always could and did deal with it. It's just that upgrading the engine made us
look again at this.

\stopsubject

\startsubject[title=Normalization]

Once we had all these spacing related features upgraded it was time to move to
other aspects math typesetting. Most of that is not handled in the engine but at
the macro level. Examples of this are making sure that math spacing obeys the
rules across alignment cells, breaking long formulas into lines with various
alignment schemes. The first is accommodated by using the primitives that set the
states at the beginning and end of a formula so that is definitely something that
the engine facilitates. The second was already possible in \MKIV\ but is somewhat
more transparent now by using tagged boundary nodes.

But for this summary we stick to discussing the more low level features and where
most of what we discussed here concerns horizontal spacing we also have some
vertical magic like the mentioned scaled fences and operators but they sort of
behave as expected given the traditional \TEX\ approach. We have some more:

\startbuffer
\definemathradical[esqrt][sqrt][height=\maxdimen,depth=\maxdimen]
\definemathradical[ssqrt][sqrt][height=3ex,depth=2ex]

\def\TestSqrt#1%
  {test $ #1{x} + #1{\sin(x)} $ test\quad
   test $ #1{x} + #1{\sin(x)} + #1{\frac{1}{x}} $ test\quad
   test $ #1{x} + #1{x^2} $ test\quad
   test $ \left(#1{x} + #1{x^2} \right) $ test\par}

\TestSqrt \sqrt  \blank
\TestSqrt \esqrt \blank
\TestSqrt \ssqrt \blank
\stopbuffer

\typebuffer \getbuffer

In the above example you see that square roots can be made to adapt themselves to
other such roots. For this we had to add an additional pass. Originally there are
just two passes: a first typesetting pass where the maximum height and depth are
collected so that in the second pass the fences can be generated and injected.
That second pass also handles the spacing and penalties. In \LUAMETATEX\ we now
have (1) radical body typesetting, (2) radical typesetting, (3) atom typesetting
with height and depth analysis, (4) fence typesetting, and finally (5) inject
spacing, penalties, remove slack, etc.

In the examples above we set the height and depth and these are passed by
keywords to the radical primitive (most atoms and math structures accept keywords
that control rendering). Here the special values \type {\maxdimen} signal that we
have to make radicals of equal height and depth.

In \MKII\ we had ways to snap formulas so that we got consistent line spacing.
For a while I wondered if the engine could help with that but in the end no
specific engine features are needed, but is is definitely an area that I keep an
eye on because consistent spacing is important. After all one has to draw aline
somewhere and we always have the \LUA\ callback mechanism available.

\stopsubject

\startsubject[title=More goodies]

This summary will never be complete because we keep improving the rendering of
math. For instance, when Mikael checked some less used math alphabets of Latin
Modern and Bonum, as part of the goodie file completion, we were a bit horrified
by the weird top accent anchoring, inconsistent dimensions and stale italic
correction present in some glyphs. For instance there was a italic correction
after an upright blackboard lowercase \quote {f}, the upright digits had somewhat
random top accent anchors, and due to the lack of granularity in for instance
wide hats, characters that are often seen together got inconsistent wide hats.
Also clashing with scripts was possible. All this resulted in yet another bunch
of features:

\startitemize
\startitem
    In the goodie files we added efficient options to remove anchors from
    alphabets (or individual characters).
\stopitem
\startitem
    In the goodie files we added similar options to remove italic correction.
\stopitem
\startitem
    Characters got a few extra fields: margins that can be used to cheat with
    dimensions so that we can get more consistent wide accents.
\stopitem
\startitem
    The engine also got the possibility to compensate for accents when
    superscripts need to be anchored (by diminishing the height of accents as
    well as via an offsets).
\stopitem
\stopitemize

We expect to add (and use) some more options like this when we run into other
persistent issues. For sure there are some already that are not discussed here.
Of course one can argue why we spend time on this: in 15 years of \UNICODE\ math
usage in the \TEX\ community no one ever bothered about a wide hat over the
digit~7 and no one wondered about the bad spacing after a lowercase blackboard~f,
but as we go on we do run into these phenomena and it has become a bit of an
obsession to get it all right. \footnote {Of course all this puts the usual
bashing of Microsoft Word by users in a different perspective: limited control in
the \TEX\ engine, faulty fonts that come with \TEX\ distributions, lack of
testing and quality control, and probably the believe that all gets done well
automatically plays a role here.}

By closely looking at default positioning of accents on top of characters Mikael
noticed that the anchor points are actually always in the middle of the topmost
left and right points of shapes. It looks like these points are calculates
automatically and therefore you end up with an anchor on top of the highest part
of the seven in Latin Modern Serif but in the middle of a seven with a flat top.
You also get anchors at the top of the vertical line in b, d, and on the sticky
bit of the g. It is a good example of being careful with automating font design.
In our case, removing most anchors and adding a few later on was the solution.
\footnote {In the original fonts and traditional \TEX\ engine a kerning pair
between a so called skew char and the character at hand is used.}

\stopsubject

\startsubject[title=Untold stories]

There are of course more features but not all make sense to discuss here. For instance,
all hard coded properties are now configurable. Take for instance:

\startbuffer
\Umathsuperscriptvariant\textstyle  1
\Umathsubscriptvariant  \textstyle  1

$ 1_2^3 \quad {\scriptstyle 1_2^3} \quad {\displaystyle 1_2^3}$
\stopbuffer

\typebuffer

This gives us:

\startlinecorrection
\scale[scale=3000]{\getbuffer}
\stoplinecorrection

Here the number refers to one of the build in variants, that themselves are a
range of styles. In the next table the narrow variants are cramped:

\def\Cramped#1{{\glyphyscale\numexpr6*\glyphyscale/10\relax#1}}

\starttabulate[|c|l|c|c|c|c|c|c|c|c|]
\BC 0 \BC normal \NC
    D  \NC \Cramped{D}  \NC
    T  \NC \Cramped{T}  \NC
    S  \NC \Cramped{S}  \NC
    SS \NC \Cramped{SS} \NC
\NR
\BC 1 \BC cramped \NC
    \Cramped{D}  \NC \Cramped{D}  \NC
    \Cramped{T}  \NC \Cramped{T}  \NC
    \Cramped{S}  \NC \Cramped{S}  \NC
    \Cramped{SS} \NC \Cramped{SS} \NC
\NR
\BC 2 \BC subscript \NC
    \Cramped{S}  \NC \Cramped{S}  \NC
    \Cramped{S}  \NC \Cramped{S}  \NC
    \Cramped{SS} \NC \Cramped{SS} \NC
    \Cramped{SS} \NC \Cramped{SS} \NC
\NR
\BC 3 \BC superscript \NC
    S  \NC S  \NC
    S  \NC S  \NC
    SS \NC SS \NC
    SS \NC SS \NC
\NR
\BC 4 \BC small \NC
    S  \NC S  \NC
    S  \NC S  \NC
    SS \NC SS \NC
    SS \NC SS \NC
\NR
\BC 5 \BC smaller \NC
    S  \NC \Cramped{S}  \NC
    S  \NC \Cramped{S}  \NC
    SS \NC \Cramped{SS} \NC
    SS \NC \Cramped{SS} \NC
\NR
\BC 6 \BC numerator \NC
    S  \NC \Cramped{S}  \NC
    S  \NC \Cramped{S}  \NC
    SS \NC \Cramped{SS} \NC
    SS \NC \Cramped{SS} \NC
\NR
\BC 7 \BC denominator \NC
    \Cramped{S}  \NC \Cramped{S}  \NC
    \Cramped{S}  \NC \Cramped{S}  \NC
    \Cramped{SS} \NC \Cramped{SS} \NC
    \Cramped{SS} \NC \Cramped{SS} \NC
\NR
\BC 8 \BC double (superscript) \NC
    S  \NC \Cramped{S}  \NC
    S  \NC \Cramped{S}  \NC
    SS \NC \Cramped{SS} \NC
    SS \NC \Cramped{SS} \NC
\NR
\stoptabulate

If you want you can change these values but of course we're then basically
changing some of logic behind math rendering and for sure Don Knuth had good
reasons for these defaults.

Another untold story relates to multi scripts. When a double script is seen,
\TEX\ injects an ordinary recovery atom, issues an error message, and when told
so just continues. In order to always continue \LUAMETATEX\ introduces a mode
variable that default to minus one, as negative values will trigger the error.
Zero of positive values are interpreted as a class and bypass the error. Here is
an example of usage:

\startbuffer
\mathdoublescriptmode
  "\tohexadecimal\mathexperimentalcode % experimental class
   \tohexadecimal\mathexperimentalcode % we have to set both left and right

\setmathspacing \mathexperimentalcode \mathexperimentalcode \allmathstyles 20mu
\setmathspacing \mathordinarycode     \mathexperimentalcode \allmathstyles 20mu

$x^1_2^3_4^^^5___6^^^7___8$
\stopbuffer

\typebuffer

We get this:

\startlinecorrection
\scale[scale=3000]{\getbuffer}
\stoplinecorrection

\stopsubject

\startsubject[title=Final words]

One can argue that all these new features can make a document look better. But
you only have to look at what Don Knuth produces himself to see that one always
could do a good job with \TEX, although maybe at the cost of some extra spacing
directives. It is the fact that \OPENTYPE\ showed up as well as many more math
fonts, all with their own (sometimes surprising) special effects, that made us
adapt the engine. Of course there are also new possibilities that permit better
and more robust macro support. The \TEX book has a chapter on \quotation {the
fine points of mathematics typesetting} for a reason.

There has never been an excuse to produce bad looking documents. It is all
about care. For sure there is a category of users who are forced to use \TEX, so
they are excused. There are also those who have no eye for typography and rely on
the macro package, so there we can to some extent blame the authors of those
packages. And there are of course the sloppy users, those who don't enter a
revision loop at all. They could as well use any system that in some way can
handle math. One can also wonder in what way massive remote editing as well as
collaborative working on documents make things better. It probably becomes less
personal. At meetings and platforms \TEX\ users like to bash the alternatives but
in the end they are part of the same landscape and when it comes to math they
dominate. Maybe there is less to brag about then we like: just do your thing and
try to do it as good as possible. Rely on your eyes and pay attention to the
details, which is possible because the engine provided the means. The previous
text shows a few things to pay attention to.

Now that all the basics that have to do with proper dimensions, spacing,
penalties and logic are dealt with, we moved on to the more high level
constructs. We also haven't applied some features in the \CONTEXT\ code base yet
and are now experimenting with the more high level constructs. For instance the
frequently used math alignment mechanism has been overhauled to support advanced
inter atom spacing across rows, and in practice one will now more often not even
use this alignment mechanism and use the alignment features in multi|-|line
display math, if only because they offer advanced annotation. As a nice side
effect some of the mechanism that we use for this (like the improved \type
{\vadjust} primitive engine feature) also became somewhat more powerful in
regular text mode and we'll see where that brings us.

Given the time we spend on this and given the numerous new features it will take
a while before all that got added to the engine will be documented. Of course the
usage in \CONTEXT\ also serves as documentation. This is not really a problem
because most users will happily rely on the goodie files being okay and
maintained, and usage other than \CONTEXT\ is unlikely to use these new features,
if only because it will break away from the established long term standards and
habits.

\stopsubject

% \setdefaultmathcodes
% $\blackrule\mathatomskip \mathdigitcode \mathdigitcode\textstyle\blackrule$

\stopchapter

\stopcomponent

% \showframe
%
% \showmakeup[penalty]
%
% \startbuffer
%     \dorecurse {50} {
%         test $\darkblue   a +         #1         + b > 2$
%         test $\darkred    a + b +     #1     + c + d > 2$
%         test $\darkgreen  a + b + c + #1 + d + e + f > 2$
%     }
% \stopbuffer
%
% \setuptolerance[verytolerant,stretch]
%
% \setuplayout[width=11cm]
%
% \starttext
%     \start
%         \mathforwardpenalties  0
%         \mathbackwardpenalties 0
%         \getbuffer
%         \par
%     \stop
%     \page
%     \start
%         \mathforwardpenalties  2 -200 -100
%         \mathbackwardpenalties 2 -100  -50
%         \getbuffer
%         \par
%     \stop
%     \page
%     \start
%         \mathforwardpenalties  2  200 100
%         \mathbackwardpenalties 2  100  50
%         \getbuffer
%         \par
%     \stop
%     \page
% \stoptext

% example:
%
%     $ \left( x + 1 \right )^1_2^^^3___4 $
%     \blank
%     $ ( x + 1 )^1_2^^^3___4 $
%     \blank
%     $ (^^^3___4 x + 1 )^1_2 $

% example:
%
% \registerengineclass[digits][dgs]
%
% \newconstant \mathdigitscode \mathdigitscode \mathclassvalue digits
%
% \protected\def\mathdigits{\mathatom\mathdigitscode}
%
% \copymathspacing \mathdigitscode \mathdigitcode
%
% \setmathspacing \mathdigitscode      \mathdigitscode      \allmathstyles 3mu
% \setmathspacing \mathdigitscode      \mathpunctuationcode \allmathstyles 1mu
% \setmathspacing \mathpunctuationcode \mathdigitscode      \allmathstyles 1mu
%
% \startTEXpage[offset=1dk,width=20dk]
%     \showboxes\showmakeup[math]
%     $
%        x
%        =
%        \mathdigits {123}
%        \mathdigits {456} ,
%        \mathdigits {78}
%        =
%        \mathdigits {123} .
%        \mathdigits {456} ,
%        \mathdigits {78}
%     $
% \stopTEXpage

% \starttext
%     \showmakeup[math]
%     $ x \neq x $ \quad $ x \not x $ \quad $ x \eq\not x $ \quad $ x \not\eq x $\par
%     \pushoverloadmode
%     \let\normalnot\not
%     \permanent\protected\def\not#1{#1\normalnot}
%     \popoverloadmode
%     $ x \neq x $ \quad $ x \not x $ \quad $ x \eq\not x $ \quad $ x \not\eq x $\par
% \stoptext

%     $ \not \eq $\par
%     $ \eq \not $\par % gets collapsed

% example:  a_1=b_1+c_1 (for spacing)


% \startbuffer
% We test \dorecurse{20}{$x^{#1}$ and $\frac{1}{#1}^x$ and $\sqrt[#1]{x}$ and }that's it.
% \stopbuffer
%
% \startpostponing
% \startcombination[nx=2,ny=3,location=top]
%     {\ruledvbox{\hsize.45\textwidth \setupformula[snap=no]                 \showboxes            \enabletrackers [math.snapping=darkred] \getbuffer}} {}
%     {\ruledvbox{\hsize.45\textwidth \setupformula[snap=no]                                       \disabletrackers[math.snapping]         \getbuffer}} {}
%     {\ruledvbox{\hsize.45\textwidth \setupformula[snap=yes,snapstep=small] \showboxes \darkgreen \enabletrackers [math.snapping=darkred] \getbuffer}} {}
%     {\ruledvbox{\hsize.45\textwidth \setupformula[snap=yes,snapstep=small]            \darkgreen \disabletrackers[math.snapping]         \getbuffer}} {}
%     {\ruledvbox{\hsize.45\textwidth \setupformula[snap=yes,snapstep=big]   \showboxes \darkblue  \enabletrackers [math.snapping=darkred] \getbuffer}} {}
%     {\ruledvbox{\hsize.45\textwidth \setupformula[snap=yes,snapstep=big]              \darkblue  \disabletrackers[math.snapping]         \getbuffer}} {}
% \stopcombination
% \stoppostponing


% https://yurichev.com/mirrors/knuth1989.pdf .. DEK:
%
% I too had trouble with numerators and denominators: change no. 229 increased the
% amount of space surrounding the bar line in displayed fractions, and I should have
% made a similar change to fractions in text. (Page 68 of the new Volume 2 turned out
% to be extremely ugly because of badly spaced fractions.) T~x82 was able to improve
% the situation because of my experiences with T~x78, but even today I must take
% special precautions in my TEX documents to get certain square roots to look right.

