summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/ontarget/ontarget-gettingridof.tex
diff options
context:
space:
mode:
Diffstat (limited to 'doc/context/sources/general/manuals/ontarget/ontarget-gettingridof.tex')
-rw-r--r--doc/context/sources/general/manuals/ontarget/ontarget-gettingridof.tex1666
1 files changed, 1666 insertions, 0 deletions
diff --git a/doc/context/sources/general/manuals/ontarget/ontarget-gettingridof.tex b/doc/context/sources/general/manuals/ontarget/ontarget-gettingridof.tex
new file mode 100644
index 000000000..75b7f5bc0
--- /dev/null
+++ b/doc/context/sources/general/manuals/ontarget/ontarget-gettingridof.tex
@@ -0,0 +1,1666 @@
+% language=us runpath=texruns:manuals/ontarget
+
+\startcomponent ontarget-gettingridof
+
+\environment ontarget-style
+
+\startchapter[title={Issues in math fonts}]
+
+\startsection[title=Introduction]
+
+After trying to improve math rendering of \OPENTYPE\ math fonts, we \footnote
+{Mikael Sundqvist and Hans Hagen} ended up with a mix of improving the engine and
+fixing fonts runtime, and we are rather satisfied with the results so far.
+
+However, as we progress and also improve the more structural and input related
+features of \CONTEXT, we wonder why we don't simply are more drastic when it
+comes to fonts. The \OPENTYPE\ specifications are vague, and most existing
+\OPENTYPE\ math fonts use a mixture of the \OPENTYPE\ features and the old \TEX\
+habits, so we are sort of on our own. The advantage of this situation is that we
+feel free to experiment and do as we like.
+
+In another article we discuss our issues with \UNICODE\ math, and we have
+realized that good working solutions will be bound to a macro package anyway.
+Also, math typesetting has not evolved much after Don Knuth set the standard,
+even if the limitations of those times in terms of memory, processing speed and
+font technologies have been lifted already for a while. And right from the start
+Don invited users to extend and adapt \TEX\ to one's needs.
+
+Here we will zoom in on a few aspects: font parameters, glyph dimensions and
+properties and kerning of scripts and atoms. We discuss \OPENTYPE\ math fonts
+only, and start with a summary of how we tweak them. We leave a detailed engine
+discussion to a future article, since that would demand way more pages, and could
+confuse the reader.
+\stopsection
+
+\startsection[title={Tweaks, also known as goodies}]
+
+The easiest tweaks to describe are those that wipe features. Because the
+\TEXGYRE\ fonts have many bad top accent anchors (they sit above the highest
+point of the shape) the \typ {wipeanchors} tweak can remove them, and we do that
+per specified alphabet.
+
+\bgroup
+\definefontfeature[mathextra][goodies=]
+\switchtobodyfont[modern]
+\startformula
+\scale[s=2]{$\widehat{7}$}
+% \widehat{7}
+\stopformula
+\egroup
+\stopformulas
+
+In a similar fashion we \typ {wipeitalics} from upright shapes. Okay, maybe they
+can play a role for subscript placement, but then they can also interfere, and
+they do not fit with the \OPENTYPE\ specification. The \typ {wipecues} tweak
+zeros the dimensions of the invisible times and friends so that they don't
+interfere and \typ {wipevariants} gets rid of bad variants of specified
+characters.
+
+The fixers is another category, and the names indicate what gets fixed. Tweaks
+like these take lists of code points and specific properties to fix. We could
+leave it to your imagination what \typ {fixaccents}, \typ {fixanchors}, \typ
+{fixellipses}, \typ {fixoldschool}, \typ {fixprimes}, \typ {fixradicals} and \typ
+{fixslashes} do, but here are some details. Inconsistencies in the dimensions of
+accents make them jump all over the place so we normalize them. We support
+horizontal stretching at the engine level.
+
+\startformula
+\scale[s=2]{\dm{\widehat{a+b+c+d} = \widetilde{u+v+w+x+y}}}
+\stopformula
+
+It required only a few lines of code thanks to already present scaling features.
+
+% MPS: I thought of an example showing the accents, but I could
+% not get it to work fine with the goodies loaded the second
+% time the font was loaded
+%
+% \startformulas
+% \bgroup \definefontfeature[mathextra][goodies=]\setupbodyfont[modern]
+% \startformula[width=2em]
+% \widehat{7}
+% \stopformula
+% \egroup
+% \bgroup\setupbodyfont[modern]
+% \startformula[width=2em]
+% \widehat{7}
+% \stopformula
+% \egroup
+% \stopformulas
+
+Anchors can be off so we fix these in a way so that they look better on
+especially italic shapes. We make sure that the automated sizing works
+consistently, as this is driven by width and overshoot. Several kind of ellipses
+can be inconsistent with each other as well as with periods (shape and size wise)
+so we have to deal with that. Radicals and other extensibles have old school
+dimensions (\TEX\ fonts have a limited set of widths and heights). We need to fix
+for instance fences of various size because we want to apply kerns to scripts on
+the four possible corners for which we need to know the real height and depth,
+
+Discussing primes would take many paragraphs so we stick to mentioning that they
+are a mess. We now have native prime support in the engine as well as assume
+properly dimensioned symbols to be used. Slashes are used for skewed fractions so
+we'd better make sure they are set up right.
+
+A nice tweak is \typ {replacealphabets}. We use this to provide alternative
+script (roundhand) and calligraphic (chancery) alphabets (yes we have both
+natively in \CONTEXT\ while \UNICODE\ combines them in one alphabet). Many
+available \OPENTYPE\ math fonts come with one of the two alphabets only, some
+with roundhand and some with chancery. For the record: this tweak replaces the
+older \typ {variants} tweak that filtered scripts from a stylistic font feature.
+
+We also use the \typ {replacealphabets} tweak to drop in Arabic shapes so that we
+can do bidirectional math. In practice that doesn't really boil down to a
+replacement but more to an addition. The \typ {addmirrors} features accompanies
+this, and it is again a rather small extension to the engine to make sure we can
+do this efficiently: when a character is looked up we check a mirror variant when
+we are in r2l mode, just like we look up a smaller variant when we're in compact
+font mode (a \CONTEXT\ feature).
+
+\bgroup
+\definefontfeature[mathextra][mathxitsarabic=yes]
+\switchtobodyfont[bonum]
+\setupmathematics[bidi=yes,align=righttoleft]\par
+\setupalign[righttoleft] %
+\startformula
+\scale[s=2]{\dm{
+\sum_{\char"1EE4E=\char"1EE01}^{\char"1EE02} \char"1EE03^{\char"1EE4E} =
+\char"1EE03^{\char"1EE01}\frac{\char"0661 - \char"1EE03^{\char"1EE02 -
+\char"1EE01 + \char"0661}}{\char"0661 - \char"1EE03} \quad (\char"1EE03\neq
+\char"0661)
+}}
+
+% \int_{\char"0627}^{\char"0628} \char"1EE03 '(\char"1EE4E)
+% %\mathatom class \mathdifferentialcode {\char"062F}
+% \dd
+% \char"1EE4E
+% = \char"1EE03(\char"0628) - \char"1EE03(\char"0627)
+% \stopformula
+% \startformula
+% \sqrt[\char"0663](\char"1EE30) = (\char"1EE30)^{1/\char"0663}
+\stopformula
+\egroup
+
+Another application of \typ {replacealphabets} is to drop in single characters
+from another font. We use this for instance to replace the \quote {not really an
+alpha} in Bonum by one of our own liking. Below we show a math italic a and the
+original alpha, together with the modified alpha.
+
+\startformula
+\scale[s=2]{\dm{
+a + \text{\getnamedglyphdirect{file:TeXGyreBonumMath-Companion.otf}{alpha.old}} + \alpha
+}}
+\stopformula
+
+For that we ship a companion font. On our disks (and in the distribution) you can
+find:
+
+\starttyping
+/tex/texmf-fonts/fonts/data/cms/companion/RalphSmithsFormalScript-Companion.otf
+/tex/texmf-fonts/fonts/data/cms/companion/TeXGyreBonumMath-Companion.otf
+/tex/texmf-fonts/fonts/data/cms/companion/XITSMath-Companion.otf
+\stoptyping
+
+All these are efficient drop|-|ins that are injected by the \typ
+{replacealphabets}, some under user control, some always. We tried to limit the
+overhead and actually bidirectional math could be simplified which also had the
+benefit that when one does tens of thousands of bodyfont switches a bit of
+runtime is gained.
+
+There are more addition tweaks: \typ {addactuarian} creates the relevant symbols
+which is actually a right sided radical (the engine has support for two|-|sided
+radicals). It takes a bit of juggling with virtual glyphs and extensible recipes,
+but the results are rewarding.
+
+\setupmathradical[annuity][strut=no]
+\definemathdelimited
+ [myannuity]
+ [topoffset=.2\exheight,
+ strut=no,
+ rightmargin=.05\emwidth,
+ right=\delimitedrightanutityuc]
+
+\startformula
+\scale[s=2]{\dm{
+\widebar{A}__{\myannuity{m}}^^{2}_{x:\annuity{n}}^{1}
+}}
+\stopformula
+
+In a similar fashion we try to add missing extensible arrows with \typ
+{addarrows}, bars with \typ {addbars}, equals with \typ {addequals} and again
+using the radical mechanism fourier notation symbols (like hats) with \typ
+{addfourier}. That one involves subtle kerning because these symbols end up at
+the right top of a fence like symbol.
+
+\startformula
+\scale[s=2]{\dm{
+\widehat{f \ast g \ast h}(\xi) = \fourier{\F1\left(f\ast g \ast h\right)}(\xi)
+}}
+\stopformula
+
+It was actually one of the reasons to introduce a more advanced kerning mechanism
+in the engine, which is not entirely trivial because one has to carry around more
+information, since all this is font and character bound, and when wrapped in
+boxes that gets hard to analyze. The \typ {addrules} makes sure that we can do
+bars over and under constructs properly. The \typ {addparts} is there to add
+extensible recipes to characters.
+
+Some of these tweaks actually are not new and are also available in \MKIV\ but
+more as features (optionally driven by the goodie file). An example is \typ
+{addscripts} that is there for specially positioned and scaled signs (high minus
+and such) but that tweak will probably be redone as part of the \quotation {deal
+with all these plus and minus issues}. The dedicated to Alan Braslau \typ
+{addprivates} tweak is an example of this: we add specific variants for unary
+minus and plus that users can enable on demand, which in turn of course gives
+class specific spacing, but we promised not to discuss those engine features
+here.
+
+\startformula
+\scale[s=2]{\dm{
+\int_1^2 \left[(x+2)^{\frac[strut=no]{1}{2}} - (x+2)^{\um\frac[strut=no]{1}{2}}\right] \dd x
+}}
+\stopformula
+
+There is a handful of tweaks that deals with fixing glyph properties (in detail).
+We mention: \typ {dimensions} and \typ {accentdimensions} that can reposition in
+the boundingbox, fix the width and italic correction, squeeze and expand etc. The
+\typ {kernpairs} tweak adds kern pairs to combinations of characters. The \typ
+{kerns} provides a way to add top left, bottom left, top right and bottom right
+kerns and those really make the results look better so we love it!
+
+\startformula
+\scale[s=2]{\showglyphs\dm{\F3\left(\frac{1}{1+x^2}\right)^n \quad x^2/(1+x)}}
+\stopformula
+
+The \typ {margins} tweak sets margin fields that the engine can use to calculate
+accents over the base character better. The same is true for \typ {setovershoots}
+that can make accents lean over a bit. The \typ {staircase} feature can be used
+to add the somewhat complicated \OPENTYPE\ kerns. From all this you can deduce
+that the engine has all types of kerning that \OPENTYPE\ requires, and more.
+
+Accents as specified in fonts can be a pain to deal with so we have more tweaks
+for them: \typ {copyaccents} moves them to the right slots and \typ
+{extendaccents} makes sure that we can extend them. Not all font makers have the
+same ideas about where these symbols should sit and what their dimensions should
+be.
+
+The \typ {checkspacing} tweak fixes bad or missing spacing related to \UNICODE\
+character entries in the font, because after all, we might need them. We need to
+keep for instance \MATHML\ in mind, which means: processing content that we don't
+see and that can contain whatever an editor puts in. The \typ {replacements}
+feature replaces one character by another from the same font. The \typ
+{substitutes} replaces a character by one from a stylistic feature.
+
+Relatively late we added the \typ {setoptions} which was needed to control the
+engine for specific fonts. The rendering is controlled by a bunch of options
+(think of kerning, italic correction, and such). Some are per font, many per
+class. Because we can (and do) use mixed math fonts in a document, we might need
+to adapt the engine level options per font, and that is what this tweak does: it
+passes options to the font so that the engine can consult them and prefer them
+over the \quote {global} ones. We needed this for some fonts that have old school
+dimensions for extensibles (like Lucida), simply because they imitated Computer
+Modern. Normally that goes unnoticed, but, as mentioned before, it interferes
+with our optional kerning. The \typ {fixoldschool} tweak sort of can fix that too
+so \typ {setoptions} is seldom needed. Luckily, some font providers are willing
+to fix their fonts!
+
+We set and configure all these tweaks in a so-called goodie file, basically a
+runtime module that returns a \LUA\ table with specifications. In addition to the
+tweaks subtable in the math namespace, there is a subtable that overloads the
+font parameters: the ones that \OPENTYPE\ specifies, but also new ones that we
+added. In the next section we elaborate more on these font bound parameters.
+
+\stopsection
+
+\startsection[title=Font parameters]
+
+At some point in the upgrading of the math machinery we discussed some of the
+inconsistencies between the math constants of the XITS and STIX fonts. Now, one
+has to keep in mind that XITS was based on a first release of STIX that only had
+\TYPEONE\ fonts so what follows should not to be seen as criticism, but more as
+observations and reason for discussion, as well as a basis for decisions to be
+made.
+
+One thing we have to mention in advance, is that we often wonder why some weird
+and|/|or confusing stuff in math fonts go unnoticed. We have some suggestions:
+
+\startitemize
+\startitem
+ The user doesn't care that much how math comes out. This can easily be
+ observed when you run into documents on the internet or posts on forums. And
+ publishers don't always seem to care either. Consistency with old documents
+ sometimes seems to be more important than quality.
+\stopitem
+\startitem
+ The user switches to another math font when the current one doesn't handle
+ its intended math domain well. We have seen that happening and it's the
+ easiest way out when you have not much control anyway (for instance when
+ using online tools).
+\stopitem
+\startitem
+ The user eventually adds some skips and kerns to get things right, because
+ after all \TEX\ is also about tweaking.
+\stopitem
+\startitem
+ The user doesn't typeset that complex math. It's mostly inline math with an
+ occasional alignment (also in text style) and very few multi|-|level display
+ math (with left and right fences that span at most a fraction).
+\stopitem
+\stopitemize
+
+We do not claim to be perfect, but we care for details, so let's go on. The next
+table shows the math constants as they can be found in the \STIX\ (two) and
+\XITS\ (one) fonts. When you typeset with these fonts you will notice that \XITS\
+is somewhat smaller, so two additional columns show the values compensated for
+the axis height and accent base height.
+
+\startluacode
+local one = {
+ ["AccentBaseHeight"]=450,
+ ["AxisHeight"]=250,
+ ["DelimitedSubFormulaMinHeight"]=1500,
+ ["DisplayOperatorMinHeight"]=1450,
+ ["FlattenedAccentBaseHeight"]=662,
+ ["FractionDenominatorDisplayStyleGapMin"]=198,
+ ["FractionDenominatorDisplayStyleShiftDown"]=700,
+ ["FractionDenominatorGapMin"]=66,
+ ["FractionDenominatorShiftDown"]=480,
+ ["FractionNumeratorDisplayStyleGapMin"]=198,
+ ["FractionNumeratorDisplayStyleShiftUp"]=580,
+ ["FractionNumeratorGapMin"]=66,
+ ["FractionNumeratorShiftUp"]=480,
+ ["FractionRuleThickness"]=66,
+ ["LowerLimitBaselineDropMin"]=600,
+ ["LowerLimitGapMin"]=150,
+ ["MathLeading"]=150,
+ ["MinConnectorOverlap"]=50,
+ ["OverbarExtraAscender"]=66,
+ ["OverbarRuleThickness"]=66,
+ ["OverbarVerticalGap"]=198,
+ ["RadicalDegreeBottomRaisePercent"]=70,
+ ["RadicalDisplayStyleVerticalGap"]=186,
+ ["RadicalExtraAscender"]=66,
+ ["RadicalKernAfterDegree"]=-555,
+ ["RadicalKernBeforeDegree"]=277,
+ ["RadicalRuleThickness"]=66,
+ ["RadicalVerticalGap"]=82,
+ ["ScriptPercentScaleDown"]=75,
+ ["ScriptScriptPercentScaleDown"]=60,
+ ["SkewedFractionHorizontalGap"]=300,
+ ["SkewedFractionVerticalGap"]=66,
+ ["SpaceAfterScript"]=41,
+ ["StackBottomDisplayStyleShiftDown"]=900,
+ ["StackBottomShiftDown"]=800,
+ ["StackDisplayStyleGapMin"]=462,
+ ["StackGapMin"]=198,
+ ["StackTopDisplayStyleShiftUp"]=580,
+ ["StackTopShiftUp"]=480,
+ ["StretchStackBottomShiftDown"]=600,
+ ["StretchStackGapAboveMin"]=150,
+ ["StretchStackGapBelowMin"]=150,
+ ["StretchStackTopShiftUp"]=300,
+ ["SubSuperscriptGapMin"]=264,
+ ["SubscriptBaselineDropMin"]=50,
+ ["SubscriptShiftDown"]=250,
+ ["SubscriptTopMax"]=400,
+ ["SuperscriptBaselineDropMax"]=375,
+ ["SuperscriptBottomMaxWithSubscript"]=400,
+ ["SuperscriptBottomMin"]=125,
+ ["SuperscriptShiftUp"]=400,
+ ["SuperscriptShiftUpCramped"]=275,
+ ["UnderbarExtraDescender"]=66,
+ ["UnderbarRuleThickness"]=66,
+ ["UnderbarVerticalGap"]=198,
+ ["UpperLimitBaselineRiseMin"]=300,
+ ["UpperLimitGapMin"]=150,
+}
+
+local two = {
+ ["AccentBaseHeight"]=480,
+ ["AxisHeight"]=258,
+ ["DelimitedSubFormulaMinHeight"]=1325,
+ ["DisplayOperatorMinHeight"]=1800,
+ ["FlattenedAccentBaseHeight"]=656,
+ ["FractionDenominatorDisplayStyleGapMin"]=150,
+ ["FractionDenominatorDisplayStyleShiftDown"]=640,
+ ["FractionDenominatorGapMin"]=68,
+ ["FractionDenominatorShiftDown"]=585,
+ ["FractionNumeratorDisplayStyleGapMin"]=150,
+ ["FractionNumeratorDisplayStyleShiftUp"]=640,
+ ["FractionNumeratorGapMin"]=68,
+ ["FractionNumeratorShiftUp"]=585,
+ ["FractionRuleThickness"]=68,
+ ["LowerLimitBaselineDropMin"]=670,
+ ["LowerLimitGapMin"]=135,
+ ["MathLeading"]=150,
+ ["MinConnectorOverlap"]=100,
+ ["OverbarExtraAscender"]=68,
+ ["OverbarRuleThickness"]=68,
+ ["OverbarVerticalGap"]=175,
+ ["RadicalDegreeBottomRaisePercent"]=55,
+ ["RadicalDisplayStyleVerticalGap"]=170,
+ ["RadicalExtraAscender"]=78,
+ ["RadicalKernAfterDegree"]=-335,
+ ["RadicalKernBeforeDegree"]=65,
+ ["RadicalRuleThickness"]=68,
+ ["RadicalVerticalGap"]=85,
+ ["ScriptPercentScaleDown"]=70,
+ ["ScriptScriptPercentScaleDown"]=55,
+ ["SkewedFractionHorizontalGap"]=350,
+ ["SkewedFractionVerticalGap"]=68,
+ ["SpaceAfterScript"]=40,
+ ["StackBottomDisplayStyleShiftDown"]=690,
+ ["StackBottomShiftDown"]=385,
+ ["StackDisplayStyleGapMin"]=300,
+ ["StackGapMin"]=150,
+ ["StackTopDisplayStyleShiftUp"]=780,
+ ["StackTopShiftUp"]=470,
+ ["StretchStackBottomShiftDown"]=590,
+ ["StretchStackGapAboveMin"]=68,
+ ["StretchStackGapBelowMin"]=68,
+ ["StretchStackTopShiftUp"]=800,
+ ["SubSuperscriptGapMin"]=150,
+ ["SubscriptBaselineDropMin"]=160,
+ ["SubscriptShiftDown"]=210,
+ ["SubscriptTopMax"]=368,
+ ["SuperscriptBaselineDropMax"]=230,
+ ["SuperscriptBottomMaxWithSubscript"]=380,
+ ["SuperscriptBottomMin"]=120,
+ ["SuperscriptShiftUp"]=360,
+ ["SuperscriptShiftUpCramped"]=252,
+ ["UnderbarExtraDescender"]=68,
+ ["UnderbarRuleThickness"]=68,
+ ["UnderbarVerticalGap"]=175,
+ ["UpperLimitBaselineRiseMin"]=300,
+ ["UpperLimitGapMin"]=135,
+}
+
+local designrelated = {
+ ["AccentBaseHeight"] = "optional**",
+ ["AxisHeight"] = "mandate",
+ ["FlattenedAccentBaseHeight"] = "optional**",
+ ["FractionRuleThickness"] = "optional",
+ ["MinConnectorOverlap"] = "mandate",
+ ["OverbarRuleThickness"] = "optional*",
+ ["RadicalDegreeBottomRaisePercent"] = "mandate",
+ ["UnderbarRuleThickness"] = "optional*",
+}
+
+local a1 = two.AccentBaseHeight / one.AccentBaseHeight
+local a2 = two.AxisHeight / one.AxisHeight
+
+context.starttabulate { "|l|r|r|r|r|l|" }
+ context.FL()
+ context.BC() context("constant")
+ context.BC() context("stix")
+ context.BC() context("xits")
+ context.BC() context("base")
+ context.BC() context("axis")
+ context.BC() context("relevance")
+ context.BC() context.NR()
+ context.ML()
+ for key, oldvalue in table.sortedhash(one) do
+ local newvalue = two[key]
+ local accvalue = math.round(oldvalue * a1)
+ local axivalue = math.round(oldvalue * a2)
+ context.NC() context(key)
+ context.NC() context(newvalue)
+ context.NC() context(oldvalue)
+ context.NC() if newvalue == accvalue then context.bold(accvalue) else context(accvalue) end
+ context.NC() if newvalue == axivalue then context.bold(axivalue) else context(axivalue) end
+ context.NC() context(designrelated[key])
+ context.NC() context.NR()
+ end
+ context.LL()
+context.stoptabulate()
+\stopluacode
+
+Very few values are the same. So, what exactly do these constants tell us? You
+can even wonder why they are there at all. Just think of this: we want to typeset
+math, and we have an engine that we can control. We know how we want it to look.
+So, what do these constants actually contribute? Plenty relates to the height and
+depth of the nucleus and|/|or the axis. The fact that we have to fix some in the
+goodie files, and the fact that we actually need more variables that control
+positioning, makes for a good argument to just ignore most of the ones provided
+by the font, especially when they seem somewhat arbitrarily. Can it be that font
+designers are just gambling a bit, looking at another font, and starting from
+there?
+
+The relationship between \TEX's math font parameters and the \OPENTYPE\ math
+constants is not one|-|to|-|one. Mapping them onto each other is possible but
+actually is font dependent. However, we can assume that the values of Computer
+Modern are leading.
+
+The \typ {AxisHeight}, \typ {AccentBaseHeight} and \typ
+{FlattenedAccentBaseHeight} are set to the x|-|height, a value that is defined in
+all fonts. The \typ {SkewedFractionVerticalGap} also gets that value. Other
+variables relate to the em|-|width (or \type {\quad}), for instance the \typ
+{SkewedFractionHorizontalGap} that gets half that value. Of course these last two
+then assume that the engine handles skewed fractions.
+
+Variables that directly map onto each other are \typ {StretchStackGapBelowMin} as
+\typ {bigopspacing1}, \typ {StretchStackTopShiftUp} as \typ {bigopspacing3}, \typ
+{StretchStackGapAboveMin} as \typ {bigopspacing2} and \typ
+{StretchStackBottomShiftDown} as \typ {bigopspacing4}. However, these clash with
+\typ {UpperLimitBaselineRiseMin} as \typ {bigopspacing3}, \typ {UpperLimitGapMin}
+as \typ {bigopspacing1}, \typ {LowerLimitBaselineDropMin} as \typ {bigopspacing4}
+and \typ {LowerLimitGapMin} as \typ {bigopspacing2}. Where in traditional fonts
+these are the same, in \OPENTYPE\ they can be different. Should they be?
+
+Internally we use different names for variables, simply because the engine has
+some parameters that \OPENTYPE\ maths hasn't. So we have \typ {limit_above_kern}
+and \typ {limit_below_kern} for \typ {bigopspacing5}.
+
+A couple of parameters have different values for (cramped) displaystyle. The \typ
+{FractionDelimiterSize} and \typ {FractionDelimiterDisplayStyleSize} use \typ
+{delim2} and \typ {delim1}. The \typ {FractionDenominatorShiftDown} and \typ
+{FractionDenominatorDisplayStyleShiftDown} map onto \typ {denom2} and \typ
+{denom1} and their numerator counterparts from \typ {num2} and \typ {num1}. The
+\typ {Stack*} parameters also use these. The \typ {sub1}, \typ{sub2}, \typ{sup1},
+\typ{sup2}, \typ{sup3}, and \typ {supdrop} can populate the \type {Sub*} and
+\type {Super*} parameters, also in different styles.
+
+The rest of the parameters can be defined in terms of the default rulethickness,
+quad or xheight, often multiplied by a factor. For some we see the \type {1/18}
+show up a number that we also see with muskips. Some constants can be set from
+registers, like \typ {SpaceAfterScript} which is just \type {\scriptspace}.
+
+If you look at the \LUATEX\ source you wil find a section where this mapping is
+done in the case of a traditional font, that is: one without a math constants
+table. In \LUAMETATEX\ we don't need to do this because font loading happens in
+\LUA. So we simply issue an error when the math engine can't resolve a mandate
+parameter. The fact that we have a partial mapping from math constants onto
+traditional parameters and that \LUATEX\ has to deal with the traditional ones
+too make for a somewhat confusing landscape. When in \LUAMETATEX\ we assume wide
+fonts to be used that have a math constants table, we can probably clean up some
+of this.
+
+We need to keep in mind that Cambria was the starting point, and it did borrow
+some concepts from \TEX. But \TEX\ had parameters because there was not enough
+information in the glyphs! Also, Cambria was meant for \MSWORD, and a word
+processor is unlikely to provide the level of control that \TEX\ offers, so it
+needs some directions with respect to e.g.\ spacing. Without user control, it has
+to come up with acceptable compromises. So actually the \LUAMETATEX\ math engine
+can be made a bit cleaner when we just get rid of these parameters.
+
+So, which constants are actually essential? The \typ {AxisHeight} is important
+and also design related. Quite likely this is where the minus sits above the
+baseline. It is used for displacements of the baseline so that for instance
+fractions nicely align. When testing script anchored to fences we noticed that
+the parenthesis in XITS had too little depth while STIX had the expected amount.
+This relates to anchoring relative to the math axis.
+
+Is there a reason why \typ {UnderbarRuleThickness} and \typ
+{OverbarRuleThickness} should differ? If not, then we only need a variable that
+somehow tells us what thickness fits best with the other top and bottom accents.
+It is quite likely the same as the \typ {RadicalRuleThickness}, which is needed
+to extend the radical symbol. So, here three constants can be replaced by one
+design related one. The \typ {FractionRuleThickness} can also be derived from
+that, but more likely is that it is a quantity that the macro package sets up
+anyway, maybe related to rules used elsewhere.
+
+The \typ {MinConnectorOverlap} and \typ {RadicalDegreeBottomRaisePercent} also
+are related to the design although one could abuse the top accent anchor for the
+second one. So they are important. However, given the small number of
+extensibles, they could have been part of the extensible recipes.
+
+The \typ {AccentBaseHeight} and \typ {FlattenedAccentBaseHeight} might relate to
+the margin that the designer put below the accent as part of the glyph, so it is
+kind of a design related constant. Nevertheless, we fix quite some accents in the
+goodie files because they can be inconsistent. That makes these constants
+somewhat dubious too. If we have to check a font, we can just as well set up
+constants that we need in the goodie file. Also, isn't it weird that there are no
+bottom variants?
+
+We can forget about \typ {MathLeading} as it serves no purpose in \TEX. The \typ
+{DisplayOperatorMinHeight} is often set wrong so although we fix that in the
+goodie file it might be that we just can use an internal variable. It is not the
+font designer who decides that anyway. The same is true for \typ
+{DelimitedSubFormulaMinHeight}.
+
+If we handle skewed fractions, \typ {SkewedFractionHorizontalGap} and \typ
+{SkewedFractionVerticalGap} might give an indication of the tilt but why do we
+need two? It is design related though, so they have some importance, when set
+right.
+
+The rest can be grouped, and basically we can replace them by a consistent set of
+engine parameters. We can still set them up per font, but at least we can then
+use a clean set. Currently, we already have more. For instance, why only \typ
+{SpaceAfterScript} and not one for before, and how about prescripts and primes?
+If we have to complement them with additional ones and also fix them, we can as
+well set up all these script related variables.
+
+For fractions the font provides \typ {FractionDenominatorDisplayStyleGapMin},
+\typ {FractionDenominatorDisplayStyleShiftDown}, \typ
+{FractionDenominatorGapMin}, \typ {FractionDenominatorShiftDown}, \typ
+{FractionNumeratorDisplayStyleGapMin}, \typ
+{FractionNumeratorDisplayStyleShiftUp}, \typ {FractionNumeratorGapMin} and \typ
+{FractionNumeratorShiftUp}. We might try to come up with a simpler model.
+
+Limits have: \typ {LowerLimitBaselineDropMin}, \typ {LowerLimitGapMin}, \typ
+{UpperLimitBaselineRiseMin} and \typ {UpperLimitGapMin}. Limits are tricky anyway
+as they also depend on abusing the italic correction for anchoring.
+
+Horizontal bars are driven by \typ {OverbarExtraAscender}, \typ
+{OverbarVerticalGap}, \typ {UnderbarExtraDescender} and \typ
+{UnderbarVerticalGap}, but for e.g.\ arrows we are on our own, so again a not so
+useful set.
+
+Then radicals: we need some more than these \typ
+{RadicalDisplayStyleVerticalGap}, \typ {RadicalExtraAscender}, \typ
+{RadicalKernAfterDegree}, \typ {RadicalKernBeforeDegree} and \typ
+{RadicalVerticalGap}, and because we really need to check these there is no gain
+having them in the font.
+
+Isn't it more a decision by the macro package how script and scriptscript should
+be scaled? Currently we listen to \typ {ScriptPercentScaleDown} and \typ
+{ScriptScriptPercentScaleDown}, but maybe it relates more to usage.
+
+We need more control than just \typ {SpaceAfterScript} and an engine could
+provide it more consistently. It's a loner.
+
+How about \typ {StackBottomDisplayStyleShiftDown}, \typ {StackBottomShiftDown},
+\typ {StackDisplayStyleGapMin}, \typ {StackGapMin}, \typ
+{StackTopDisplayStyleShiftUp} and \typ {StackTopShiftUp}? And isn't this more for
+the renderer to decide: \typ {StretchStackBottomShiftDown}, \typ
+{StretchStackGapAboveMin}, \typ {StretchStackGapBelowMin} and \typ
+{StretchStackTopShiftUp}?
+
+This messy bit can also be handled more convenient so what exactly is the
+relationship with the font design of \typ {SubSuperscriptGapMin}, \typ
+{SubscriptBaselineDropMin}, \typ {SubscriptShiftDown}, \typ {SubscriptTopMax},
+\typ {SuperscriptBaselineDropMax}, \typ {SuperscriptBottomMaxWithSubscript}, \typ
+{SuperscriptBottomMin}, \typ {SuperscriptShiftUp} and \typ
+{SuperscriptShiftUpCramped}?
+
+Just for the record, here are the (font related) ones we added so far. A set of
+prime related constants similar to the script ones: \typ {PrimeRaisePercent},
+\typ {PrimeRaiseComposedPercent}, \typ {PrimeShiftUp}, \typ
+{PrimeBaselineDropMax}, \typ {PrimeShiftUpCramped}, \typ {PrimeSpaceAfter} and
+\typ {PrimeWidthPercent}. Of course, we also added \typ {SpaceBeforeScript} just
+because we want to be symmetrical in the engine where we also have to deal with
+prescripts.
+
+These we provide for some further limit positioning: \typ {NoLimitSupFactor} and
+\typ {NoLimitSubFactor}; these for delimiters: \typ {DelimiterPercent} and \typ
+{DelimiterShortfall}; and these for radicals in order to compensate for sloping
+shapes: \typ {RadicalKernAfterExtensible} and \typ {RadicalKernBeforeExtensible}
+because we have doublesided radicals.
+
+Finally, there are quite some (horrible) accent tuning parameters: \typ
+{AccentTopShiftUp}, \typ {AccentBottomShiftDown}, \typ
+{FlattenedAccentTopShiftUp}, \typ {FlattenedAccentBottomShiftDown}, \typ
+{AccentBaseDepth}, \typ {AccentFlattenedBaseDepth}, \typ {AccentTopOvershoot},
+\typ {AccentBottomOvershoot}, \typ {AccentSuperscriptDrop}, \typ
+{AccentSuperscriptPercent} and \typ {AccentExtendMargin}, but we tend to move
+some of that to the tweaks on a per accent basis.
+
+Setting these parameters right is not trivial, and also a bit subjective. We might,
+however, assume that for instance the math axis is set right, but alas, when we
+were fixing the less and greater symbols in Lucida Bright Math, we found that all
+symbols actually were designed for a math axis of 325, instead of the given
+value 313, and that difference can be seen!
+
+\startbuffer
+\scale[s=2]{\dm{
+ 2 > -\left\{\frac{1}{1+x^2}\right\}
+}}
+\stopbuffer
+
+\startlinecorrection
+\startcombination[nx=2]
+ \startcontent
+ % \definefontfeature[mathextra][goodies=]
+ \switchtobodyfont[lucidaold]
+ \showglyphs
+ \getbuffer
+ \stopcontent
+ \startcaption
+ Old Lucida
+ \stopcaption
+ \startcontent
+ \switchtobodyfont[lucida]
+ \showglyphs
+ \getbuffer
+ \stopcontent
+ \startcaption
+ New Lucida
+ \stopcaption
+\stopcombination
+\stoplinecorrection
+
+The assumption is that the axis goes trough the middle of
+the minus. Luckily it was relatively easy to fix these two symbols (they also had
+to be scaled, maybe they originate in the text font?) and adapt the
+axis. We still need to check all the other fonts, but it looks like they are okay,
+which is good because the math axis plays an important role in rendering math.
+It is one of the few parameters that has to be present and right. A nice side
+effect of this is that we end up with discussing new (\CONTEXT) features. One
+can for instance shift all non-character symbols down just a little and lower
+the math axis, to get a bit more tolerance in lines with many inline fractions,
+radicals or superscripts, that otherwise would result in interline skips.
+
+A first step in getting out of this mess is to define {\em all} these parameters
+in the goodie file where we fix them anyway. That way we are at least not
+dependent on changes in the font. We are not a word processor so we have way more
+freedom to control matters. And preset font parameters sometimes do more harm
+than good. A side effect of a cleanup can be that we get rid of the evolved mix
+of uppercase and lowercase math control variables and can be more consistent.
+Ever since \LUATEX\ got support for \OPENTYPE, math constants names have been
+mapped and matched to traditional \TEX\ font parameters.
+
+\stopsection
+
+\startsection[title=Metrics]
+
+With metrics we refer to the dimensions and other properties of math glyphs. The
+origin of digital math fonts is definitely Computer Modern and thereby the
+storage of properties is bound to the \TFM\ file format. That format is binary
+and can be loaded fast. It can also be stored in the format, unless you're using
+\LUATEX\ or \LUAMETATEX\ where \LUA\ is the storage format. A \TFM\ file stores
+per character the width, height, depth and italic correction. The file also
+contains font parameters. In math fonts there are extensible recipes and there is
+information about next in size glyphs. The file has kerning and ligature tables
+too.
+
+Given the times \TEX\ evolved in, the format is rather compact. For instance, the
+height, depth and italic correction are shared and indices to three shared values
+are used. There can be 16 heights and depths and 64 italic corrections. That way
+much fits into a memory word.
+
+The documentation tells us that \quotation {The italic correction of a character
+has two different uses. (a)~In ordinary text, the italic correction is added to
+the width only if the \TEX\ user specifies \quote{\type {\/}} after the
+character. (b)~In math formulas, the italic correction is always added to the
+width, except with respect to the positioning of subscripts.} It is this last
+phenomena that gives us some trouble with fonts in \OPENTYPE\ math. The fact that
+traditional fonts cheat with the width and that we add and selectively remove or
+ignore the correction makes for fuzzy code in \LUATEX\ although splitting the
+code paths and providing options to control all this helps a bit. In \LUAMETATEX\
+we have more control but also expect an \OPENTYPE\ font. In \OPENTYPE\ math there
+are italic corrections, and we even have the peculiar usage of it in positioning
+limits. However, the idea was that staircase kerns do the detailed relative
+positioning.
+
+Before we dive into this a bit more, it is worth mentioning that Don Knuth paid a
+lot of attention to details. The italic alphabet in math uses the same shapes as
+the text italic but metrics are different as is shown below. We have also met fonts
+where it looked like the text italics were taken, and where the metrics were handled
+via more excessive italic correction, sometimes combined with staircase kerns that
+basically were corrections for the side bearing. This is why we always come back to
+Latin Modern and Cambria when we investigate fonts: one is based on the traditional
+\TEX\ model, with carefully chosen italic corrections, and the other is based on the
+\OPENTYPE\ model with staircase kerning. They are our reference fonts.
+
+\startlinecorrection
+\startcombination[nx=1,ny=2]
+ \startcontent
+ \definedfont[file:lmroman10italic.otf]%
+ \showglyphs
+ \scale[s=3]{abcdefghijklmnopqrstuvwxyz}
+ \stopcontent
+ \startcaption
+ Latin Modern Roman Italic
+ \stopcaption
+ \startcontent
+ \definedfont[file:latinmodernmath.otf]%
+ \showglyphs
+ \scale[s=3]{𝑎𝑏𝑐𝑑𝑒𝑓𝑔ℎ𝑖𝑗𝑘𝑙𝑚𝑛𝑜𝑝𝑞𝑟𝑠𝑡𝑢𝑣𝑤𝑥𝑦𝑧}
+ \stopcontent
+ \startcaption
+ Latin Modern Math Italic
+ \stopcaption
+\stopcombination
+\stoplinecorrection
+
+In \CONTEXT\ \MKIV\ we played a lot with italic correction in math and there were
+ways to enforce, ignore, selectively apply it, etc. But, because fonts actually
+demand a mixture, in \LUAMETATEX\ we ended up with more extensive runtime
+patching of them. Another reason for this was that math fonts can have weird
+properties. It looks like when these standards are set and fonts are made, the
+font makers can do as they like as long as the average formula comes out right,
+and metrics to some extent resemble a traditional font. However, when testing how
+well a font behaves in a real situation there can be all kind of interferences
+from the macro package: inter|-|atom kerning, spacing corrections macros,
+specific handling of cases, etc. We even see \OPENTYPE\ fonts that seem to
+have the same limited number of heights, depths and italic corrections. And, as a
+consequence we get for instance larger sizes of fences having the same depth for
+all the size variants, something that is pretty odd for an \OPENTYPE\ font with no
+limitations.
+
+The italic correction in traditional \TEX\ math gets added to the width. When a
+subscript is attached to a kernel character it sits tight against that character:
+its position is driven by the width of the kernel. A superscript on the other
+hand is moved over the italic width so that it doesn't overlap or touch the
+likely sticking out bit of the kernel. This means that a traditional font (and
+quite some \OPENTYPE\ math fonts are modelled after Computer Modern) have to find
+compromises of width and italic correction for characters where the subscript is
+supposed to move left (inside the bounding box of the kernel).
+
+The \OPENTYPE\ specification has some vague remarks about applying italic
+correction between the last in a series of slanted shapes and operators, as well
+as positioning limits, and suggests that it relates to relative super- and
+subscript positioning. It doesn't mention that the correction is to be added to
+the width. However, the main mechanism for anchoring script are these top and
+bottom edge kerns. It's why in fonts that provide these, we are unlikely to find
+italic correction unless it is used for positioning limits.
+
+It is for that reason that an engine can produce reasonable results for fonts
+that either provide italics or provide kerns for anchoring: having both on the
+same glyph would mean troubles. It means that we can configure the engine options
+to add italic correction as well as kerns, assuming distinctive usage of those
+features. For a font that uses both we need to make a choice (this is possible,
+since we can configure options per font). But that will never lead to always nicely
+typeset math. In fact, without tweaks many fonts will look right because in
+practice they use some mixture. But we are not aiming at partial success, we want
+all to look good.
+
+Here is another thing to keep in mind (although now we are guessing a bit). There
+is a limited number of heights and depths in \TEX\ fonts possible (16), but four
+times as many italic corrections can be defined (64). Is it because Don Knuth
+wanted to properly position the sub- and subscripts? Adding italic correction to
+the width is pretty safe: shapes should not overlap. Choosing the right width for
+a subscript needs more work because it's is more visual. In the end we have a
+width that is mostly driven by superscript placement! That also means that as
+soon as we remove the italic correction things start looking bad. In fact,
+because also upright math characters have italic correction the term \quote
+{italic} is a bit of a cheat: it's all about script positioning and has little to
+do with the slope of the shapes.
+
+One of the reasons why for instance spacing between an italic shape and an
+upright one in \TEX\ works out okay is that in most cases they come from a
+different font, which can be used as criterium for keeping the correction;
+between a sequence of same|-|font characters it gets removed. However, in
+\OPENTYPE\ math there is a good chance that all comes from the same font (at
+least in \CONTEXT), unless one populates many families as in traditional \TEX. We
+have no clue how other macro packages deal with this but it might well be the
+case that using many families (one for each alphabet) works better in the end.
+The engine is really shape and alphabet agnostic, but one can actually wonder if
+we should add a glyph property indicating the distinctive range. It would provide
+engine level control over a run of glyphs (like multiplying a variable
+represented by a greek alpha by another variable presented by an upright b).
+
+But glyph properties cannot really be used here because we are still dealing with
+characters when the engine transforms the noad list into a node list. So, when we
+discussed this, we started wondering how the engine could know about a specific
+shape (and tilt) property at all, and that brought us to pondering about an
+additional axis of options. We already group characters in classes, but we can
+also group them with properties like \typ {tilted}, \typ {dotless}, \typ {bold}.
+When we pair atoms we can apply options, spacing and such based on the specific
+class pair, and we can do something similar with category pairs. It basically
+boils down to for instance \type {\mccode} that binds a character to a category.
+Then we add a command like \typ {\setmathcategorization} (analogue to \typ
+{\setmathspacing}) that binds options to pairs of categories. An easier variant
+of this might be to let the \type {\mccode} carry a (bit)set of options that then
+get added to the already existing options that can be bound to character noads as
+we create them. This saves us some configuration. Deciding what suits best
+depends on what we want to do: the fact that \TEX\ doesn't do this means that
+probably no one ever gave it much thought, but once we do have this mechanism it
+might actually trigger demand, if only by staring at existing documents where
+characters of a different kind sit next to each other (take this \quote {a}
+invisible times \quote {x}). It would not be the first time that (in \CONTEXT)
+the availability of some feature triggers creative (ab)usage.
+
+Because the landscape has settled, because we haven't seen much fundamental
+evolution in \OPENTYPE\ math, because in general \TEX\ math doesn't really
+evolve, and because \CONTEXT\ in the past has not been seen as suitable for
+ math, we can, as mentioned before, basically decide what approach we
+follow. So, that is why we can pick up on this italic correction in a more
+drastic way: we can add the correction to the width, thereby creating a nicely
+bounded glyph, and moving the original correction to the right bottom kern, as
+that is something we already support. In fact, this feature is already available,
+we only had to add setting the right bottom kern. The good news is that we don't
+need to waste time on trying to get something extra in the font format, which is
+unlikely to happen anyway after two decades.
+
+It is worth noticing that when we were exploring this as part of using \METAPOST\
+to analyze and visualize these aspects, we also reviewed the \typ {wipeitalics}
+tweak and wondered if, in retrospect, it might be a dangerous one when applied to
+alphabets (for digits and blackboard bold letters it definitely makes
+sense): it can make traditional super- and subscript anchoring less optimal.
+However, for some fonts we found that improper bounding boxes can badly interfere
+anyway: for instance the upright \quote {f} in EBGaramond sticks out left and
+right, and has staircase kerns that make scripts overlap. The right top of the
+shape sticks out a lot and that is because the text font variant is used. We already decided to
+add a \typ {moveitalics} tweak that moves italic kerns into the
+width and then setting a right bottom kern that compensates it that can be a
+pretty good starting point for our further exploration of optimal kerns at the
+corners. That tweak also fixes the side bearings (negative llx) and compensates
+left kerns (when present) accordingly. An additional \typ {simplifykerns} tweak
+can later migrate staircase kerns to simple kerns.
+
+So, does that free us from tweaks like \typ {dimensions} and \typ {kerns}? Not
+completely. But we can forget about the italic correction
+in most cases. We have to set up less lower right kerns and maybe correct a few.
+It is just a more natural solution. So how about these kerns that we need to
+define? After all, we also have to deal with proper top kerns, and like to add
+kerns that are not there simply because the mentioned comprise between width,
+italic and the combination was impossible. More about that in the next section.
+
+\stopsection
+
+\startsection[title=Kerning]
+
+In the next pictures we will try to explain more visual what we have in mind and
+are experimenting with as we write this. In the traditional approach we have
+shapes that can communicate the width, height, depth and italic correction to the
+engine so that is what the engine can work with. The engine also has the
+challenge to anchor subscripts and superscripts in a visual pleasing way.
+
+\startMPdefinitions
+ numeric UsedUnit ; UsedUnit = 1mm ;
+ numeric UsedWidth ; UsedWidth := 10UsedUnit ;
+ numeric UsedItalic ; UsedItalic := 2UsedUnit ;
+ numeric UsedScript ; UsedScript = 5UsedUnit;
+ picture LeftCharA ; LeftCharA := image(
+ draw origin -- (UsedWidth,UsedWidth)
+ withpen pencircle scaled 2UsedUnit
+ withcolor .4white ;
+ path p ; p := boundingbox currentpicture ;
+ draw rightboundary currentpicture
+ bottomenlarged -5UsedUnit
+ withpen pencircle scaled .5UsedUnit ;
+ setbounds currentpicture to p ;
+ draw origin
+ withpen pencircle scaled 1UsedUnit
+ withcolor .1white ;
+ setbounds currentpicture to boundingbox currentpicture
+ leftenlarged -UsedItalic
+ rightenlarged -UsedItalic ;
+ draw boundingbox currentpicture
+ withpen pencircle scaled .1UsedUnit ;
+ ) ;
+ picture RightCharA ; RightCharA := image(
+ draw (0,UsedWidth) -- (UsedWidth,0)
+ withpen pencircle scaled 2UsedUnit
+ withcolor .6white ;
+ path p ; p := boundingbox currentpicture ;
+ draw rightboundary currentpicture
+ bottomenlarged -5UsedUnit
+ withpen pencircle scaled .5UsedUnit ;
+ setbounds currentpicture to p ;
+ draw origin
+ withpen pencircle scaled 1UsedUnit
+ withcolor .1white ;
+ setbounds currentpicture to boundingbox currentpicture
+ leftenlarged -UsedItalic
+ rightenlarged -UsedItalic ;
+ draw boundingbox currentpicture
+ withpen pencircle scaled .1UsedUnit ;
+ ) ;
+ picture LeftCharB ; LeftCharB := image(
+ draw origin -- (UsedWidth,UsedWidth)
+ withpen pencircle scaled 2UsedUnit
+ withcolor .4white ;
+ path p ; p := boundingbox currentpicture ;
+ draw origin
+ withpen pencircle scaled 1UsedUnit
+ withcolor .1white ;
+ draw boundingbox currentpicture
+ withpen pencircle scaled .1UsedUnit ;
+ draw lrcorner p
+ shifted (-UsedItalic,0)
+ withpen pencircle scaled 1UsedUnit
+ withcolor .1white ;
+ draw urcorner p
+ withpen pencircle scaled 1UsedUnit
+ withcolor .1white ;
+ setbounds currentpicture to p ;
+ ) ;
+ picture RightCharB ; RightCharB := image(
+ draw (0,UsedWidth) -- (UsedWidth,0)
+ withpen pencircle scaled 2UsedUnit
+ withcolor .6white ;
+ path p ; p := boundingbox currentpicture ;
+ draw origin
+ withpen pencircle scaled 1UsedUnit
+ withcolor .1white ;
+ draw boundingbox currentpicture
+ withpen pencircle scaled .1UsedUnit ;
+ draw lrcorner p
+ shifted (-UsedItalic,0)
+ withpen pencircle scaled 1UsedUnit
+ withcolor .1white ;
+ draw urcorner p
+ withpen pencircle scaled 1mm
+ withcolor .1white ;
+ setbounds currentpicture to p ;
+ ) ;
+ picture SuperScript ; SuperScript := image(
+ draw unitsquare scaled UsedScript
+ shifted (0,-UsedScript/2)
+ ) ;
+ picture SubScript ; SubScript := image(
+ draw unitsquare scaled UsedScript
+ shifted (0,-UsedScript/2)
+ ) ;
+ def WidenResultA =
+ setbounds currentpicture to boundingbox currentpicture
+ leftenlarged 6UsedUnit
+ rightenlarged 6UsedUnit;
+ enddef ;
+ def WidenResultB =
+ setbounds currentpicture to boundingbox currentpicture
+ topenlarged .5UsedScript
+ leftenlarged 6UsedUnit
+ rightenlarged 6UsedUnit;
+ enddef ;
+\stopMPdefinitions
+
+\startlinecorrection
+ \startcombination[nx=3,ny=1]
+ \startcontent
+ \startMPcode
+ draw LeftCharA ;
+ draw RightCharA xshifted (UsedWidth+UsedItalic+3UsedUnit) ;
+ WidenResultA ;
+ \stopMPcode
+ \stopcontent
+ \startcaption
+ two characters
+ \stopcaption
+ \startcontent
+ \startMPcode
+ draw LeftCharA ;
+ draw RightCharA xshifted UsedWidth ;
+ WidenResultA ;
+ \stopMPcode
+ \stopcontent
+ \startcaption
+ width only
+ \stopcaption
+ \startcontent
+ \startMPcode
+ draw LeftCharA ;
+ draw RightCharA xshifted (UsedWidth+UsedItalic) ;
+ WidenResultA ;
+ \stopMPcode
+ \stopcontent
+ \startcaption
+ with italic
+ \stopcaption
+ \stopcombination
+\stoplinecorrection
+
+In this graphic we show two pseudo characters. The shown bounding box indicates
+the width as seen by the engine. An example of such a shape is the math italic~f,
+and as it is used a lot in formulas it is also one of the most hard ones to handle
+when it comes to spacing: in nearly all fonts the right top sticks out and in
+some fonts the left part also does that. Imagine how that works out with scripts,
+fences and preceding characters.
+
+When we put two such characters together they will overlap, and this is why we need
+to add the italic correction. That is also why the \TEX\ documentation speaks in
+terms of \quotation {always add the italic correction to the width}. This also
+means that we need to remove it occasionally, something that you will notice when
+you study for instance the \LUATEX\ source, that has a mix of traditional and
+\OPENTYPE\ code paths. Actually, compensating can either be done by changing the
+width property of a glyph node or by explicitly adding a kern. In \LUAMETATEX\ we
+always add real kerns because we can then trace better.
+
+The last graphic in the above set shows how we compensate the width for the bit
+that sticks out. It also shows that we definitely need to take neighboring shapes
+into account when we determine the width and italic correction, especially when
+the later is {\em not} applied (read: removed).
+
+\startlinecorrection
+ \startcombination[nx=3,ny=1]
+ \startcontent
+ \startMPcode
+ draw LeftCharA ;
+ path p ; p := boundingbox currentpicture ;
+ draw SuperScript
+ shifted urcorner p xshifted UsedScript ;
+ draw SubScript
+ shifted lrcorner p xshifted UsedScript ;
+ WidenResultB ;
+ \stopMPcode
+ \stopcontent
+ \startcaption
+ kernel
+ \stopcaption
+ \startcontent
+ \startMPcode
+ draw LeftCharA ;
+ path p ; p := boundingbox currentpicture ;
+ draw SuperScript
+ shifted urcorner p ;
+ draw SubScript
+ shifted lrcorner p ;
+ WidenResultB ;
+ \stopMPcode
+ \stopcontent
+ \startcaption
+ subscript
+ \stopcaption
+ \startcontent
+ \startMPcode
+ draw LeftCharA ;
+ path p ; p := boundingbox currentpicture ;
+ draw SuperScript
+ shifted urcorner p
+ xshifted UsedItalic ;
+ draw SubScript
+ shifted lrcorner p ;
+ WidenResultB ;
+ \stopMPcode
+ \stopcontent
+ \startcaption
+ superscript
+ \stopcaption
+ \stopcombination
+\stoplinecorrection
+
+Here we anchored a super- and subscript. The subscript position it tight to the
+advance width, again indicated by the box. The superscript however is moved by
+the italic correction and in the engine additional spacing before and after can
+be applied as well, but we leave that for now. It will be clear that when the
+font designer chooses the width and italic correction, the fact that scripts get
+attached has to be taken into account.
+
+\startlinecorrection
+ \startcombination[nx=2,ny=1]
+ \startcontent
+ \startMPcode
+ draw LeftCharB ;
+ draw RightCharB xshifted (UsedWidth+UsedItalic+3UsedUnit) ;
+ WidenResultA ;
+ \stopMPcode
+ \stopcontent
+ \startcaption
+ two characters
+ \stopcaption
+ \startcontent
+ \startMPcode
+ draw LeftCharB ;
+ draw RightCharB xshifted (UsedWidth+UsedItalic) ;
+ WidenResultA ;
+ \stopMPcode
+ \stopcontent
+ \startcaption
+ width only
+ \stopcaption
+ \stopcombination
+\stoplinecorrection
+
+In this graphic we combine the italic correction with the width. Keep in mind
+that in these examples we use tight values but in practice that correction can
+also add some extra right side bearing (white space). This addition is an
+operation that we can do when loading a font. At the same time we also compensate
+the left edge for which we can use the x coordinate of the left corner of the
+glyphs real bounding box. The advance width starts at zero and that corner is
+then left of the origin. By looking at shapes we concluded that in most cases
+that shift is valid for usage in math where we don't need that visual overlap. In
+fact, when we tested some of that we found that the results can be quite horrible
+when you don't do that; not all fonts have left bottom kerning implemented.
+
+The dot at the right is actually indicating the old italic correction. Here we
+let it sit on the edge but as mentioned there can be additional (or maybe less)
+italic correction than tight.
+
+\startlinecorrection
+ \startcombination[nx=3,ny=1]
+ \startcontent
+ \startMPcode
+ draw LeftCharB ;
+ path p ; p := boundingbox currentpicture ;
+ draw SuperScript
+ shifted urcorner p xshifted UsedScript ;
+ draw SubScript
+ shifted lrcorner p xshifted UsedScript ;
+ WidenResultB ;
+ \stopMPcode
+ \stopcontent
+ \startcaption
+ kernel
+ \stopcaption
+ \startcontent
+ \startMPcode
+ draw LeftCharB ;
+ path p ; p := boundingbox currentpicture ;
+ draw SuperScript
+ shifted urcorner p ;
+ draw SubScript
+ shifted lrcorner p ;
+ WidenResultB ;
+ \stopMPcode
+ \stopcontent
+ \startcaption
+ superscript
+ \stopcaption
+ \startcontent
+ \startMPcode
+ draw LeftCharB ;
+ path p ; p := boundingbox currentpicture ;
+ draw SuperScript
+ shifted urcorner p ;
+ draw SubScript
+ shifted (-UsedItalic,0)
+ shifted lrcorner p ;
+ WidenResultB ;
+ \stopMPcode
+ \stopcontent
+ \startcaption
+ subscript
+ \stopcaption
+ \stopcombination
+\stoplinecorrection
+
+Finally we add the scripts here. This time we position the superscript and
+subscript at the top and bottom anchors. The bottom anchor is, as mentioned, the
+old italic correction, and the top one currently just the edge. And this is what
+our next project is about: identify the ideal anchors and use these instead.
+
+In the \CONTEXT\ goodie files (the files that tweak the math fonts runtime) we
+can actually already set these top and bottom anchors and the engine will use
+them when set. These kerns are not to be confused with the more complicated
+staircase kerns. They are much simpler and lightweight. The fact that we already
+have them makes it relatively easy to experiment with this.
+
+It must be noted that we talk about three kinds of kerns: inter character kerns,
+corner kerns and staircase kerns. We can set them all up with tweaks but so far
+we only did that for the most significant ones, like integrals. The question is:
+can we automate this? We should be careful because the bad top accent anchors in
+the \TEXGYRE\ fonts demonstrate how flawed heuristics can be. Interesting is that
+the developers of these font used \METAPOST\ and are highly qualified in that
+area. And for us using \METAPOST\ is also natural!
+
+The approach that we follow is somewhat interactive. When working on the math
+update we like to chat (with zoom) about these matters. We discuss and explore
+plenty and with these kerns we do the same. Because \METAPOST\ produces such nice
+and crispy graphics, and because \METAFUN\ is well integrated into \CONTEXT\ we
+can link all these subsystems and just look at what we get. A lot is about
+visualization: if we discuss so called \quote {grayness} in the perspective of
+kerning, we end up with calculating areas, then look at what it tells us and as a
+next step figure out some heuristic. And of course we challenge each other into
+new trickery.
+
+% THIS WILL BECOME A MODULE!
+
+\startluacode
+local formatters = string.formatters
+
+local glyph = nil
+local mpdata = nil
+
+local f_boundingbox = formatters["((%N,%N)--(%N,%N)--(%N,%N)--(%N,%N)--cycle)"]
+local f_vertical = formatters["((%N,%N)--(%N,%N))"]
+
+function mp.lmt_glyphshape_start(id,character)
+ if type(id) == "string" then
+ id = fonts.definers.internal({ name = id } ,"<module:fonts:shapes:font>")
+ end
+ local fontid = (id and id ~= 0 and id) or font.current()
+ local shapedata = fonts.hashes.shapes[fontid] -- by index
+ local characters = fonts.hashes.characters[fontid] -- by unicode
+ local descriptions = fonts.hashes.descriptions[fontid] -- by unicode
+ local shapeglyphs = shapedata.glyphs or { }
+ if type(character) == "string" and character ~= "" then
+ local hex = string.match(character,"^0x(.+)")
+ if hex then
+ character = tonumber(hex,16)
+ else
+ character = utf.byte(character)
+ end
+ else
+ character = tonumber(character)
+ end
+ local chardata = characters[character]
+ local descdata = descriptions[character]
+ if chardata then
+ glyph = shapeglyphs[chardata.index]
+ if glyph and (glyph.segments or glyph.sequence) and not glyph.paths then
+ local units = shapedata.units or 1000
+ local factor = 100/units
+ local width = (descdata.width or 0) * factor
+ local height = descdata.boundingbox[4] * factor
+ local depth = descdata.boundingbox[2] * factor
+ local math = descdata.math
+ local italic = (math and math.italic or 0) * factor
+ local accent = (math and math.accent or 0) * factor
+ mpdata = {
+ paths = fonts.metapost.paths(glyph,factor),
+ boundingbox = fonts.metapost.boundingbox(glyph,factor),
+ baseline = fonts.metapost.baseline(glyph,factor),
+ width = width,
+ height = height,
+ depth = depth,
+ italic = italic,
+ accent = accent,
+ usedbox = f_boundingbox(0,depth,width,depth,width,height,0,height),
+ usedline = f_vertical(0,0,width,0),
+ }
+ end
+ else
+ print("NO",id,character)
+ end
+end
+
+function mp.lmt_glyphshape_stop()
+ glyph = nil
+ mpdata = nil
+end
+
+function mp.lmt_glyphshape_n()
+ if mpdata then
+ mp.print(#mpdata.paths)
+ else
+ mp.inject.numeric(0)
+ end
+end
+
+function mp.lmt_glyphshape_path(i)
+ if mpdata then
+ mp.print(mpdata.paths[i])
+ else
+ mp.inject.pair(0,0)
+ end
+end
+
+function mp.lmt_glyphshape_boundingbox()
+ if mpdata then
+ mp.print(mpdata.boundingbox)
+ else
+ mp.inject.pair(0,0)
+ end
+end
+function mp.lmt_glyphshape_usedbox()
+ if mpdata then
+ mp.print(mpdata.usedbox)
+ else
+ mp.inject.pair(0,0)
+ end
+end
+
+function mp.lmt_glyphshape_baseline()
+ if mpdata then
+ mp.print(mpdata.baseline)
+ else
+ mp.inject.pair(0,0)
+ end
+end
+function mp.lmt_glyphshape_usedline()
+ if mpdata then
+ mp.print(mpdata.usedline)
+ else
+ mp.inject.pair(0,0)
+ end
+end
+
+function mp.lmt_glyphshape_width () mp.print(mpdata and mpdata.width or 0) end
+function mp.lmt_glyphshape_depth () mp.print(mpdata and mpdata.depth or 0) end
+function mp.lmt_glyphshape_height() mp.print(mpdata and mpdata.height or 0) end
+function mp.lmt_glyphshape_italic() mp.print(mpdata and mpdata.italic or 0) end
+function mp.lmt_glyphshape_accent() mp.print(mpdata and mpdata.accent or 0) end
+
+\stopluacode
+
+\startMPdefinitions
+ presetparameters "glyphshape" [
+ % id = "",
+ % character = "",
+ shape = true,
+ boundingbox = false,
+ baseline = false,
+ usedline = true,
+ usedbox = true,
+ ] ;
+
+def lmt_glyphshape = applyparameters "glyphshape" "lmt_do_glyphshape" enddef ;
+
+vardef glyphshape_start(expr id, character) =
+ lua.mp.lmt_glyphshape_start(id, character) ;
+enddef ;
+
+vardef glyphshape_stop = lua.mp.lmt_glyphshape_stop() ; enddef ;
+vardef glyphshape_n = lua.mp.lmt_glyphshape_n() enddef ;
+vardef glyphshape_path(expr i) = lua.mp.lmt_glyphshape_path(i) enddef ;
+vardef glyphshape_boundingbox = lua.mp.lmt_glyphshape_boundingbox() enddef ;
+vardef glyphshape_baseline = lua.mp.lmt_glyphshape_baseline() enddef ;
+vardef glyphshape_usedbox = lua.mp.lmt_glyphshape_usedbox() enddef ;
+vardef glyphshape_usedline = lua.mp.lmt_glyphshape_usedline() enddef ;
+vardef glyphshape_width = lua.mp.lmt_glyphshape_width() enddef ;
+vardef glyphshape_height = lua.mp.lmt_glyphshape_height() enddef ;
+vardef glyphshape_depth = lua.mp.lmt_glyphshape_depth() enddef ;
+vardef glyphshape_italic = lua.mp.lmt_glyphshape_italic() enddef ;
+vardef glyphshape_accent = lua.mp.lmt_glyphshape_accent() enddef ;
+
+vardef lmt_do_glyphshape =
+ image (
+ pushparameters "glyphshape" ;
+ lua.mp.lmt_glyphshape_start(getparameter "id", getparameter "character") ;
+ if getparameter "shape" :
+ draw for i=1 upto lua.mp.lmt_glyphshape_n() :
+ lua.mp.lmt_glyphshape_path(i) &&
+ endfor cycle ;
+ fi ;
+ if getparameter "boundingbox" :
+ draw
+ lua.mp.lmt_glyphshape_boundingbox()
+ withcolor red
+ ;
+ fi ;
+ if getparameter "usedline" :
+ draw
+ lua.mp.lmt_glyphshape_usedline()
+ withcolor green
+ ;
+ fi ;
+ if getparameter "usedbox" :
+ draw
+ lua.mp.lmt_glyphshape_usedbox()
+ withcolor blue
+ ;
+ fi ;
+ lua.mp.lmt_glyphshape_stop() ;
+ popparameters ;
+ )
+enddef ;
+
+\stopMPdefinitions
+
+\startplacefigure[location=none]
+\startMPcode[offset=1dk]
+picture leftchar ;
+picture rightchar ;
+path leftbbox ;
+path rightbbox ;
+numeric leftitalic ;
+numeric rightitalic ;
+numeric leftaccent ;
+numeric rightaccent ;
+
+numeric N ; N := 50 ;
+
+glyphshape_start("file:texgyrebonum-math.otf", "0x1D453") ;
+ leftchar := image (draw for i=1 upto glyphshape_n : glyphshape_path(i) && endfor cycle ;) ;
+ leftbbox := glyphshape_usedbox ;
+ leftaccent := glyphshape_accent ;
+ leftitalic := xpart urcorner leftbbox - glyphshape_italic ;
+glyphshape_stop ;
+glyphshape_start("file:texgyrebonum-math.otf", "0x1D45A") ;
+ rightchar := image (draw for i=1 upto glyphshape_n : glyphshape_path(i) && endfor cycle ;) ;
+ rightbbox := glyphshape_usedbox ;
+ rightaccent := glyphshape_accent ;
+ rightitalic := xpart urcorner rightbbox - glyphshape_italic ;
+glyphshape_stop ;
+
+rightchar := rightchar xshifted (xpart lrcorner leftbbox) ;
+rightbbox := rightbbox xshifted (xpart lrcorner leftbbox) ;
+
+rightaccent := rightaccent + xpart lrcorner leftbbox ;
+rightitalic := rightitalic + xpart lrcorner leftbbox ;
+
+numeric d ; d := (xpart lrcorner leftbbox) - leftitalic ;
+rightchar := rightchar shifted (d,0);
+rightbbox := rightbbox shifted (d,0);
+
+draw leftbbox withcolor 0.5white ;
+draw rightbbox withcolor 0.5white ;
+draw leftchar withpen pencircle scaled 1 ;
+draw rightchar withpen pencircle scaled 1 ;
+
+numeric miny, maxy ;
+
+miny := max(ypart lrcorner leftbbox, ypart llcorner rightbbox) ;
+maxy := min(ypart urcorner leftbbox, ypart ulcorner rightbbox) ;
+
+path testv ; testv := ((0,miny) -- (0,maxy)) xshifted (xpart lrcorner leftbbox) ;
+
+% % testv := testv shifted (d,0);
+% draw testv withcolor darkred ;
+
+path midpath, leftintersections, rightintersections ;
+pair leftintersection[], rightintersection[] ;
+
+numeric yta ; yta := 0 ;
+numeric minl ; minl := 1000 ;
+
+for i = 1 upto (N-1) :
+ midpath := (0, ypart point (i/N) along testv) -- (xpart urcorner rightbbox, ypart point (i/N) along testv);
+ for j within leftchar :
+ midpath := midpath cutbeforelast pathpart j ;
+ endfor
+ for j within rightchar :
+ midpath := midpath cutafterfirst pathpart j ;
+ endfor
+
+ if ( (i = 1) or ((xpart point 1 of midpath) - (xpart point 0 of midpath) < minl) ) :
+ minl := (xpart point 1 of midpath) - (xpart point 0 of midpath) ;
+ fi
+
+ if ((xpart point 0 of midpath) < eps) or ((xpart point 1 of midpath) > ((xpart urcorner rightbbox) - eps)) :
+ draw midpath withpen pencircle scaled 1 withcolor 0.1[white,darkgreen] withtransparency (1,0.5) ;
+ midpath := (point 0 of midpath) && cycle ;
+ fi
+
+ draw midpath withcolor 0.4[white,darkgreen] ;
+ draw point 0 of midpath withpen pencircle scaled 1 withcolor darkgreen ;
+ draw point 1 of midpath withpen pencircle scaled 1.25 withcolor darkgreen ;
+
+ yta := yta + (1/N)*((xpart point 1 of midpath) - (xpart point 0 of midpath)) ;
+endfor
+
+drawarrow (origin -- ((xpart lrcorner leftbbox) - leftitalic,0)) shifted (urcorner leftbbox) withcolor "orange" ;
+drawarrow (origin -- ((xpart lrcorner rightbbox) - rightitalic - d,0)) shifted (urcorner rightbbox) withcolor "orange" ;
+
+% draw (leftaccent, (ypart urcorner leftbbox )) withcolor "darkblue" withpen pencircle scaled 3 ;
+% draw (rightaccent + d, (ypart urcorner rightbbox)) withcolor "darkblue" withpen pencircle scaled 3 ;
+
+\stopMPcode
+
+\stopplacefigure
+
+
+We are sure that getting this next stage in the perfection of math typesetting in
+\CONTEXT\ and \LUAMETATEX\ will take quite some time, but the good news is that
+all machinery is in place. We also have to admit that it all might not work out
+well, so that we stick to what we have now. But at least we had the fun then. And
+it is also a nice example of both applying mathematics and programming graphics.
+
+That said, if it works out well, we can populate the goodie files with output
+from \METAPOST, tweak a little when needed, and that saves us some time. One
+danger is that when we try to improve rendering the whole system also evolves
+which in turn will give different output, but we can always implement all this as
+features because after all \CONTEXT\ is very much about configuration. And it
+makes nice topics for articles and talks too!
+
+The kerns discussed in the previous paragraphs are not the ones that we
+find in \OPENTYPE\ fonts. There we have \quote {staircase} kerns that stepwise go
+up or down by height and kern. So, one can have different kerns depending on the
+height and sort of follow the shape. This permits quite precise kerning between
+for instance the right bottom of a kernel and left top of a subscript. So how is
+that used in practice? The reference font Cambria has these kerns but close
+inspection shows that these are not that accurate. Fortunately, we never enter
+the danger zone with subscripts, because other parameters prevent that. If we look
+at for instance Lucida and Garamond, then we see that their kerns are mostly used
+as side bearing, and not really as staircase kerns.
+
+\usemodule[s][fonts-shapes]
+
+\startlinecorrection
+\startcombination[nx=5,ny=1]
+ \startcontent
+ \ShowGlyphShape{name:cambria-math}{100bp}{0x1D6FD}
+ \stopcontent
+ \startcaption
+ \type {U+1D6FD}
+ \stopcaption
+ \startcontent
+ \ShowGlyphShape{name:cambria-math}{100bp}{0x003A4}
+ \stopcontent
+ \startcaption
+ \type {U+003A4}
+ \stopcaption
+ \startcontent
+ \ShowGlyphShape{name:cambria-math}{100bp}{0x1D4CC}
+ \stopcontent
+ \startcaption
+ \type {U+1D4CC}
+ \stopcaption
+ \startcontent
+ \ShowGlyphShape{name:cambria-math}{100bp}{0x1D6B8}
+ \stopcontent
+ \startcaption
+ \type {U+1D6B8}
+ \stopcaption
+ \startcontent
+ \ShowGlyphShape{name:cambria-math}{100bp}{0x1D70C}
+ \stopcontent
+ \startcaption
+ \type {U+1D70C}
+ \stopcaption
+\stopcombination
+\stoplinecorrection
+
+In these figures you see a few glyphs from cambria with staircase kerns and
+although we show them small you will notice that some kern boundaries touch the
+shape. As subscripts never go that high it goes unnoticed but it also shows that
+sticking to the lowest boundary makes sense.
+
+We conclude that we can simplify these kerns, and just transform them into our
+(upto four) corner kerns. It is unlikely that Cambria gets updates and that other
+fonts become more advanced. One can even wonder if multiple steps really give
+better results. The risk of overlap increases with more granularity because not
+every pair of glyphs is checked. Also, the repertoire of math characters will
+likely not grow and include shapes that differ much from what we can look at now.
+Reducing these kerns to simple ones, that can easily be patched at will in a
+goodie file, has advantages. We can even simplify the engine.
+
+\stopsection
+
+\startsection[title=Conclusion]
+
+So how can we summarize the above? The first conclusion is that we can only get
+good results when we runtime patch fonts to suite the engine and our (\CONTEXT)
+need. The second conclusion is that we should seriously consider to drop (read:
+ignore) most math font parameter and|/|or to reorganize them. There is no
+need to be conforming, because these parameters are often not that well
+implemented (thumb in mouth). The third conclusion (or observation) is that we
+should get rid of the excessive use of italic correction, and go for our new
+corner kerns instead. Last, we can conclude that it makes sense to explore how we
+can use \METAPOST\ to analyze the shapes in such a way that we can improve inter
+character kerning, corner kerns and maybe even, in a limited way, staircase kerns.
+
+And, to come back to accents: very few characters need a top kern. Most can be
+handled with centered anchors, and we need tweaks for margins and overshoot
+anyway. The same is true for many other tweaks: they are there to stay.
+
+This is how we plan to go forward:
+
+\startitemize[packed]
+ \startitem
+ We pass no italic corrections in the math fonts to the engine,
+ but instead we have four dedicated simple corner kerns, top and
+ bottom anchors, and we also compensate negative left side bearing. We
+ should have gone that route earlier (as follow up on a \MKIV\ feature)
+ but were still in some backward compatibility mindset.
+ \stopitem
+ \startitem
+ The \LUAMETATEX\ math engine might then be simplified by removing all
+ code related to italic correction. Of course it hurts that we spent so
+ much time on that over the years. We can anyway disable engine options
+ related to italic correction in the \CONTEXT\ setup. Of course the engine
+ is less old school generic then but that is the price of progress.
+ \stopitem
+ \startitem
+ A default goodie file is applied that takes care of this when no goodie
+ file is provided. We could do some in the engine, but there is no real
+ need for that. We can simplify the mid 2022 goodie files because we have
+ to fix less glyphs.
+ \stopitem
+ \startitem
+ If we ever need italic correction (that is: backtrack) then we use the
+ (new) \type {\mccode} option code that can identity sloped shapes. But,
+ given that ignoring the correction between sloped shapes looks pretty bad,
+ we can as well forget about this. After all, italic correction never
+ really was about correcting italics, but more about anchoring scripts.
+ \stopitem
+ \startitem
+ Staircase kerns can be reduced to simple corner kerns and the engine can
+ be simplified a bit more. In the end, all we need is true widths and simple
+ corner kerns.
+ \stopitem
+ \startitem
+ We reorganize the math parameters and get rid of those that are not
+ really font design dependent. This also removes a bit of overlap. This will
+ be done as we document.
+ \stopitem
+ \startitem
+ Eventually we can remove tweaks that are no longer needed in the new
+ setup, which is a good thing as it also save us some documenting and
+ maintenance.
+ \stopitem
+\stopitemize
+
+All this will happen in the perspective of \CONTEXT\ and \LUAMETATEX\ but we
+expect that after a few years of usage we can with confidence come to some
+conclusions that can trickle back in the other engines so that other macro
+packages can benefit from a somewhat radical different but reliable approach to
+math rendering, one that works well with the old and new fonts.
+
+\stopsection
+
+\stopchapter
+
+\stopcomponent