% language=us runpath=texruns:manuals/luametatex \environment luametatex-style \startdocument[title=Constructions] \startluacode local styles = tex.getmathstylevalues () styles = table.swapped(styles,styles) local parameters = tex.getmathparametervalues() parameters = table.swapped(parameters,parameters) local variants = tex.getmathvariantvalues () variants = table.swapped(variants,variants) local presets = tex.getmathvariantpresets () presets = table.swapped(presets,presets) -- inspect(presets) -- inspect(presets) function document.printmathpresets() context.starttabulate { "||||" } context.FL() context.BC() context("construct") context.BC() context("value") context.BC() context("preset name") context.BC() context.NR() context.TL() for parameter=parameters.overlinevariant,parameters.stackvariant do local value = tex.getmath(parameter,"display") local preset = variants[presets[value]] context.NC() context.type("\\Umath"..parameters[parameter]) context.NC() context("0x%08X",value) context.NC() context(preset) context.NC() context.NR() end context.LL() context.stoptabulate() end function document.printmathvariants() for parameter=parameters.overlinevariant,parameters.stackvariant do for style=styles.display,styles.crampedscriptscript do local p, s = tex.getmathstylevariant(style,parameter) if p and s then logs.report("mathvariants","%-24s %-20s %-18s %-20s",parameters[parameter],styles[style],variants[p],styles[s]) end end end end function document.showmathvariant(variant) local parameter = type(variant) == "string" and parameters[variant] or variant context.startsubsubsubject { title = variant } context.starttabulate { "||T||" } context.BC() context("current style") context.BC() context("mapping") context.BC() context("used style") context.BC() context.NR() context.ML() for style=styles.display,styles.crampedscriptscript do local p, s = tex.getmathstylevariant(style,parameter) if p and s then context.NC() context(styles[style]) context.NC() context("0x%08X",p) context.NC() context(styles[s]) context.NC() context.NR() end end context.stoptabulate() context.stopsubsubsubject() end \stopluacode \startsection[title={Introduction}] This is more a discussion of the way some constructs in for instance math work. It will never be exhausting and mostly is for our own usage. We don't discuss all the options bit many are interfaced in higher level macros in \CONTEXT. This chapter will gradually grow, depending on time and mood. \stopsection \startsection[title=Boxes] Boxes are very important in \TEX. We have horizontal boxes and vertical boxes. When you look at a page of text, the page itself is a vertical box, and among other things it packs lines that are themselves horizontal boxes. The lines that make a paragraph are the result of breaking a long horizontal box in smaller pieces. \startlinecorrection \ruledvbox \bgroup \hsize 20em \showmakeup[line] \showboxes This is a vertical box. It has a few lines of text that started out as one long line but has been broken in pieces. Doing this as good as possible is one of \TEX's virtues. \egroup \stoplinecorrection There is a low level manual on boxes so here we can limit the discussion to basics. A box is in \TEX\ speak a node. In traditional \TEX\ it has a width, height, depth and shift. \startlinecorrection \startMPcode numeric wd ; wd := 24 ; numeric ht ; ht := 7 ; numeric dp ; dp := 3 ; path body ; body := unitsquare xyscaled (wd, ht+dp) shifted (0,-dp) ; path line ; line := (0,0) -- (wd,0) ; draw line withcolor "middlegray" ; draw body withcolor "darkred" ; currentpicture := currentpicture scaled 5 ; \stopMPcode \stoplinecorrection Here we see a box and the gray line is called the baseline, the height goes up and the depth goes down. Normally the height and depth are determined by what goes in the box but they can be changed as we like. \startbuffer \setbox\scratchboxone\ruledhpack{SHIFT 1} \setbox\scratchboxtwo\ruledhpack{SHIFT 2} \boxshift\scratchboxtwo 1ex \dontleavehmode \box\scratchboxone\box\scratchboxtwo \setbox\scratchboxone\ruledvpack{SHIFT 3} \setbox\scratchboxtwo\ruledvpack{SHIFT 4} \boxshift\scratchboxtwo 1ex \box\scratchboxone\box\scratchboxtwo \stopbuffer \typebuffer In this example you'll notice that the shift depends on the box being horizontal or vertical. The primitives \type {\raise}, \type {\lower}, \type {\moveleft} and \type {\moveright} can be used to shift a box. \startlinecorrection \getbuffer \stoplinecorrection The reason why we have the shift property is that it is more efficient than wrapping a box in another box and shifting with kerns. In that case we also have to go via a box register so that we can manipulate the final dimensions. Another advantage is that the engine can use shifts to position for instance elements in a math formula and even the par builder used shifts to deal with positioning the lines according to shape and margin. In \LUAMETATEX\ the later is no longer the case. Inside a box there can be mark (think running headers), insert (think footnotes) and adjust (think injecting something before or after the current line) nodes. The par builder will move this from inside the box to between the lines but when boxes are nested too deeply this won't happen and they get lost. In \LUAMETATEX\ these objects do bubble up because we make them box properties. So, in addition to the dimensions and shift a box also has migration fields. In the low level manuals you can find examples of accessing various properties of boxes so here we stick to a short description. The reason for mentioning them is that it gives you an idea of what goes on in the engine. \starttabulate \FL \BC field \BC usage \NC \NR \TL \NC \type {width} \NC the (used) width \NC \NR \NC \type {height} \NC the (used) height \NC \NR \NC \type {depth} \NC the (used) depth \NC \NR \NC \type {shift_amount} \NC the shift (right or down) \NC \NR \ML \NC \type {list} \NC pointer to the content \NC \NR \ML \NC \type {glue_order} \NC the calculated order of glue stretch of shrink \NC \NR \NC \type {glue_sign} \NC the determined sign of glue stretch of shrink \NC \NR \NC \type {glue_set} \NC the calculated multiplier for glue stretch or shrink \NC \NR \ML \NC \type {geometry} \NC a bit set registering manipulations \NC \NR \NC \type {orientation} \NC positional manipulations \NC \NR \NC \type {w_offset} \NC used in horizontal movement calculations \NC \NR \NC \type {h_offset} \NC used in vertical movement calculations \NC \NR \NC \type {d_offset} \NC used in vertical movement calculations \NC \NR \NC \type {x_offset} \NC a horizontal shift independent of dimensions \NC \NR \NC \type {y_offset} \NC a vertical shift independent of dimensions \NC \NR \NC \type {axis} \NC the math axis \NC \NR \ML \NC \type {dir} \NC the direction the box goes to (l2r or r2l) \NC \NR \NC \type {package_state} \NC a bitset indicating how the box came to be as it is \NC \NR \NC \type {index} \NC a (system dependent) identifier \NC \NR \ML \NC \type {pre_migrated} \NC content bound to the box that eventually will be injected \NC \NR \NC \type {post_migrated} \NC idem \NC \NR \NC \type {pre_adjusted} \NC idem \NC \NR \NC \type {post_adjusted} \NC idem \NC \NR \ML \NC \type {source_anchor} \NC an identifier bound to the box \NC \NR \NC \type {target_anchor} \NC idem \NC \NR \NC \type {anchor} \NC a bitset indicating where and how to anchor \NC \NR \ML \NC \type {except} \NC carried information about additional virtual depth \NC \NR \NC \type {exdepth} \NC additional virtual depth taken into account in the page builder \NC \NR \LL \stoptabulate We have the usual dimension but also extra ones that relate to \typ {\boxxoffset} and \typ {\boxyoffset} (these are virtual) as well as \typ {\boxxmove} and \typ {\boxymove} (these influence dimensions). The \typ {\boxorientation} also gets registered. The state fields carry information that is used in various places, the pre and post fields relate to the mentioned embedded content. Anchors are just there so that a macro package can play with this and excepts refer to an additional dimensions that is looked at in the page builder, for instance in order to prevent a page break at an unlucky spot. It all gives an indication of what we are dealing with. \stopsection \startsection[title=Math style variants] The \LUAMETATEX\ math engine is a follow up on the one in \LUATEX. That one gradually became more configurable in order to deal with both traditional fonts and \OPENTYPE\ fonts. In \LUAMETATEX\ much has been redone, opened up and extended. New mechanisms and constructs have been added. In the process hard coded heuristics with regards to math styles inside constructions were made configurable, a feature that is probably not used much, apart from experimenting. A side effect is that we can show how the engine is set up, so we do that when applicable. % \starttabulate % \NC normal \NC \tohexa8 \mathnormalstylepreset \NC \NR % \NC cramped \NC \tohexa8 \mathcrampedstylepreset \NC \NR % \NC subscript \NC \tohexa8 \mathsubscriptstylepreset \NC \NR % \NC superscript \NC \tohexa8 \mathsuperscriptstylepreset \NC \NR % \NC small \NC \tohexa8 \mathsmallstylepreset \NC \NR % \NC smaller \NC \tohexa8 \mathsmallerstylepreset \NC \NR % \NC numerator \NC \tohexa8 \mathnumeratorstylepreset \NC \NR % \NC denominator \NC \tohexa8 \mathdenominatorstylepreset \NC \NR % \NC doublesuperscript \NC \tohexa8 \mathdoublesuperscriptstylepreset \NC \NR % \stoptabulate \ctxlua{document.printmathpresets()} \stopsection \startsection[title=Math scripts] The basic components in a math formula are characters, accents, fractions, radicals and fences. They are represented in the to be processed node list as noads and eventually are converted in glyph, kern, glue and list nodes. Each noad carries similar but also specific information about its purpose and intended rendering. In \LUAMETATEX\ that is quite a bit more than in traditional \TEX. These noads are often called atoms. The center piece in a noad is called the nucleus. The fact that these noads also can have scripts attached makes them more like molecules. Scripts can be attached to the left and right, high or low. That makes fours of them: pre|/|post super|/|sub scripts. In \LUAMETATEX\ we also have a prime script, which comes on its own, above a post subscript or after the post superscript, if given. \startlinecorrection \startMPcode numeric wd ; wd := 10 ; numeric ht ; ht := 8 ; numeric dp ; dp := 2 ; path nucleus ; nucleus := fullsquare xyscaled (2wd, ht +dp ) shifted (0,-dp ) ; path follower ; follower := fullsquare xyscaled ( wd/3,ht/6+dp/4) shifted (0,-dp ) ; path presubscript ; presubscript := fullsquare xyscaled ( wd, ht/2+dp/2) shifted (0,-dp/2) ; path presuperscript ; presuperscript := fullsquare xyscaled ( wd, ht/2+dp/2) shifted (0,-dp/2) ; path postsubscript ; postsubscript := fullsquare xyscaled ( wd, ht/2+dp/2) shifted (0,-dp/2) ; path postsuperscript ; postsuperscript := fullsquare xyscaled ( wd, ht/2+dp/2) shifted (0,-dp/2) ; path primescript ; primescript := fullsquare xyscaled ( wd/2,ht/2+dp/2) shifted (0,-dp/2) ; presubscript := anchored.lrt (presubscript, llcorner nucleus) shifted (-1,0) ; presuperscript := anchored.lrt (presuperscript, ulcorner nucleus) shifted (-1,0) ; postsubscript := anchored.llft (postsubscript, lrcorner nucleus) shifted ( 1,0) ; postsuperscript := anchored.llft (postsuperscript, urcorner nucleus) shifted ( 1,0) ; primescript := anchored.llft (primescript, urcorner nucleus) shifted (bbwidth postsuperscript + 2,0) ; draw nucleus withcolor "darkgray" ; draw presubscript withcolor "darkred" ; draw presuperscript withcolor "darkgreen" ; draw postsubscript withcolor "darkblue" ; draw postsuperscript withcolor "darkyellow" ; draw primescript withcolor "darkorange" ; draw follower shifted ( .5bbwidth nucleus + bbwidth postsuperscript + bbwidth primescript + 3,0) withcolor "darkgray" ; draw follower shifted (- .5bbwidth nucleus - bbwidth presuperscript - 1,0) withcolor "darkgray" ; draw presubscript shifted ( - bbwidth presubscript - 1,0) withcolor "darkred" ; draw presuperscript shifted ( - bbwidth presuperscript - 1,0) withcolor "darkgreen" ; draw postsubscript shifted ( bbwidth postsubscript + bbwidth primescript + 2,0) withcolor "darkblue" ; draw postsuperscript shifted ( bbwidth postsuperscript + bbwidth primescript + 2,0) withcolor "darkyellow" ; currentpicture := currentpicture scaled 5 ; \stopMPcode \stoplinecorrection Here the raised rectangle represents the prime. The large center piece is the nucleus. Four scripts are attached to the nucleus. The two smaller center pieces indicate follow up atoms. They make it possible to have multiple pre- and postscripts. For single scripts we get combinations like these: \startlinecorrection \startcombination[nx=3,ny=2,distance=4em] {\scale [s=3] {\showglyphs\im { X ^{\tt a} _{\tt b} ^^^{\tt c} ___{\tt d} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { X _{\tt b} ___{\tt d} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { X ^{\tt a} ^^^{\tt c} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { X ' ^{\tt a} _{\tt b} ^^^{\tt c} ___{\tt d} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { X ' _{\tt b} ___{\tt d} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { X ' ^{\tt a} ^^^{\tt c} \mathaxisbelow }}} {} \stopcombination \stoplinecorrection And for multiple (there can be more that two) we get this assembly: \startlinecorrection \startcombination[nx=3,ny=2,distance=4em] {\scale [s=3] {\showglyphs\im { X ^{\tt a} _{\tt b} ^^^{\tt c} ___{\tt d} ^{\tt A} _{\tt B} ^^^{\tt C} ___{\tt D} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { X _{\tt b} ___{\tt d} _{\tt B} ___{\tt D} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { X ^{\tt a} ^^^{\tt c} ^{\tt A} ^^^{\tt C} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { X ' ^{\tt a} _{\tt b} ^^^{\tt c} ___{\tt d} ^{\tt A} _{\tt B} ^^^{\tt C} ___{\tt D} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { X ' _{\tt b} ___{\tt d} _{\tt B} ___{\tt D} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { X ' ^{\tt a} ^^^{\tt c} ^{\tt A} ^^^{\tt C} \mathaxisbelow }}} {} \stopcombination \stoplinecorrection It will be clear that there is quite a bit of code involved in dealing with this because these scripts are not only to be anchored relative to the nucleus but also to each other. The dimensions of the scripts determine for instance how close a combined super and subscript are positioned. \startlinecorrection \startcombination[nx=3,ny=1,distance=2em] {\scale [s=5] {\showglyphs\im { X _{\tt p} \mathaxisbelow }}} {} {\scale [s=5] {\showglyphs\im { X ^{\tt p} _{\tt p} \mathaxisbelow }}} {} {\scale [s=5] {\showglyphs\im { X ^{\tt p} \mathaxisbelow }}} {} \stopcombination \stoplinecorrection The rendering of scripts involves several parameters, of which some relate to font parameters. In \LUAMETATEX\ we have a few more variables and we also overload font parameters, if only because only a few make sense and it looks like font designers just copy values from the first available fonts so in the end we can as well use our own preferred values. The following parameters play a role in rendering the shown assembly, The traditional \TEX\ engine expects a math font to set quite some parameters for positioning the scripts but has no concept of prescripts and neither has \OPENTYPE. This is why we have extra parameters (and for completeness we also have them for the post scripts). One can wonder of font parameters make sense here because in the end we can decide for a better visual result with different ones. After all, assembling scripts is not really what fonts are about. \starttabulate[||||||] \FL \BC engine parameter \BC target \BC open type font \BC tex font \BC \NR \TL \NC subscriptshiftdrop \NC post \NC SubscriptBaselineDropMin \NC subdrop \NC \NR \NC subscriptshiftdown \NC post \NC SubscriptShiftDown \NC sub1 \NC \NR \NC subscriptsuperscriptshiftdown \NC post \NC SubscriptShiftDown[WithSuperscript] \NC sub2 \NC \NR \NC subscriptsuperscriptvgap \NC post \NC SubSuperscriptGapMin \NC 4 rulethickness \NC \NR \NC subscripttopmax \NC post \NC SubscriptTopMax \NC 4/5 xheight \NC \NR \NC superscriptshiftdrop \NC post \NC SuperscriptBaselineDropMax \NC supdrop \NC \NR \NC superscriptbottommin \NC post \NC SuperscriptBottomMin \NC 1/4 xheight \NC \NR \NC superscriptshiftup \NC post \NC SuperscriptShiftUp[Cramped] \NC sup1 sup2 sup3 \NC \NR \NC superscriptsubscriptbottommax \NC post \NC SuperscriptBottomMaxWithSubscript \NC 4/5 xheight \NC \NR \NC \llap{\star\space}primeraise \NC prime \NC PrimeRaisePercent \NC \NC \NR \NC \llap{\star\space}primeraisecomposed \NC prime \NC PrimeRaiseComposedPercent \NC \NC \NR \NC \llap{\star\space}primeshiftup \NC prime \NC PrimeShiftUp[Cramped] \NC \NC \NR \NC \llap{\star\space}primeshiftdrop \NC prime \NC PrimeBaselineDropMax \NC \NC \NR \NC \llap{\star\space}primespaceafter \NC prime \NC PrimeSpaceAfter \NC \NC \NR \NC spaceafterscript \NC post \NC SpaceAfterScript \NC \typ {\scriptspace} \NC \NR \NC \llap{\star\space}spacebeforescript \NC post \NC SpaceBeforeScript \NC \NC \NR \NC \llap{\star\space}spacebetweenscript \NC multi \NC SpaceBetweenScript \NC \NC \NR \NC \llap{\star\space}extrasuperscriptshift \NC pre \NC \NC \NC \NR \NC \llap{\star\space}extrasuperprescriptshift \NC pre \NC \NC \NC \NR \NC \llap{\star\space}extrasubscriptshift \NC pre \NC \NC \NC \NR \NC \llap{\star\space}extrasubprescriptshift \NC pre \NC \NC \NC \NR \NC \llap{\star\space}extrasuperscriptspace \NC post \NC \NC \NC \NR \NC \llap{\star\space}extrasubscriptspace \NC post \NC \NC \NC \NR \NC \llap{\star\space}extrasuperprescriptspace \NC pre \NC \NC \NC \NR \NC \llap{\star\space}extrasubprescriptspace \NC pre \NC \NC \NC \NR \LL \stoptabulate The parameters marked by a \star\ are \LUAMETATEX\ specific. Some have an associated font parameter but that is not official \OPENTYPE. For a very long time we had only a few math fonts but even today most of these fonts seem to use values that are similar to the ones \TEX\ uses. In that respect one can as well turn them into rendering specific ones. After all, changes are slim that a formula rendered by \TEX\ or e.g.\ \MSWORD\ are metric compatible and with the advanced spacing options in \LUAMETATEX\ we're even further off. Also keep in mind that the \TEX\ font parameters could be overloaded at the \TEX\ end. The spacing after a (combination of) postscript(s) is determined by \quote {space after script} and the spacing before a (combination of) prescript(s) by \quote {space before script}. If we have multi-scripts the \quote {space between script} kicks in and the space after the script is subtracted from it. The given space between is scaled with the \type {\scriptspacebetweenfactor} parameter. The default style mapping that we use are the same as those (hard coded) in regular \TEX\ and those for prime scripts are the same as for superscripts. \startluacode document.showmathvariant("subscriptvariant") document.showmathvariant("superscriptvariant") document.showmathvariant("primevariant") \stopluacode \stopsection \startsection[title=Skewed fractions] Skewed fractions are native in \LUAMETATEX. Such a fraction is a horizontal construct with the numerator and denominator shifted up and down a bit. It looks like this: \startlinecorrection \startMPcode vardef baseline expr p = (xpart llcorner p, 0) -- (xpart lrcorner p,0) enddef ; numeric wd ; wd := 12 ; numeric ht ; ht := 7 ; numeric dp ; dp := 3 ; numeric ax ; ax := 4 ; numeric ws ; ws := 5 ; numeric hs ; hs := 6 ; numeric ds ; ds := 3 ; path slash ; slash := (-ws,-(hs+ds)) -- (ws,(hs+ds)) ; path numerator ; numerator := unitsquare xyscaled (wd, ht+dp) shifted (0,-dp) && ((0,0) -- (wd,0)) ; path denominator ; denominator := numerator ; numerator := numerator shifted - center numerator ; denominator := denominator shifted - center denominator ; numerator := anchored.lft (numerator, center slash) shifted (-3.5ws, ax/2) ; denominator := anchored.rt (denominator, center slash) shifted ( 3.5ws,-ax/2) ; draw slash withcolor "darkgray" withpen pencircle scaled 1 ; draw numerator withcolor "darkred" ; draw denominator withcolor "darkblue" ; path line ; line := (baseline currentpicture) leftenlarged 1 rightenlarged 1 ; draw line withstacking -1 withcolor "middlegray" ; draw line shifted (0,ax) withstacking -1 withcolor "darkgreen" ; % axis currentpicture := currentpicture scaled 5 ; \stopMPcode \stoplinecorrection The rendering is driven by some parameters that determine the horizontal and vertically shifts but we found that the ones given by the font make no sense (and are not that well defined in the standard either). The horizontal shift relates to the width (and angle) of the slash and the vertical relates to the math axis. We don't listen to \quote {skewed fraction hgap} nor to \quote {skewed fraction vgap} but use the width of the middle character, normally a slash, that can grow on demand and multiply that with a \type {hfactor} that can be passed with the fraction command. A \type {vfactor} is used a multiplier for the vertical shift over the axis. Examples of (more)) control can be found in the \CONTEXT\ math manual. Here we just show a few examples that use \type {\vfrac} with its default values. \startlinecorrection \startcombination[nx=3,ny=2,distance=4em] {\scale [s=3] {\showglyphs\im { \vfrac{1} {2} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { \vfrac{a} {b} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { \vfrac{b} {a} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { \vfrac{x^2} {x^3} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { \vfrac{(x+1)}{(x+2)} \mathaxisbelow }}} {} {\scale [s=3] {\showglyphs\im { \vfrac{x+1} {x+2} \mathaxisbelow }}} {} \stopcombination \stoplinecorrection The quality of the slashes differs per font, some lack granularity in sizes, others have inconsistent angles between the base character and larger variants. The following commands are used: \starttyping \Uskewed \Uskewedwithdelims \stoptyping There are some parameter involved: \starttyping \Umathskeweddelimitertolerance \Umathskewedfractionhgap \Umathskewedfractionvgap \stoptyping \stopsection \startsection[title=Math fractions] Fractions in \TEX\ come in variants: with or without rule in the middle and with or without fences. The reason for the fenced ones is that they are not spaced like open and close class symbols. So, instead of open, fraction, close being three things, we have one thing. In \LUAMETATEX\ we can also use an extensible instead of the rule. \startlinecorrection \startMPcode def Example (expr showbar) = numeric wd ; wd := 20 ; numeric ht ; ht := 7 ; numeric dp ; dp := 3 ; numeric ax ; ax := 2 ; numeric ay ; ay := -2 ; numeric ab ; ab := 2 ; path numerator ; numerator := unitsquare xyscaled ( wd, ht+dp) shifted (0,-dp) && ((0,0) -- (wd,0)) ; path denominator ; denominator := numerator ; path fraction ; fraction := (-wd/2-ax,0) -- (wd/2+ax,0) ; numerator := numerator shifted - center numerator ; denominator := denominator shifted - center denominator ; numerator := numerator shifted (0, (ht+dp)+ay) ; denominator := denominator shifted (0,-(ht+dp)-ay) ; if showbar : draw fraction withcolor "darkgray" withpen pencircle scaled 1 ; fi ; draw numerator withcolor "darkred" ; draw denominator withcolor "darkblue" ; path leftbar ; leftbar := (leftboundary currentpicture topenlarged 2 bottomenlarged 2) shifted (-ab,0) ; path rightbar ; rightbar := (rightboundary currentpicture topenlarged 2 bottomenlarged 2) shifted ( ab,0) ; draw leftbar withcolor "darkgray" withpen pencircle scaled 1 ; draw rightbar withcolor "darkgray" withpen pencircle scaled 1 ; currentpicture := currentpicture scaled 5 ; enddef ; draw image (Example(true)) ; draw image (Example(false)) shifted (20+bbwidth(currentpicture) ,0) ; \stopMPcode \stoplinecorrection Because the rule is optional, we can have the following, which represents a so called binom construct. \stopsection \startsection[title=Math radicals] Radicals indeed look like roots. But the radical mechanism basically is a wrapping construct: there's something at the left that in traditional \TEX\ gets a rule appended. The left piece is an extensible, so it first grow with variant glyphs and when we run out if these we get an upward extensible with a repeated upward rule like symbol that then connect with the horizontal rule. In \LUAMETATEX\ the horizontal rule can be an extensible (repeated symbol) and we can also have a symbol at the right, which indeed can be a vertical extensible too. \startlinecorrection \startMPcode vardef baseline expr p = (xpart llcorner p, 0) -- (xpart lrcorner p,0) enddef ; numeric wd ; wd := 24 ; numeric ht ; ht := 7 ; numeric dp ; dp := 3 ; numeric dw ; dw := 3 ; numeric dh ; dh := 3 ; numeric dd ; dd := 1 ; numeric rw ; rw := 2 ; numeric rh ; rh := 2 + ht ; numeric rd ; rd := 2 + dp ; path rleft ; rleft := (-3rw,rh/3) -- (-2rw,-rd) -- (-rw,rh) ; path rright ; rright := (wd+2,rh) -- (wd+2,rh-2); path rmiddle ; rmiddle := (-rw,rh) -- (wd+2,rh); path body ; body := unitsquare xyscaled (wd, ht+dp) shifted (0,-dp) && ((0,0) -- (wd,0)) ; path degree ; degree := unitsquare xyscaled (dw, dh+dd) shifted (0,-dd) && ((0,0) -- (dw,0)) ; degree := degree shifted (-3rw-2,rh/3+dd+2) ; draw rleft withcolor "darkblue" ; draw rmiddle withcolor "darkgray" ; draw rright withcolor "darkblue" ; draw body withcolor "darkred" ; draw degree withcolor "darkgreen" ; path line ; line := (baseline currentpicture) leftenlarged 1 rightenlarged 1 ; draw line withstacking -1 withcolor "middlegray" ; currentpicture := currentpicture scaled 5 ; \stopMPcode \stoplinecorrection Here are some aspects to take care of when rendering a radical like this: \startitemize[packed] \startitem The radical symbol goes below the baseline of what it contains. \stopitem \startitem There is some distance between the left symbol and the body. \stopitem \startitem There is some distance between the top symbol and the body. \stopitem \startitem There is some distance between the right symbol and the body. \stopitem \startitem The degree has to be anchored properly and possibly can stick out left. \stopitem \startitem The (upto) three elements have to overlap a little to avoid artifacts. \stopitem \startitem Multiple radicals might have to be made consistent with respect to heights and depths. \stopitem \stopitemize Involved commands: \starttyping \Uradical \Uroot \Urooted \stoptyping Relevant parameters: \starttyping \Umathradicaldegreeafter \Umathradicaldegreebefore \Umathradicaldegreeraise \Umathradicalextensibleafter \Umathradicalextensiblebefore \Umathradicalkern \Umathradicalrule \Umathradicalvariant \Umathradicalvgap \stoptyping \stopsection \startsection[title=Math accents] todo \stopsection \startsection[title=Math fences] todo \stopsection \stopdocument % \tohexa8 \mathnormalstylepreset \par % \tohexa8 \mathcrampedstylepreset \par % \tohexa8 \mathsubscriptstylepreset \par % \tohexa8 \mathsuperscriptstylepreset \par % \tohexa8 \mathsmallstylepreset \par % \tohexa8 \mathsmallerstylepreset \par % \tohexa8 \mathnumeratorstylepreset \par % \tohexa8 \mathdenominatorstylepreset \par % \tohexa8 \mathdoublesuperscriptstylepreset \par % \tohexa8 \Umathoverlayaccentvariant \displaystyle\par % \tohexa8 \Umathradicalvariant \displaystyle\par % \tohexa8 \Umathradicalvariant \textstyle \par % \tohexa8 \Umathunderlinevariant \displaystyle\par % $2x^{2^2}$ % $\sqrt{x-\frac{1}{\sqrt{2}}}$ % $\Umathradicalvariant \allmathstyles 0 \sqrt{x-\frac{1}{\sqrt{2}}}$ % $2\frac{1}{2}$ % An alternative description: % % \def\blob#1{\mathord{\ruledhbox{\strut\tttf #1}}} % % The most common cases of scripts attached to a nucleus are the following where % vertical spacing depends on the dimensions and combinations: % % \startlinecorrection % \im { \blob{nuc} % \superscript {\blob{sup 1}} % } % \quad % \im { \blob{nuc} % \subscript {\blob{sub 1}} % } % \quad % \im { \blob{nuc} % \superscript {\blob{sup 1}} % \subscript {\blob{sub 1}} % } % \stoplinecorrection % % We also have primes. These have always been somewhat messy in \TEX\ (macro % packages) because they are on the one hand already raised (in text they also % serve as minutes) but because they are supposed to be anchored as super script % the non raised variant us used. Another complication is that, especially in % \UNICODE\ the multiple primes are single characters. In \LUAMETATEX\ primes are % an additional script which makes for better positioning, definitely when we also % have a superscript. Multiple primes are collected and can be collapsed into a % single character. \footnote {In \CONTEXT\ \MKIV\ primes are handles at the \LUA\ % end and become scripts. In \MKIV\ as well as in \MKXL\ collapsing is still a % \LUA\ task, but it is much simpler in \MKXL.} % % \startlinecorrection % \im { \blob{nuc} % \primescript {\blob{pri}} % } % \quad % \im { \blob{nuc} % \primescript {\blob{pri}} % \subscript {\blob{sub 1}} % } % \quad % \im { \blob{nuc} % \primescript {\blob{pri}} % \superscript {\blob{sup 1}} % } % \quad % \im { \blob{nuc} % \primescript {\blob{pri}} % \superscript {\blob{sup 1}} % \subscript {\blob{sub 1}} % } % \stoplinecorrection % % We also have prescripts and these have to align properly with postscripts % when present. Combinations of super- and subscripts make for different spacing % compared to single scripts and you can imagine that looking at four possible % scripts in various combinations have to obey to the same rules. % % \startlinecorrection % \im { \blob{nuc} % \superscript {\blob{sup 1}} % \superprescript{\blob{sup 1}} % } % \quad % \im { \blob{nuc} % \subscript {\blob{sup 1}} % \subprescript{\blob{sup 1}} % } % \quad % \im { \blob{nuc} % \superscript {\blob{sup 1}} % \subprescript{\blob{sup 1}} % } % \stoplinecorrection % % Finally there can be multiscripts and often we then talk in terms of index. One % can explicitly mark an index. A single \type {^} means super (post) script (or % more verbose \typ {\superscript}), while \type {^^} means indexed super (post) % script (\typ {\indexedsuperscript}). The threesome \type {^^^} makes a super pre % script and likewise the quadruple \type {^^^^} is an indexed super pre script. % % \startlinecorrection % \im { \blob{nuc} % \primescript {\blob{pri}} % \superscript {\blob{sup 1}} % \subscript {\blob{sub 1}} % \superprescript{\blob{presup 1}} % \subprescript {\blob{presub 1}} % \superscript {\blob{sup 2}} % \subscript {\blob{sub 2}} % \superprescript{\blob{presup 2}} % \subprescript {\blob{presub 2}} % } % \stoplinecorrection % % We can move to the next multiscript assembly with \typ {\noscript} so we have some % control over positioning. % % \startlinecorrection % \im { \blob{nuc} % \superscript {\blob{sup 1}} % \noscript % \subscript {\blob{sub 1}} % \noscript % \superscript {\blob{sup 2}} % } % \stoplinecorrection