%% This is part of the OpTeX project, see http://petr.olsak.net/optex \_codedecl \loadmath {Unicode Math fonts <2023-01-17>} % preloaded in format \_doc ----------------------------- \`\loadmath` `{}` loads the given font. It does: \begitems * define \`\_unimathfont` as ``, * redefine `\normalmath` and `\boldmath` macros to their Unicode counterparts, * 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{% \_ifmathloading \_initunifonts \_isfont{#1}\_iffalse \_opwarning{Math font "#1" not found, skipped...}% \_else \_def\_unimathfont{#1}% \_let\_normalmath = \_normalunimath \_let\_boldmath = \_boldunimath \_normalmath \_wterm {MATH-FONT: "#1" -- 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 givem math character. \_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 math fonts 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. \^`\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-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