summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/ontarget/ontarget-math.tex
diff options
context:
space:
mode:
Diffstat (limited to 'doc/context/sources/general/manuals/ontarget/ontarget-math.tex')
-rw-r--r--doc/context/sources/general/manuals/ontarget/ontarget-math.tex1816
1 files changed, 1816 insertions, 0 deletions
diff --git a/doc/context/sources/general/manuals/ontarget/ontarget-math.tex b/doc/context/sources/general/manuals/ontarget/ontarget-math.tex
new file mode 100644
index 000000000..c7e5551d5
--- /dev/null
+++ b/doc/context/sources/general/manuals/ontarget/ontarget-math.tex
@@ -0,0 +1,1816 @@
+% 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 draw 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 build 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
+next 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 build 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 be 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 month 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 that
+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 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 this kind of 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 hav elittle 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 that 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 found one, 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
+
+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 introduced 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=
+\mathord
+.\nucleus
+..\mathchar (fam="0,char="58)
+.\superscript
+..\mathchar (fam="0,char="32)
+.\subscript
+..\mathchar (fam="0,char="32)
+.\primescript
+..\mathchar (fam="0,char="27)
+\stoptyping
+
+Of course this feature scan 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 fenced 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
+little 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 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 of 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 upto 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 niling is not granular enough a while later we introduced a
+way to set this per class, as is demonstrated in the next 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!}
+
+\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 be 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:
+
+\starttyping
+7:3: > \inlinemath=
+7:3: \mathord
+7:3: .\nucleus
+7:3: ..\mathchar (fam="0,char="28)
+7:3: \mathord
+7:3: .\nucleus
+7:3: ..\mathlist
+7:3: ...\mathopen
+7:3: ....\nucleus
+7:3: .....\mathchar (fam="0,char="28)
+7:3: \mathord
+7:3: .\nucleus
+7:3: ..\mathchar (fam="0,char="28)
+7:3: \mathopen
+7:3: .\nucleus
+7:3: ..\mathchar (fam="0,char="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 it 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 care 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
+and 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 it 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 later 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
+
+\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 we 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 a 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 brawl 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.
+
+Once all the basics that have to do with proper dimensions, spacing, penalties
+and logic are dealt with, we will move on to the more high level constructs. So,
+expect more.
+
+\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)