Mathematics

Mathematics

The frontend/math package is an OpenType-MATH engine: it turns a tree of math atoms into a typeset *node.HList, reading the geometry constants, italic corrections, math kerns, stretchy-delimiter variants and glyph assemblies from a font’s OpenType MATH table.

Most callers do not build atom trees by hand — they feed MathML through the frontend/math/mathml reader, which produces the same atom list. The reader is the entry point used by htmlbag and therefore by glu and bagme.

A math font is required

The engine works on glyph IDs from a font carrying an OpenType MATH table (Latin Modern Math, STIX Two Math, XITS Math, Cambria Math, …). A font without that table is rejected — the engine needs its constants and variant data.

From MathML

The mathml package reads a <math> fragment and renders it in one call:

import (
    "github.com/boxesandglue/boxesandglue/backend/font"
    "github.com/boxesandglue/boxesandglue/frontend/math/mathml"
)

// fnt is a *font.Font built from a MATH-table font.
hlist, err := mathml.Render([]byte(`<math>
    <msup><mi>a</mi><mn>2</mn></msup><mo>+</mo>
    <msup><mi>b</mi><mn>2</mn></msup><mo>=</mo>
    <msup><mi>c</mi><mn>2</mn></msup>
</math>`), fnt)

Render dispatches to inline or display layout based on the root display attribute. To inspect or post-process the atoms first, use Parse, which returns the atom list plus the display flag:

atoms, displayBlock, err := mathml.Parse(src, fnt)

For accessibility, AltText returns a plain-text approximation suitable for a Formula element’s /Alt — it honours the MathML alttext attribute when present, otherwise concatenates the token content:

alt := mathml.AltText(src) // e.g. "a 2 + b 2 = c 2"

Building atoms directly

The engine’s public constructors in frontend/math build atoms without MathML — useful for programmatic formula construction:

import "github.com/boxesandglue/boxesandglue/frontend/math"

// x² + a/b, laid out in inline style
hlist, err := math.InlineMath(fnt,
    math.Ord(xGID).WithSupGlyph(twoGID),
    math.Bin(plusGID),
    math.Frac(math.Ord(aGID), math.Ord(bGID)),
)

// the same atoms in display style (larger operators, limits)
hlist, err = math.DisplayMath(fnt, atoms...)

Atom constructors include Ord, Bin, Rel, Op, Open, Close, Punct, Frac, Sqrt, and accent/limit helpers. The engine applies the inter-atom spacing table, sub/superscript and limit placement, fraction rules, and radical construction following TeX’s algorithms and the OpenType MATH metrics. The constructors work on glyph IDs, so the caller is responsible for mapping characters (including math-italic code points) to GIDs in the chosen font — which is exactly what the MathML reader does for you.