%% This is part of the OpTeX project, see http://petr.olsak.net/optex \_codedecl \loadmath {Unicode Math fonts <2023-09-03>} % preloaded in format \_doc ----------------------------- \`\loadmath` ` {}` loads the given font. It does: \begitems * define \`\_unimathfont` as ``, * redefine `\normalmath` and `\boldmath` macros to their Unicode counterparts, * save the `` 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` `{} \to {}` defines \`\_unimathboldfont` as `` only if `\_unimathfont` is defined as ``. 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. They are using \`\_setunimathdimens` in a similar sense as \^`\_setmathdimens`. \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. \_cod ----------------------------- \_def\_normalunimath{% \_setmathfamily 0 \_tenrm % font for non-math objects in math mode \_loadumathfamily 1 {\_unimathfont}{} % Base font \_loadmathfamily 4 rsfs % script \_setunimathdimens }% \_def\_boldunimath{% \_setmathfamily 0 \_tenbf % font for non-math objects in math mode \_ifx\_unimathboldfont \_undefined \_loadumathfamily 1 {\_unimathfont}{embolden=1.7;} % Base faked bold \_else \_loadumathfamily 1 {\_unimathboldfont}{} % Base real bold font \_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` ` {}{}` loads the given Unicode-math fonts in three sizes using single with different `mathsize=1,2,3` font features. The math font family is set with given ``. The `` 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 dependig on the current `\_mfam`.\nl The \^`\_mfactor` `` 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;script=math;} \_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` ` {[]}{} {[]}{} {}` allocates new 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}{#3} }% \_ifx\_relax#4\_relax \_global\_aheadto\_boldmath{\_loadumathfamily #1{#2}{embolden=1.7;} }% \_else \_global\_aheadto\_boldmath{\_loadumathfamily #1{#4}{#5} }% \_fi \_normalmath \_wterm{add-MATH-FONT: #1=\the#1, "#2", \ifx"#4"\else bold: "#4"\fi}% \_fi \_fi } \_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 , , . Sometimes, we may want to get these quantities from the given Unicode math character by our macros. It is possible by \`\themathcodeclass```, \`\themathcodefam``` and \`\themathcodechar``` macros. The parameter is a math character or it is a macro like `\doteq`, `\times`. Moreower, \`\thedelcodefam``` and \`\thedelcodechar``` return delcode quaitities of given math character. All these commands use the common Lua code defined in the \`\_getmathcode``{}` 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` ` {}` saves to \`\_mafam` and runs for each sequence from the the relevant code settings using `\Umathcode` primitive. In case of `\int`-like operators the =8 and we only re-declare `\_int:` as an operator with the new \^`\_mafam`. Note that the used primitives have the syntax: \begtt \catcode`<=13 \Umathchardef = \Umathcode = \Udelcode = \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` ` {}` sets mathcodes of given characters with explicit es. Each pair can be `{}` and `` can include \`\Urange` `-`. This is reason why we apply `\expanded` to the `` 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` ` {}` 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 `` 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` `{} \to {}` loads bold variant only if `` was sucessully 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 {[]}{} {[]}{} {} \endtt The `\famname` is a control sequence declared by \^`\addUmathfont` for later use. It gets math family number. The `` is decimal number for size corrections in view of the main math font. If it is empty then =1. If is empty, the \"faked bold" derived from 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 {}`. For example: \begtt \mathchars \xits {\stareq \triangleq \veeeq \wedgeq} \endtt % sets the characters `\stareq`, `\triangleq`, `\veeeq`, `\wedgeq` from the `\xits` additional font. The can include control sequences from the `unicode-table.tex`, but no math accents. These contol 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` ` {}`. Each pair in the is `` (separated by optional space) or `{}`. The includes declared characters or \^`\Urange` `-` which is equal to the list of characters beginning and ending , 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 ` = ` \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 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