%% This is part of the OpTeX project, see http://petr.olsak.net/optex

\_codedecl \loadmath {Unicode Math fonts <2025-02-06>} % preloaded in format

   \_doc -----------------------------
   \`\loadmath` `<optional-factor> {<Unicode-math font>}` loads the given font. It does:
   \begitems
   * define \`\_unimathfont` as `<Unicode-math font>`,
   * redefine `\normalmath` and `\boldmath` macros to their Unicode counterparts,
   * save the `<optional-factor>` as scaling factor, see also \^`\_mfactor`,
   * load the `\_unimathfont` by `\normalmath`,
   * print information about the loaded font on the terminal,
   * redefine all encoding dependent setting by `\input unimath-codes.opm`,
   * protect new loading by setting \`\_ifmathloading` to false.
   \enditems
   \`\noloadmath` disallows Unicode-math loading by \`\_mathloadingfalse`.\nl
   \`\doloadmath` allows Unicode-math loading by \`\_mathloadingtrue`.
   \_cod -----------------------------

\_newifi \_ifmathloading   \_mathloadingtrue

\_def\_noloadmath{\_mathloadingfalse}
\_def\_doloadmath{\_mathloadingtrue}

\_def\_loadmath#1#{\_loadmathA{#1}}
\_def\_loadmathA#1#2{%
   \_ifmathloading
   \_initunifonts
   \_isfont{#2}\_iffalse
      \_opwarning{Math font "#2" not found, skipped...}%
   \_else
      \_sdef{_mfactor:1}{#1}\_def\_unimathfont{#2}%
      \_let\_normalmath = \_normalunimath  \_let\_boldmath = \_boldunimath
      \_normalmath
      \_wterm {MATH-FONT: "#2" -- unicode math prepared.}%
      \_ifx\_ncharrmA\_undefined \_opinput {unimath-codes.opm}\_fi
      \_mathloadingfalse
   \_fi\_fi}

\_public \loadmath \noloadmath \doloadmath ;

   \_doc -----------------------------
   \`\loadboldmath` `{<bold-font>} \to {<normal-font>}`
   defines \`\_unimathboldfont` as `<bold-font>` only if `\_unimathfont` is
   defined as `<normal-font>`. It is used when \^`\boldmath` macro is run.
   When no `\_unimathboldfont` is defined then the `\boldmath` macro
   use \"fake bold" generated by `embolden` \LuaTeX/ font feature.
   \_cod -----------------------------

\_def\_loadboldmath#1#2\to #3{%
   \_def\_tmp{#3}\_ifx\_unimathfont\_tmp % do work only if #3 is loaded as normal Math
   \_isfont{#1}\_iffalse
      \_opwarning{Bold-Math font "#1" not found, skipped...}
   \_else
      \_def\_unimathboldfont{#1}%
      \_wterm {MATH-FONT: "#1" -- unicode math bold prepared.}%
   \_fi\_fi}

\_public \loadboldmath ;

   \_doc -----------------------------
   The Unicode version of the \^`\normalmath` and \^`\boldmath` macros
   are defined here as \`\_normalunimath` and \`\_boldunimath` macros.
   The base font \^`\_unimathfont` is loaded to family 1 with `script=math`
   feature. It is generally used for all variables, digits and math symbols.
   The same font is loaded to family 2 with `script=latn`. It can be used for
   sequences of letters where we don't want to insert italic correction
   between them. The default \^`\rm` and \^`\it` macros run \^`\_rmletters` and
   \^`\_itletters` and they use family 2, so these selectors prohibit italic
   corrections between letters.
   \nl
   You can combine more fonts if you register them to another
   math families (5, 6, 7, etc.) in the \^`\normalmath` macro.
   \nl
   The default value of \^`\_normalunimath` shows a combination of base Unicode-math
   font at family 1 with 8bit Math font at family 4. See definition of `\script` macro where
   `\fam4` is used.
   The final macro \`\_setunimathdimens` does similar work as \^`\_setmathdimens`.
   \_cod -----------------------------

\_def\_normalunimath{%
    \_setmathfamily 0 \_tenrm             % font for non-math objects in math mode
    \_loadumathfamily 1 {\_unimathfont}{script=math;} % Base math font
    \_loadumathfamily 2 {\_unimathfont}{script=latn;} % Base font, no italic corr. between letters
    \_loadmathfamily  4 rsfs              % script
    \_setunimathdimens
}%
\_def\_boldunimath{%
    \_setmathfamily 0 \_tenbf             % font for non-math objects in math mode
    \_ifx\_unimathboldfont \_undefined
       \_loadumathfamily 1 {\_unimathfont}{script=math;embolden=1.7;} % Base faked bold
       \_loadumathfamily 2 {\_unimathfont}{script=latn;embolden=1.7;} % Base faked, no italcor.
    \_else
       \_loadumathfamily 1 {\_unimathboldfont}{script=math;} % Base real bold font
       \_loadumathfamily 2 {\_unimathboldfont}{script=latn;} % Base real bold, no italcorr.
    \_fi
    \_loadmathfamily  4 rsfs              % script
    \_setunimathdimens
}%
\_def\_setunimathdimens{% PlainTeX sets these dimens for 10pt size only:
  \_delimitershortfall=0.5\_fontdimen6\_textfont1
  \_nulldelimiterspace=0.12\_fontdimen6\_textfont1
  \_setmathparam\_Umathspaceafterscript \_scriptspacefactor
  \_setbox0=\_hbox{\_everymath{}$\_fam1\_displaystyle{0\_atop0}$}%
  \_Umathfractiondelsize\_displaystyle = \_dimexpr(\_ht0-\_Umathaxis\_displaystyle)*2\_relax
  \_setbox0=\_box\_voidbox
}

   \_doc -----------------------------
   If you try the example above about
   \~`\loadboldmath``{[xitsmath-bold]} \to {[xitsmath-regular]}`
   then you can find a bug in XITSMath-Bold font: the symbols for norm
   $\|x\|$ are missing. So, we have to define `\_boldmath` macro manually.
   The missing symbol is loaded from family 5 as no-bold variant in our example:
   \begtt
   \loadmath{[xitsmath-regular]}
   \def\_boldmath{%
      \_loadumathfamily 1 {[xitsmath-bold]}{} % Base font
      \_loadmathfamily 4  rsfs % script
      \_loadumathfamily 5 {[xitsmath-regular]}{}
      \_def\|{\_Udelimiter 0 5 "02016 }%      % norm delimiter from family 5
      \_setmathdimens
   }
   \endtt

   \`\_loadumathfamily` `<number> {<font>}{<font features>}`
   loads the given Unicode-math fonts in three sizes
   using single <font> with different `mathsize=1,2,3` font features.
   The math font family is set with given `<number>`.
   The `<font features>` are added to the default
   \`\_mfontfeatures` and to the size-dependent features `ssty=1`
   if script size is asked or `ssty=2` if scriptscriptsize is asked.\nl
   \`\_mparams` can insert additional font features
   depending on the current `\_mfam`.\nl
   The \^`\_mfactor` `<family><space>` sets scaling factor,
   see section~\ref[math-preload] for more information.\nl
   The \`\_textmff`, \`\_scriptmff` and \`\_sscriptmff` are font
   features for text, script and sscript sizes respectively. They are
   locally re-defined in \^`\mathbox` macro.
   \_cod -----------------------------

\_def\_umathname#1#2{"#1:\_mfontfeatures#2"}
\_def\_mfontfeatures{mode=base;}

\_def\_loadumathfamily{\_afterassignment\_loadumathfamilyA \_chardef\_mfam}
\_def\_loadumathfamilyA #1#2 {\_mfactor
  \_font\_mF \_umathname{#1}{\_textmff   \_mparams #2} at\_sizemtext \_textfont         \_mfam=\_mF
  \_font\_mF \_umathname{#1}{\_scriptmff \_mparams #2} at\_sizemtext \_scriptfont       \_mfam=\_mF
  \_font\_mF \_umathname{#1}{\_sscriptmff\_mparams #2} at\_sizemtext \_scriptscriptfont \_mfam=\_mF
}
\_def\_textmff   {ssty=0;mathsize=1;}
\_def\_scriptmff {ssty=1;mathsize=2;}
\_def\_sscriptmff{ssty=2;mathsize=3;}
\_def\_mparams{}

   \_doc -----------------------------
   \`\addUmathfont` `<fam> {[<normal-font>]}{<ffeatures>} {[<bold-font>]}{<ffeatures>} {<factor>}`
   allocates new <fam> using \^`\newfam` and adds loading this font to the
   \~`\normalmath` and \~`\boldmath` macros. Note that allocationos using
   \^`\newfam` starts from 43 because numbers 1--42 are reserved for direct
   usage without \^`\newfam`.
   We use \^`\aheadto` here because we want to read the main family 1 as
   last one (for definitive setting of math parameters).
   \_cod -----------------------------

\_def\_addUmathfont #1#2#3#4#5#6{% #1: fam (will be set), #2#3: normal font, #4#5: bold font
   \_ifx\_ncharrmA\_undefined \_errmessage{basic Unicode math font must be loaded first}%
   \_else \_isfont{#2}\_iffalse \_opwarning{font #2 is unavailable}%
   \_else
      \_newfam#1\_relax
      \_sdef{_mfactor:\_the\_numexpr#1\_relax}{#6}%
      \_global\_aheadto\_normalmath{\_loadumathfamily #1{#2}{\_addUmathdefault #3} }%
      \_ifx\_relax#4\_relax
         \_global\_aheadto\_boldmath{\_loadumathfamily #1{#2}{\_addUmathdefault embolden=1.7;#3} }%
      \_else
         \_global\_aheadto\_boldmath{\_loadumathfamily #1{#4}{\_addUmathdefault #5} }%
      \_fi
      \_normalmath
      \_wterm{add-MATH-FONT: #1=\the#1, "#2", \ifx"#4"\else bold: "#4"\fi}%
   \_fi \_fi
}
\_def\_addUmathdefault {script=math;} % default font features when \_addUmathfont is used

   \_doc -----------------------------
   The math characters can be given directly (by their Unicode) or by a macro
   like `\doteq`, `\times`, etc. These macros simply expand to the math character
   with its Unicode. And this math character has its `\Umathcode` given by
   <class>, <family>, <slot-number>. Sometimes, we may want to get these
   quantities from the given Unicode math character by our macros. It is
   possible by \`\themathcodeclass``<math-char>`,
   \`\themathcodefam``<math-char>` and \`\themathcodechar``<math-char>` macros.
   The parameter <math-char> is a math character or it is a macro like `\doteq`, `\times`.
   Moreower, \`\thedelcodefam``<math-char>` and \`\thedelcodechar``<math-char>`
   return delcode quaitities of given math character.
   All these commands use the common Lua code defined in
   the \`\_getmathcode``<code>{<math or del>}<character number>` macro.
   \_cod -----------------------------

\_def\_getmathcode#1#2{\_directlua{tex.print(tex.get#2code(token.scan_int())[#1])}}
\_def\_themathcodeclass #1{\_getmathcode 1{math}\_ea`#1 }
\_def\_themathcodefam   #1{\_getmathcode 2{math}\_ea`#1 }
\_def\_themathcodechar  #1{\_getmathcode 3{math}\_ea`#1 }
\_def\_thedelcodefam    #1{\_getmathcode 1{del}\_ea`#1 }
\_def\_thedelcodechar   #1{\_getmathcode 2{del}\_ea`#1 }

\_public \themathcodeclass \themathcodefam \themathcodechar \thedelcodefam \thedelcodechar ;

   \_doc -----------------------------
   \`\mathchars` `<fam> {<list of sequences>}`
   saves <fam> to \`\_mafam` and runs for each sequence from the <list of sequences>
   the relevant code settings using `\Umathcode` primitive.
   In case of `\int`-like operators the <math class>=8 and we only
   re-declare `\_int:<int-character>` as an operator with the new \^`\_mafam`.
   Note that the used primitives have the syntax:
   \begtt \catcode`<=13
   \Umathchardef <sequence> = <math class> <math family> <slot number>
   \Umathcode <code>        = <math class> <math family> <slot number>
   \Udelcode <code>         = <math family> <slot number>
   \endtt
   \_cod -----------------------------

\_def\_mathchars {\_afterassignment\_mathcharsA \_chardef\_mafam=}
\_def\_mathcharsA #1{\_foreach #1\_do{%
   \_chardef\_tmp=\_themathcodeclass##1\_relax
   \_ifnum\_tmp=8 % \int, \iint, \oint, etc.
       \_ea\_Umathchardef \_csname _int:##1\_endcsname =1 \_mafam \_ea`##1
   \_else
       \_Umathcode \_ea`##1=\_tmp \_mafam \_themathcodechar##1
   \_fi
}}

   \_doc -----------------------------
   \`\mathcodes` `<fam> {<list of pairs>}` sets mathcodes of given
   characters with explicit <class>es. Each pair can be `<class>{<list of chars>}`
   and `<list of chars>` can include \`\Urange` `<from>-<to>`.
   This is reason why we apply `\expanded` to the `<list of chars>`
   before reading it by \^`\foreach`: the \^`\Urange` is expandable
   and expands to the relevant list of characters.
   \_cod -----------------------------

\_def\_mathcodes{\_afterassignment\_mathcodesA\_chardef\_mafam=}
\_def\_mathcodesA#1{%
   \_foreach #1\_do ##1##2{%
      \_ea\_foreach\_expanded{##2}\_do{\_Umathcode `####1=##1\_mafam \_ea`####1}%
   }%
}
\_def\_Urange #1-#2{\_fornum \_ea`#1..\_ea`#2\_do{\_Uchar##1 }}

\_public \addUmathfont \mathchars \mathcodes \Urange ;

\_endcode


The \^`\loadmath` `<optional-factor> {<Unicode-math font>}` macro loads the given math font and
redefines all default math-codes using `\input unimath-codes.opm`.
If Unicode-math font is loaded then \^`\_mathloadingfalse`
is set, so the new Unicode-math font isn't loaded until \^`\doloadmath` is used.

The `<optional-factor>` is scaling factor of loaded font with respect to the
size of the text font. It can be used if the used text font and loaded math font have
incompatible ex height. If missing then the scaling factor is 1.

\^`\loadboldmath` `{<bold-font>} \to {<normal-font>}` loads bold variant only
if `<normal-font>` was sucessfully loaded by the previous `\loadmath`. For example:

\begtt
\loadmath     {[xitsmath-regular]}
\loadboldmath {[xitsmath-bold]} \to {[xitsmath-regular]}
\endtt
There are very few Unicode-math fonts with full \~`\boldmath` support.
I know only XITSMath-Bold and KpMath-Bold. If \^`\loadboldmath` is not used
then \"faked bold" created from \~`\normalmath` is used by default.

The {\em main math font} is loaded by \^`\loadmath` (typically indirectly using
\^`\fontfam`) and you can load more {\em additional math fonts} by
\^`\addUmathfont`:
\begtt \catcode`<=13
\addUmathfont \famname {[<normal-font>]}{<ffeatures>} {[<bold-font>]}{<ffeatures>} {<factor>}
\endtt
The `\famname` is a control sequence declared by \^`\addUmathfont` for later
use. It gets math family number. The `<factor>` is decimal number for size
corrections in view of the main math font. If it is empty then <factor>=1.
If <bold-font> is empty, the \"faked bold" derived from <normal-font> is used.
Example:
\begtt
\fontfam[lm]  % does \lodmath{[latinmodern-math]}
\addUmathfont \xits {[XITSMath-Regular]}{} {[XITSMath-Bold]}{} {}
\endtt
%
declares `latinmodern-math` as main math font (its bold variant is \"faked bold").
The additional math font family `\xits` is declared in the example. It uses
`XITSMath-Regular` for normal printing and `XITSMath-Bold` for bold printing.

All characters used in math formula are printed from main math font by
default. But you can re-declare characters for printing from
additional font by \^`\mathchars` `\famname {<list of sequences>}`. For
example:

\begtt
\mathchars \xits {\stareq \triangleq \veeeq \wedgeq}
\endtt
%
sets the characters `\stareq`, `\triangleq`, `\veeeq`, `\wedgeq` from
the `\xits` additional font. The <list of sequences> can include
control sequences from the `unicode-table.tex`, but no math
accents. These control sequences can be printed by `\input print-unimath.opm`.

The \^`\mathchars` macro keeps the class and slot of declared math objects
and re-declares only family of them. It is applied to all control
sequences given in the parameter. The relevant math codes are re-declared.

Use `\addto\selector{\fam\famname}` if you want to print whole math alphabet
from an additional math font. For example `\addto\cal{\fam\xits}`
declares all `\cal` characters from the `\xits` font loaded by
\^`\addUmathfont`.

The \^`\mathcodes` macro provides comfortable settings of math codes of math
objects. Its syntax is \^`\mathcodes` `<family> {<list-of-pairs>}`. Each pair
in the <list-of-pairs> is `<class-number><character>` (separated by optional
space) or `<class-number>{<list-of-characters>}`. The <list-of-characters>
includes declared characters or \^`\Urange` `<from>-<to>` which is equal to the
list of characters beginning <from> and ending <to>, for example
`\Urange a-d` is equal to `abcd`. The characters can be given directly or
by the math sequences like `\times`, `\doteq` too.

The \^`\mathcodes` macro declares mathcode of given characters internally by
\begtt \catcode`<=13
\Umathcode `<character> = <class-number> <family> `<character>
\endtt

The \^`\mathcodes` macro sets math codes of given Unicode characters.
The relevant control sequence from `unicode-table.tex` changes its
behavior too. For example, If you change math code of × then the
`\times` control sequence will behave like new declared ×.


\secc Unicode-math macros preloaded in the format

\printdoc unimath-macros.opm


\secc[unimath-codes] Macros and codes set when `\loadmath` is processed firstly

The file `unimath-codes.opm` is loaded when the \^`\loadmath` is used. The
macros here redefines globally all encoding dependent settings declared in
the section~\ref[math-macros].

\printdoc     unimath-codes.opm
\printdoctail unimath-codes.opm

\secc Printing all Unicode math slots in used math font

\printdoctail print-unimath.opm
\printdoc     print-unimath.opm

\_endinput

2025-02-06 fam2 introduced: no italic corrections are inserted using fam2
2023-09-03 mathsize does work (luaotfload v. 3.36 corrected the bug
2023-08-28 mathsize doesn't work now
2023-07-03 \loadmath: optional scaling factor introduced
2023-01-17 \mathchars: \int operators re-implemented
2023-01-15 \_def\_umathrange moved to unimath-codes.opm
2023.01-15 \themathcodeclass etc. introduced
2022-12-01 reading number by \_loadumathfamily more robust
2022-11-18 \mathchars improved, \Udelcodes are set too, \addUmathfont uses \ahead
2022-11-17 \Umathchardef replaced by \chardef
2022-11-16 \resetmathchars removed, \mathchars, \mathcodes introduced
2022-11-13 \_setfontfamily 0 added.
2022-07-22 \Umathspaceafterscript setting added.
2022-06-10 \addUmathfont and \resetmathchars added.
2021-08-16 \_loadumathfamily simplified, used mathsize= font feature.
2021-08-16 nomathparam font feature used for families > 3 (bug fixed).
2021-08-02 ssty fontfeatures rewritten; fam2, fam3 unused, \scriptspace not set
2021-04-04 \_setunimathdimens: \setbox0=\box\voidbox added
2021-03-09 \_setunimathdimes: \_begin/end/group instead {}, bug fixed
2021-02-15 \_textmff, \_scriptmff and \_sscriptmff introduced
2021-02-15 \_expandafter -> \_ea
2020-06-07 \Umathfractiondelsize (for \choose brackets) corrected, see https://tug.org/pipermail/luatex/2020-June/007365.html
2020-04-15 \_setmathdimens -> \_setuniathdimens
2020-02-25 implemented
