iosMath Documentation

repository·master·Indexed 23 days ago

https://github.com/kostub/iosmath

A native library for iOS and macOS that renders LaTeX math equations into UIView/NSView subclasses. It provides high-performance typesetting using the OpenType MATH table, offering a native alternative to WebView-based solutions like MathJax or KaTeX. The library includes MTMathUILabel for rendering, support for custom LaTeX commands, and a rendering pipeline based on TeX Appendix G concepts.

Tokens
6.4K
Snippets
14
Records
31
Agent score
81%

What's inside iosMath

  1. Information about Latin Modern Math fonts

    master

    Latin Modern Math is an OpenType (OTF) math companion font for the Latin Modern family. It is designed to be visually compatible with D.E. Knuth's canonical fonts, maintaining similar symbol widths.

    Key features include:

    • MATH Table Support: Contains the special MATH table required for advanced math processing.
    • Comprehensive Scripts: Includes basic serif (regular, bold, italic, bold italic), calligraphic (regular, bold), double-struck, fraktur (regular, bold), sans-serif (regular, bold, oblique, bold oblique), and monospaced scripts.
    • Unicode Compliance: Designed with support for mathematical Unicode characters as described in Unicode Technical Report #25.

    Note that most alphabets in this font (except the main roman alphabet) are intended to be used as symbols rather than text stream letters.

  2. Understand the iosMath rendering pipeline

    master

    The iosMath rendering process follows a pipeline that transforms a LaTeX string into a visual display. While TeX uses a two-pass algorithm, iosMath collapses this into a single left-to-right pass because critical preprocessing (Rules 5, 6, and 14) is performed during the MTMathList.finalized stage before layout begins.

    The Pipeline Stages:

    1. LaTeX string $\rightarrow$ MTMathListBuilder $\rightarrow$ MTMathList (a list of MTMathAtoms).
    2. MTMathList.finalized: Pre-bakes important rules (Rules 5, 6, 14).
    3. MTTypesetter.preprocessMathList: Merges Rule 14 and reclassifies Number, Variable, and Unary atoms to Ord (Ordinary).
    4. MTTypesetter.createDisplayAtoms: Executes the core typesetting rules (Rules 1–4, 7–13, 15–18, 20, 22) in a single pass.
    5. MTMathListDisplay: Produces a tree of MTDisplay objects.
    6. MTDisplay.draw: Final rendering using CoreText or CGContext.
    LaTeX string ──► MTMathListBuilder ──► MTMathList (of MTMathAtoms)
                                                │
                                                ▼
                                       MTMathList.finalized  (Rules 5, 6, 14 pre-bake)
                                                │
                                                ▼
                         MTTypesetter.preprocessMathList  (Rule 14 merge + Number→Ord, Variable→Ord, Unary→Ord)
                                                │
                                                ▼
                MTTypesetter.createDisplayAtoms  (Rules 1–4, 7–13, 15–18, 20, 22; two-pass merged into one)
                                                │
                                    MTMathListDisplay (tree of MTDisplays)
                                                │
                                         MTDisplay.draw:  (CoreText / CGContext)
  3. How iosMath implements TeX math typesetting rules

    master

    iosMath implements a math typesetting pipeline inspired by TeX Appendix G, mapping TeX rules to an OpenType MATH-based model. The process involves two main phases:

    1. First Pass (MTTypesetter.createDisplayAtoms:): The engine traverses the math list, creating MTMathAtom objects. During this pass, it handles style changes, calculates spacing (mu to pt conversion), and processes complex structures like radicals, fractions, and accents.
    2. Finalize Phase (MTMathList.finalized): The engine performs a second pass to refine the list. This includes reclassifying atom types (e.g., converting BinaryOperator to UnaryOperator or Ordinary based on context) to ensure correct inter-element spacing.

    Key Implementation Notes:

    • Spacing: Uses an OpenType-era equivalent of TeX's $\sigma_6$ (calculated as fontSize / 18) for space units.
    • Atom Reclassification: To handle TeX's Rule 5 and 6, iosMath uses a two-step path: Bin $\rightarrow$ UnaryOperator $\rightarrow$ Ordinary. This ensures spacing is handled correctly before the final layout.
    • Limitations: Unlike TeX, iosMath does not implement \mathchoice, \vcenter, or line-breaking penalties (\binoppenalty), as math lists are laid out monolithically.
  4. Understand iosMath feature gaps and TeX compatibility

    master

    iosMath implements a subset of the TeX Appendix G algorithm. Developers should be aware of the following limitations when expecting full TeX parity:

    • Missing Commands/Rules: \nonscript, \mathchoice, \vcenter, \above, \abovewithdelims, \overwithdelims, and \atopwithdelims are not currently parsed.
    • Spacing & Kerning: Ligatures and kerns between Ord symbols (Rule 14) are not implemented. User-tunable parameters like \delimiterfactor, \thinmuskip, \medmuskip, and \thickmuskip are hard-coded constants.
    • Limits & Penalties: \displaylimits is reduced to a two-state limits boolean (cannot be changed at runtime with a modifier). Penalties (Rule 21) are not inserted.
    • Layout: Rule 1 items (rule, discretionary, whatsit, penalty, boundary) are absent from the noad model. Non-OpenType ξ₁₃ (extra padding for limits) is always 0.
  5. How large operators (\sum, \prod, etc.) handle limits

    master

    iosMath manages large operators and their limits (e.g., \sum_{i=1}^n) through MTTypesetter.makeLargeOp: and addLimitsToDisplay:forOperator:delta::

    • Limits Decision: The limits property on MTLargeOperator is determined at parse time. Symbols like \sum and \prod default to limits:YES, while \int and \log default to NO.
    • Vertical Centering: The operator is centered on the axis using the formula: shiftDown = 0.5 * (ascent - descent) - axisHeight.
    • Limit Placement: When limits are attached, an MTLargeOpLimitsDisplay is created.
      • Upper limits use style C^up (cramped).
      • Lower limits use style C^down (always cramped).
      • Vertical gaps are determined by UpperLimitGapMin and LowerLimitGapMin from the MATH table.
    • Italic Correction: If a subscript exists and limits are not used, an italic correction (delta) is applied to allow the subscript to nestle under the italic overhang.
  6. Information about TeX Gyre Termes Math font

    master

    TeX Gyre Termes Math is an OpenType (OTF) math companion font designed for the TeX Gyre Termes family. It is specifically built for mathematical typesetting and includes a MATH table as described in Microsoft's OpenType Math specifications.

    Key features include:

    • Comprehensive Scripts: Contains basic serif (regular, bold, italic, bold italic), calligraphic (regular, bold), double-struck, fraktur (regular, bold), sans-serif (regular, bold, oblique, bold oblique), and monospaced scripts.
    • Mathematical Symbols: Includes specialized symbols for Greek, Hebrew, and various mathematical notations.
    • Compatibility: Designed to support Unicode mathematical character sets (referencing Unicode Technical Report #25).

    Note that scripts like fraktur, sans-serif, and monospaced are treated as symbols rather than standard text letters and are intended to be used in mathematical contexts (e.g., with subscripts, superscripts, or primes).

  7. How accents (\mathaccent) are rendered in iosMath

    master

    iosMath implements accent typesetting via MTTypesetter.makeAccent:, following these steps:

    1. Style: The inner nucleus is typeset in a cramped style (C').
    2. Width Matching: The engine performs a 'successor walk' using findVariantGlyph:withMaxWidth: to find the widest accent glyph that does not exceed the width of the accentee.
    3. Vertical Adjustment: The vertical shift (delta) is calculated using AccentBaseHeight from the OpenType MATH table: delta = MIN(accenteeAdjustment, accentBaseHeight).
    4. Skewing: Instead of TeX's \skewchar, iosMath uses OpenType top-accent attachment points (getTopAccentAdjustment:) for more precise positioning.
    5. Sub/Superscript Promotion: If the nucleus is a single character and the accent has sub/superscripts, the accent's sub/superscripts are promoted into the nucleus to prevent collision.
  8. How fractions and stacks are rendered in iosMath

    master

    Fractions and stacks (like \frac, \atop, \binom) are handled by MTTypesetter.makeFraction: and addDelimitersToFractionDisplay:forFraction::

    • Bar Thickness: For \frac and \over, the bar thickness is set to FractionRuleThickness. For stack-based commands like \binom or \atop, the thickness is 0.
    • Styles:
      • The numerator is typeset in a style one level higher than the current style (e.g., Display $\rightarrow$ TeX), with cramped:NO.
      • The denominator is typeset in the same style as the numerator, but with cramped:YES.
    • Delimiters: If delimiters (like \left( and \right)) are provided, the fraction is wrapped in an MTMathListDisplay using glyphs of height fractionDelimiterDisplayStyleSize (Display) or fractionDelimiterSize (TeX).
    • Alignment: Both numerator and denominator are reboxed to a common width by centering them at (width - their.width) / 2.
  9. Understand the iosMath Display Tree model

    master

    iosMath uses a display tree model where an MTMathListDisplay holds an array of MTDisplay objects.

    • Relative Positioning: Positions are relative to the parent. When draw is called, the parent translates the context to its position before asking children to draw.
    • Sub/Superscripts: These are treated as regular children in the tree rather than being nested inside the parent atom's display, which simplifies positioning logic.
    • Special Display Types:
      • MTFractionDisplay: Draws the fraction bar.
      • MTRadicalDisplay: Draws the surd glyph and horizontal top-bar.
      • MTLineDisplay: Draws over/underline bars.
      • MTAccentDisplay & MTLargeOpLimitsDisplay: Position auxiliary displays around a nucleus.
      • MTInnerDisplay: Holds left/right delimiter glyphs.
  10. How style and cramping propagate in iosMath

    master

    The MTTypesetter manages layout using _style and _cramped as mutable state. When rendering complex math structures, the style propagates as follows:

    • Fractions: Numerator uses fractionStyle (one step smaller, not cramped); Denominator uses fractionStyle + cramped.
    • Radicands: Same style + cramped.
    • Accents: Same style + cramped.
    • Sub/Superscripts & Op Limits: Uses scriptStyle + specific subscriptCramped/superScriptCramped rules.
    • Delimiters (\left...\right): Same style + current cramping.
    • Underlines/Overlines: Inner content uses same style + current cramping.
    • Tables: Uses same style, but cramped:NO is explicitly set (a potential deviation from TeX).
  11. How iosMath handles styles and cramped variants

    master

    TeX defines eight styles (D, D′, T, T′, S, S′, SS, SS′). iosMath simplifies this by using four MTLineStyle values: Display, Text, Script, and ScriptScript.

    To handle the 'primed' (cramped) variants, iosMath tracks a _cramped boolean on the MTTypesetter. This is functionally equivalent to the TeX primed notation (e.g., C′ is the cramped variant of C).

    Cramped behavior defaults:

    • subscriptCramped: Always YES (matches TeX behavior where subscripts use the cramped variant).
    • superScriptCramped: Inherits the current _cramped state.
    • Specific contexts: Radicands (makeRadical), overline/accent inner lists, and fraction denominators are all passed cramped:YES.
  12. Understand the MTMathAtom math model

    master

    An MTMathList is a linked list of MTMathAtom objects. Each atom has a type (MTMathAtomType) that determines how it is rendered and spaced. Common atom types include:

    • MTFraction: Contains numerator and denominator lists.
    • MTRadical: Contains a radicand and an optional degree.
    • MTLargeOperator: Represents operators like \sum or \int with optional limits.
    • MTInner: An embedded list, often used with delimiters.
    • MTAccent: Represents accents like \hat or \vec.