summaryrefslogtreecommitdiff
path: root/macros/optex/base/unimath-macros.opm
blob: ac926b5e89e2b6cf5f29c79c8af7e2c06fa1754c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
%% 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` `<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.
   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` `<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
   dependig 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;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` `<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}{#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
   <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 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 {[<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 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` `<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

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