summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/optex/base/fonts-select.opm
blob: eab114fcc48e17aeade29b6844f15284ef80da88 (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
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
%% This is part of the OpTeX project, see http://petr.olsak.net/optex

\_codedecl \fontfam {Fonts selection system <2021-04-22>} % preloaded in format

   \_doc -----------------------------
   \`\initunifonts` macro extends \LuaTeX's font capabalities,
   in order to be able to load Unicode fonts. Unfortunately, this part of
   \OpTeX/ depends on `luaotfload` package, which adapts Con\TeX/t's generic
   font loader for plain \TeX/ and \LaTeX. `luaotfload` uses Lua functions
   from \LaTeX's `luatexbase` namespace, we provide our own replacements.
   Moreover, `\initunifont` switches with
   the \^`\_doresizefont` macro to OTF mode which is represented by the
   macro \`\_doresizeunifont`. This mode includes
   a fallback to TFM mode if \^`\_fontnamegen` is not defined.
   Finally, `\initunifonts` sets itself to relax because we don't want to do
   this work twice.\nl
   \`\_ttunifont` is default font for `\tt` variant if
   `f-lmfonts.opm` (or another font file where `\tt` is declared) is not loaded.
   \_cod -----------------------------

\_def\_initunifonts {%
   \directlua{%
      require('luaotfload-main')
      luaotfload.main()
   }%
   \_gdef\_rfskipatX ##1" ##2\_relax{"##1"}%
   \_global\_let \_doresizefont=\_doresizeunifont
   \_gdef\_tryloadtt {\_fontdef\_tentt{\_let\_fontnamegen=\_ttunifont\_rm}}%
   \_global\_let \_initunifonts=\_relax % we need not to do this work twice
   \_global\_let \initunifonts=\_relax
}
\_gdef\_doresizeunifont #1{\_logfont{#1}%
   \_ifx\_fontnamegen\_undefined \_doresizetfmfont#1\_else
       \_font#1={\_fontnamegen} \_sizespec \_relax \_setwsp#1\_relax
   \_fi
}
\_def\_ttunifont{[lmmono10-regular]:\_fontfeatures-tlig;}

\_public \initunifonts ;

   \_doc -----------------------------
   The \`\_famdecl` `[<Family Name>] \<Famselector> {<comment>} {<modifiers>} {<variants>} {<math>}`\nl
   `{<font for testing>} {\def`\^`\_fontnamegen``{<data>}}` runs \^`\initunifonts`, then
   checks if `\<Famselector>` is defined. If it is true, then closes the file by
   `\endinput`. Else it defines `\<Famselector>` and saves it to the
   internal `\_f:<currfamily>:main.fam` command.
   The macro \`\_initfontfamily` needs it. The \`\_currfamily` is set
   to the `<Famselector>` because the following \^`\moddef` commands need to
   be in the right font family context. The `\_currfamily` is set to the
   `<Famselector>` by the `\<Famselector>` too, because `\<Famselector>`
   must set the right font family context. The font family context is given by the current
   `\_currfamily` value and by the actual meaning of the \^`\_fontnamegen` macro.
   The \`\_mathfaminfo` is saved for usage in the catalog.
   \_cod -----------------------------

\_def\_famdecl [#1]#2#3#4#5#6#7#8{%
   \_initunifonts \_uniaccents
   \_unless\_ifcsname _f:\_csstring#2:main.fam\_endcsname
      \_isfont{#7}\_iffalse
         \_opwarning{Family [#1] skipped, font "#7" not found}\_ea\_ea\_ea\_endinput \_else
         \_edef\_currfamily {\_csstring #2}\_def\_mathfaminfo{#6}%
         \_wterm {FONT: [#1] -- \_string#2 \_detokenize{(#3)^^J mods:{#4} vars:{#5} math:{#6}}}%
         \_unless \_ifx #2\_undefined
            \_opwarning{\_string#2 is redefined by \_string\_famdecl\_space[#1]}\_fi
         \_protected\_edef#2{\_def\_noexpand\_currfamily{\_csstring #2}\_unexpanded{#8\_resetfam}}%
         \_ea \_let \_csname _f:\_currfamily:main.fam\_endcsname =#2%
      \_fi
   \_else \_csname _f:\_csstring#2:main.fam\_endcsname \_reloading \_rm \_ea \_endinput \_fi
}
\_def\_initfontfamily{%
   \_csname _f:\_currfamily:main.fam\_endcsname \_reloading \_rm
}

   \_doc -----------------------------
   \`\_regoptsizes` `<internal-template> <left-output>?<right-output> <resizing-data>`
   prepares data for using by the \`\_optname` `<internal-template>` macro.
   The data are saved to the `\_oz:<internal-template>` macro.
   When the `\_optname` is expanded then the data are scanned by the macro
   \`\_optnameA` `<left-output>?<right-output> <mid-output> `\code{<}`<size>`
   in the loop.\nl
   \`\_optfontalias` `{<template A>}{<template B>}` is defined as
   `\let\_oz:<templateA>=\_oz:<templateB>`.
   \_cod -----------------------------

\_def\_regoptsizes #1 #2?#3 #4*{\_sdef{_oz:#1}{#2?#3 #4* }}
\_def\_optname #1{\_ifcsname _oz:#1\_endcsname
   \_ea\_ea\_ea \_optnameA \_csname _oz:#1\_ea\_endcsname
   \_else \_failedoptname{#1}\_fi
}
\_def\_failedoptname #1{optname-fails:(#1)}
\_def\_optnameA #1?#2 #3 <#4 {\_ifx*#4#1#3#2\_else
   \_ifdim\_optsize<#4pt #1#3#2\_optnameC
   \_else \_afterfifi \_optnameA #1?#2 \_fi\_fi
}
\_def\_optnameC #1* {\_fi\_fi}
\_def\_afterfifi #1\_fi\_fi{\_fi\_fi #1}
\_def\_optfontalias #1#2{\_slet{_oz:#1}{_oz:#2}}

   \_doc -----------------------------
   \`\_fvars` `<rm-template> <bf-template> <it-template> <bi-template>`
   saves data for usage by the `\_currV` macro. If a template is only dot
   then previous template is used (it can be used if the font family doesn't
   dispose with all standard variants).
   \nl
   \`\_currV` expands to a template declared by `\_fvars` depending on the
   `<variant name>`. Usable only of standard four variants. Next variants
   can be declared by the \^`\famvardef` macro.
   \nl
   \`\_fsetV` `<key>=<value>,...,<key>=<value>` expands to
   `\def\_<key>V{<value>}` in the loop.
   \nl
   \`\_onlyif` `<key>=<value-a>,<value-b>...,<value-z>: {<what>}`
   runs <what> only if the `\_<key>V` is defined as `<value-a>` or
   `<value-b>` or ... or `<value-z>`.
   \nl
   \`\_prepcommalist` `ab,{},cd,\_end,` expands to `ab,,cd,` (auxiliary macro
   used in `\_onlyif`).\nl
   \`\_ffonum` is a shortcut for oldstyle digits font features used in
   font family files. You can do `\let\_ffonum=\ignoreit` if you don't want
   to set old digits together with `\caps`.
   \_cod -----------------------------

\_def\_fvars #1 #2 #3 #4 {%
   \_sdef{_fvar:rm}{#1}%
   \_sdef{_fvar:bf}{#2}%
   \_ifx.#2\_slet{_fvar:bf}{_fvar:rm}\_fi
   \_sdef{_fvar:it}{#3}%
   \_ifx.#3\_slet{_fvar:it}{_fvar:rm}\_fi
   \_sdef{_fvar:bi}{#4}%
   \_ifx.#4\_slet{_fvar:bi}{_fvar:it}\_fi
}
\_def\_currV{\_cs{_fvar:\_whatresize}}
\_def\_V{ }
\_def \_fsetV #1 {\_fsetVa #1,=,}
\_def \_fsetVa #1=#2,{\_isempty{#1}\_iffalse
   \_ifx,#1\_else\_sdef{_#1V}{#2}\_ea\_ea\_ea\_fsetVa\_fi\_fi
}
\_def \_onlyif #1=#2:#3{%
    \_edef\_act{\_noexpand\_isinlist{,\_prepcommalist #2,\_end,}{,\_cs{_#1V},}}\_act
    \_iftrue #3\_fi
}
\_def\_prepcommalist#1,{\_ifx\_end#1\_empty\_else #1,\_ea\_prepcommalist\_fi}
\_def\_ffonum {+onum;+pnum}

   \_doc -----------------------------
   The \`\moddef` `\<modifier> {<data>}` simply speaking does
   `\def\<modifier>{<data>}`, but we need to respect
   the family context. In fact, `\protected\def\_f:<current family>:<modifier>{<data>}` is
   performed and the `\<modifier>` is defined as
   \`\_famdepend``\<modifier>{_f:\_currfamily:<modifier>}`. It expands to
   `\_f:\_currfamily:<modifier>` value if it is defined or it prints
   the warning. When the `\_currfamily` value is
   changed then we can declare the same `\<modifier>` with a different meaning.

   When a user declares a prefixed variant of the `\<modifier>` then unprefixed
   modifier name is used in internal macros, this is the reason why we are using
   the \`\_remifirstunderscore``\_tmp` (where `\_tmp` expands to
   `_<something>` or to `<something>`. The `\_remifirstunderscore`
   redefines `\_tmp` in the way that it
   expands only to `<something>` without the first `_`.

   \`\_setnewmeaning` `<cs-name>=\_tmpa <by-what>` does exactly `\_let <csname>=\_tmpa`
   but warning is printed if <cs-name> is defined already and it is not a variant
   selector or font modifier.

   \`\_addtomodlist` `<font modifier>` adds given modifier to \`\_modlist`
   macro. This list is used after `\resetmod` when a new family is selected by
   a family selector, see \`\_resetfam` macro.
   This allows reinitializing the same current modifiers in the font context
   after the family is changed.
   \_cod -----------------------------

\_def \_moddef #1#2{\_edef\_tmp{\_csstring#1}%
   \_sdef{_f:\_currfamily:\_tmp}{\_addtomodlist#1#2\_reloading}%
   \_protected \_edef \_tmpa{\_noexpand\_famdepend\_noexpand#1{_f:\_noexpand\_currfamily:\_tmp}}%
   \_setnewmeaning #1=\_tmpa \moddef
}
\_protected \_def\_resetmod {\_cs{_f:\_currfamily:resetmod}} % private variant of \resetmod
\_def \_resetfam{\_def\_addtomodlist##1{}\_resetmod
   \_edef \_modlist{\_ea}\_modlist
   \_let\_addtomodlist=\_addtomodlistb
}
\_def \_currfamily{} % default current family is empty
\_def \_modlist{}    % list of currently used modifiers

\_def \_addtomodlist#1{\_addto\_modlist#1}
\_let \_addtomodlistb=\_addtomodlist

\_def\_famdepend#1#2{\_ifcsname#2\_endcsname \_csname#2\_ea\_endcsname \_else
   \_ifx\_addtomodlist\_addtomodlistb
      \_opwarning{\_string#1 is undeclared in family "\_currfamily", ignored}\_fi\_fi
}
\_def\_setnewmeaning #1=\_tmpa#2{%
   \_ifx #1\_undefined \_else \_ifx #1\_tmpa \_else
      \_opwarning{\_string#1 is redefined by \_string#2}%
   \_fi\_fi
   \_let#1=\_tmpa
}
\_public \moddef ;

   \_doc -----------------------------
   The \`\famvardef` `\<XX> {<data>}`
   uses analogical trick like \^`\moddef` with
   the \^`\_famdepend` macro. The auxiliary
   \`\_famvardefA` `\<XX> \_ten<XX> \_tryload<XX> {<data>}` is used.
   It does:
   \begitems
   * `\def \_tryload:<currfam>:<XX> {`\^`\fontdef`` \_ten<XX> {<data>}}` loads font `\_ten<XX>`,
   * `\protected\def \<XX> {\_famdepend \<XX> {_f:<currfam>:<XX>}}`,
   * `\def \_f:<currfam>:<XX> {\_tryload:<currfam>:<XX>\_ten<XX>}` keeps family dependent definition,
   * `\def \_currvar:_ten<XX> {\<XX>}` in order to the \^`\currvar` macro work correctly.
   \enditems
   `\famvardef\tt` behaves somewhat differently: it doesn't re-define the
   `\tt` macro which is defined  as `\_tryloadtt \_tentt` in sections~\ref[math-preload]
   and~\ref[unimath-codes]. It only re-defines the internal `\_tryloadtt` macro.
   \_cod -----------------------------

\_def\_famvardef#1{\_edef\_tmp{\_csstring#1}%
   \_ea\_famvardefA \_ea#1\_csname _ten\_tmp\_ea\_endcsname
      \_csname _tryload:\_currfamily:\_tmp\_endcsname
}
\_def\_famvardefA #1#2#3#4{% #1=\XX #2=\_tenXX #3=\_tryload:currfam:XX #4=data
   \_isinlist{.\_rm\_bf\_it\_bi\currvar\_currvar}#1\_iftrue
      \_opwarning{\_string\famvardef:
         You cannot re-declare standard variant selector \_string#1}%
   \_else
      \_def#3{\_fontdef#2{#4}}%
      \_protected\_edef\_tmpa{\_noexpand\_famdepend\_noexpand#1{_f:\_noexpand\_currfamily:\_tmp}}%
      \_ifx #1\_tt \_let\_tryloadtt=#3\_else \_setnewmeaning #1=\_tmpa \famvardef \_fi
      \_sdef{_f:\_currfamily:\_tmp}{#3#2}%
      \_sdef{_currvar:\_csstring#2}{#1}%
   \_fi
}
\_public \famvardef ;

   \_doc -----------------------------
   The \`\fontfam` `[<Font Family>]` does:
   \begitems
   * Convert its parameter to lower case and without spaces, e.g.\ `<fontfamily>`.
   * If the file `f-<fontfamily>.opm` exists read it and finish.
   * Try to load user defined `fams-local.opm`.
   * If the `<fontfamily>` is declared in `fams-local.opm` or `fams-ini.opm`
     read relevant file and finish.
   * Print the list of declared families.
   \enditems
   The `fams-local.opm` is read by the \`\_tryloadfamslocal` macro. It sets
   itself to `\_relax` because we need not load this file twice.
   The \`\_listfamnames` macro prints registered font families to the
   terminal and to the log file.
   \_cod -----------------------------

\_def\_fontfam[#1]{%
   \_lowercase{\_edef\_famname{\_ea\_removespaces #1 {} }}%
   \_isfile {f-\_famname.opm}\_iftrue \_opinput {f-\_famname.opm}%
   \_else
       \_tryloadfamslocal
       \_edef\_famfile{\_trycs{_famf:\_famname}{}}%
       \_ifx\_famfile\_empty \_listfamnames
       \_else \_opinput {\_famfile.opm}%
   \_fi\_fi
}
\_def\_tryloadfamslocal{%
   \_isfile {fams-local.opm}\_iftrue
      \_opinput {fams-local.opm}\_famfrom={}%
   \_fi
   \_let \_tryloadfamslocal=\_relax  % need not to load fams-local.opm twice
}
\_def\_listfamnames {%
   \_wterm{===== List of font families ======}
   \_begingroup
       \_let\_famtext=\_wterm
       \_def\_faminfo [##1]##2##3##4{%
           \_wterm{ \_space\_noexpand\fontfam [##1] -- ##2}%
       \_let\_famalias=\_famaliasA}%
       \_opinput {fams-ini.opm}%
       \_isfile {fams-local.opm}\_iftrue \_opinput {fams-local.opm}\_fi
       \_message{^^J}%
   \_endgroup
}
\_def\_famaliasA{\_message{ \_space\_space\_space\_space -- alias:}
   \_def\_famalias[##1]{\_message{[##1]}}\_famalias
}
\_public \fontfam ;

   \_doc -----------------------------
   When the `fams-ini.opm` or `fams-local.opm` files are read then we need
   to save only a mapping from family names or alias names to the font family file
   names. All other information is ignored in this case. But if these files
   are read by the `\_listfamnames` macro or when printing a catalog then more
   information is used and printed.\nl
   \`\_famtext` does nothing or prints the text on the terminal.
   \nl
   \`\_faminfo` `[<Family Name>] {<comments>} {<file-name>} {<mod-plus-vars>}`
   does\nl `\_def \_famf:<familyname> {<file-name>}` or prints information on
   the terminal.
   \nl
   \`\_famalias` `[<Family Alias>]` does `\def \_famf:<familyalias> {<file-name>}`
   where `<file-name>` is stored from the previous `\_faminfo` command. Or
   prints information on the terminal.
   \nl
   \`\_famfrom` declares type foundry or owner or designer of the font family.
   It can be used in `fams-ini.opm` or `fams-local.opm` and it is printed
   in the font catalog.
   \_cod -----------------------------

\_def\_famtext #1{}
\_def\_faminfo [#1]#2#3#4{%
   \_lowercase{\_edef\_tmp{\_ea\_removespaces #1 {} }}%
   \_sdef{_famf:\_tmp}{#3}%
   \_def\_famfile{#3}%
}
\_def\_famalias [#1]{%
   \_lowercase{\_edef\_tmpa{\_ea\_removespaces #1 {} }}%
   \_sdef{_famf:\_tmpa\_ea}\_ea{\_famfile}%
}
\_newtoks\_famfrom
\_input fams-ini.opm
\_let\_famfile=\_undefined
\_famfrom={}

   \_doc -----------------------------
   When the \^`\fontfam``[catalog]` is used then the file
   `fonts-catalog.opm` is read. The macro \^`\_faminfo` is redefined here
   in order to print catalog samples of all declared modifiers/variant
   pairs. The user can declare different samples and different behavior of
   the catalog, see the end of catalog listing for more information.
   The default parameters
   \`\catalogsample`, \`\catalogmathsample`, \`\catalogonly` and
   \`\catalogexclude` of the catalog are declared here.
   \_cod -----------------------------

\_newtoks \_catalogsample
\_newtoks \_catalogmathsample
\_newtoks \_catalogonly
\_newtoks \_catalogexclude
\_catalogsample={ABCDabcd Qsty fi fl áéíóúüů řžč ÁÉÍÓÚ ŘŽČ 0123456789}

\_public \catalogonly \catalogexclude \catalogsample \catalogmathsample ;

   \_doc -----------------------------
   The font features are managed in the \`\_fontfeatures` macro.
   They have their implicit values saved in the \`\_defaultfontfeatures`
   and the \`\setff` `{<features>}`
   can add next font features. If there is the same font feature as the newly
   added one then the old value is removed from the `\_fontfeatures` list.
   \_cod -----------------------------

\_def \_defaultfontfeatures {+tlig;}
\_def \_setff #1{%
   \_ifx^#1^\_let \_fontfeatures=\_defaultfontfeatures
   \_else \_edef\_fontfeatures{\_fontfeatures #1;}\_fi
   \_reloading
}
\_setff {} % default font features: +tlig;
\_def\_removefeature #1{%
    \_isinlist\_fontfeatures{#1}\_iftrue
        \_def\_tmp ##1#1##2;##3\_relax{\_def\_fontfeatures{##1##3}}%
        \_ea \_tmp \_fontfeatures \_relax
    \_fi
}
\_public \setff ;

   \_doc -----------------------------
   The \`\setfontcolor` and \`\setletterspace` are macros based on the
   special font features provided by \LuaTeX/ (and by \XeTeX/ too but it is not
   our business). The \`\setwordspace` recalculates the `\fontdimen2,3,4`
   of the font using the \`\setwsp` macro which is used by the
   \^`\_doresizeunifont` macro. It activates a dummy font feature `+Ws` too in
   order the font is reloded by the `\font` primitive (with independent
   `\fontdimen` registers).
   \_cod -----------------------------

\_def\_savedfontcolor{}
\_def\_savedletterspace{}
\_def\_savedwsp{}

\_def \_setfontcolor #1{\_removefeature{color=}%
    \_edef\_tmp{\_calculatefontcolor{#1}}%
    \_ifx\_tmp\_empty \_else \_edef\_fontfeatures{\_fontfeatures color=\_tmp;}\_fi
    \_reloading
}
\_def \_setletterspace #1{\_removefeature{letterspace=}%
    \_if^#1^\_else \_edef\_fontfeatures{\_fontfeatures letterspace=#1;}\_fi
    \_reloading
}
\_def \_setwordspace #1{%
   \_if^#1^\_def\_setwsp##1{}\_removefeature{+Ws}%
   \_else \_def\_setwsp{\_setwspA#1/}\_setff{+Ws}\_fi
   \_reloading
}
\_def\_setwsp #1{}
\_def\_setwspA #1{\_ifx/#1\_ea\_setwspB \_else\_afterfi{\_setwspC#1}\_fi}
\_def\_setwspB #1/#2/#3/#4{\_fontdimen2#4=#1\_fontdimen2#4%
   \_fontdimen3#4=#2\_fontdimen3#4\_fontdimen4#4=#3\_fontdimen4#4}
\_def\_setwspC #1/{\_setwspB #1/#1/#1/}

\_def\_calculatefontcolor#1{\_trycs{_fc:#1}{#1}} % you can define more smart macro ...
\_sdef{_fc:red}{FF0000FF}    \_sdef{_fc:green}{00FF00FF} \_sdef{_fc:blue}{0000FFFF}
\_sdef{_fc:yellow}{FFFF00FF} \_sdef{_fc:cyan}{00FFFFFF}  \_sdef{_fc:magenta}{FF00FFFF}
\_sdef{_fc:white}{FFFFFFFF}  \_sdef{_fc:grey}{00000080}  \_sdef{_fc:lgrey}{00000025}
\_sdef{_fc:black}{} % ... you can declare more colors...

\_public \setfontcolor \setletterspace \setwordspace ;

\_endcode %---------------------------------------------------


\sec[fontsystem] The Font Selection System
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

The basic principles of the Font Selection System used in \OpTeX/
was documented in the section~\ref[fontfam].

\secc Terminology

We distinguish between
\begitems
* {\em font switchers}, they are declared by the `\font` primitive or by
  \^`\fontlet` or \~`\fontdef` macros, they select given font.
* {\em variant selectors}, there are four basic variant selectors
  \^`\rm`, \^`\bf`, \^`\it`, \^`\bi`, there is a special selector \^`\currvar`.
  More variant selectors can be declared by the \~`\famvardef` macro.
  They select the font depending on the given variant and on the {\em font context}
  (i.e.\ on current family and on more features given by font modifiers).
  In addition, \OpTeX/ defines \~`\tt` as variant selector
  independent of chosen font family. It selects typewriter-like font.
* {\em font modifiers} are declared in a family (`\cond`, `\caps`) or are
  \"build in" (\^`\setfontsize``{<size spec>}`, \~`\setff{<features>}`).
  They do appropriate change in the {\em font context} but do not select
  the font.
* {\em family selectors} (for example `\Termes`, `\LMfonts`),
  they are declared typically in the {\em font family files}.
  They enable to switch between font families, they do appropriate
  change in the {\em font context} but do not select
  the font.
\enditems

These commands set their values locally. When the \TeX/ group is
left then the selected font and the {\em font context} are returned back to the values
used when the group was opened. They have the following features:

The {\em font context} is a set of macro values that will affect the
selection of real font when the variant selector is processed. It includes the
value of {\em current family}, current font size, and
more values stored by font modifiers.

The {\em family context} is the current family value stored in the font
context. The variant selectors declared by \~`\famvardef` and
font modifiers declared by \~`\moddef` are dependent on the {\em family context}.
They can have the same names but different behavior in different families.

The fonts registered in \OpTeX/ have their macros in the {\em font family files},
each family is declared in one font family file with the name `f-famname.opm`.
All families are collected in `fams-ini.opm` and users can give more
declarations in the file `fams-local.opm`.

\secc Font families, selecting fonts

The \^`\fontfam` `[<Font Family>]` opens the relevant font family file where
the `<Font Family>` is declared. The family selector is defined here by rules
described in the section~\ref[fontfamfiles]. Font modifiers and variant
selectors may be declared here.
The loaded family is set as current and `\rm` variant selector is processed.

The available declared font modifiers and declared variant selectors are
listed in the log file when the font family is load. Or you can print
`\fontfam[catalog]` to show available font modifiers and variant selectors.

The font modifiers can be independent, like `\cond` and `\light`. They can
be arbitrarily combined (in arbitrary order) and if the font family disposes
of all such sub-variants then the desired font is selected (after variant
selector is used). On the other hand, there are font modifiers that negates
the previous font modifier, for example: `\cond`, `\extend`. You can reset
all modifiers to their initial value by the \^`\resetmod` command.

You can open more font families by more \^`\fontfam` commands. Then the
general method to selecting the individual font is:

\begtt \catcode`\<=13
<family selector> <font modifiers> <variant selector>
\endtt
For example:
\begtt
\fontfam [Heros]  % Heros family is active here, default \rm variant.
\fontfam [Termes] % Termes family is active here, default \rm variant.
{\Heros \caps \cond \it The caps+condensed italics in Heros family is here.}
The Termes roman is here.
\endtt

There is one special command \^`\currvar` which acts as a variant selector.
It keeps the current variant and the font of such variant is
reloaded with respect to the current font context by the previously given family
selector and font modifiers.

You can use the \^`\setfontsize` `{<sizespec>}` command in the same sense as
other font modifiers. It saves information about font size to the font
context. See section~\ref[setfontsize]. Example:

\begtt
\rm default size \setfontsize{at14pt}\rm here is 14pt size \it italic is
in 14pt size too \bf bold too.
\endtt

A much more comfortable way to resize fonts is using OPmac-like commands
\~`\typosize` and \~`\typoscale`.
These commands prepare the right sizes for math
fonts too and they re-calculate many internal parameters like `\baselineskip`.
See section~\ref[opmac-fonts] for more information.


\secc Math Fonts
%---------------

Most font families are connected with a preferred Unicode-math font. This
Unicode-math is activated when the font family is loaded. If you don't prefer
this and you are satisfied with 8bit math CM+AMS fonts preloaded in the
\OpTeX/ format then you can use command \^`\noloadmath` before you load a first
font family.

If you want to use your specially selected Unicode-math font then use
\^`\loadmath` `{[<font_file>]}` or \^`\loadmath` `{<font_name>}` before first
`\fontfam` is used.


\secc[fontcommands] Declaring font commands
%----------------------------

Font commands can be font switches, variant selectors, font modifiers,
family selectors and defined font macros doing something with fonts.

\begitems
* Font switches can be decared by `\font` primitive (see
  section~\ref[fontprimitive]) or by \^`\fontlet` command (see
  section~\ref[fontlet]) or by \~`\fontdef` command (see
  sections~\ref[fontdef2] and~\ref[fontdef]).
  When the font switches are used then they select the given font independently
  of the current font context. They can be used
  in `\output` routine (for example) because we need to set fixed fonts
  in headers and footers.
* Variant selectors are \^`\rm`, \^`\bf`, \^`\it`, \^`\bi`, \~`\tt` and \^`\currvar`. More
  variant selectors can be declared by \~`\famvardef` command. They select a
  font dependent on the current font context, see section~\ref[famvardef].
  The `\tt` selector is documented in section~\ref[tt].
* Font modifiers are \"build in" or declared by \~`\moddef` command.
  They do modifications in the font context but don't select any font.
  \begitems
  * \"build-in" font modifiers are \^`\setfontsize` (see
    section~\ref[setfontsize]), \~`\setff` (see section~\ref[setff]),
    \~`\setfontcolor`, \~`\setletterspace` and \~`\setwordspace`
    (see section~\ref[specff]). They are independent of font family.
  * Font modifiers declared by \~`\moddef` depend on the font family and they
    are typically declared in font family files, see
    section~\ref[fontfamfiles].
  \enditems
* Family selectors set the given
  font family as current and re-set data used by the family-dependent font
  modifiers to initial values and to the currently used modifiers.
  They are declared in font family files
  by \~`\_famdecl` macro, see section~\ref[fontfamfiles].
* Font macros can be defined arbitrarily by `\def` primitive by users.
  See an example in section~\ref[fontmacros].
\enditems

All declaration commands mentioned here: `\font`, `\fontlet`, `\fontdef`, `\famvardef`,
`\moddef`, `\_famdecl` and `\def` make local assignment.

\secc[fontdef2] The `\fontdef` declarator in detail

The general format for \^`\fontdef` usage is
\begtt \catcode`\<=13
\fontdef\<font switch> {\<family selector> <font modifiers> \<variant selector>}
\endtt
%
where `\<family selector>` and `<font modifiers>` are optional and
`\<variant selector>` is mandatory.

The \^`\fontdef` does the following steps.
It pushes the current font context to a stack, it does modifications of the font
context by given `\<family selector>` and/or `<font modifiers>` and it
finds the real font by `\<variant selector>`. This font is not selected but
it is assigned to the declared `\<font switch>` (like `\font` primitive does
it). Finally, `\fontdef` pops the font context stack, so the current
font context is the same as it was before `\fontdef` is used.

More about `\fontdef` command including examples is written in
section~\ref[fontdef].


\secc[famvardef] The `\famvardef` declarator

You can declare a new variant selector by the \^`\famvardef` macro. This
macro has similar syntax as \^`\fontdef`:
\begtt \catcode`\<=13
\famvardef\<new variant selector> {\<family selector> <font modifiers> \<variant selector>}
\endtt
%
where `\<family selector>` and `<font modifiers>` are optional and
`\<variant selector>` is mandatory.
The `\<new variant selector>` should be used in the same sense as `\rm`,
`\bf` etc. It can be used as the final command in next
\^`\fontdef` or \^`\famvardef` declarators
too. When the `\<new variant selector>` is used in the normal text then it does
the following steps: pushes current font context to a stack, modifies font
context by declared `\<family selector>` and/or `<font modifiers>`,
runs following `\<variant selector>`.
This last one selects a real font. Then pops the font context stack.
The new font is selected but the font context has its original values.
This is main difference between `\famvardef\foo{...}` and `\def\foo{...}`.

Moreover, the \^`\famvardef` creates the `\<new variant selector>` family dependent.
When the selector is used in another family context than it is defined then a warning is
printed on the terminal \"<var selector> is undeclared in the current family"
and nothing happens. But you can declare the same variant selector by
\^`\famvardef` macro in the context of a new family. Then the same command
may do different work depending on the current font family.

Suppose that the selected font family provides the font modifier `\medium` for
mediate weight of fonts. Then you can declare:
\begtt
\famvardef \mf {\medium\rm}
\famvardef \mi {\medium\it}
\endtt
Now, you can use six independent variant selectors `\rm`, `\bf`, `\it`,
`\bi`, `\mf` and  `\mi` in the selected font family.

A `\<family selector>` can be written before `<font modifiers>` in the
`\famvardef` parameter. Then the `\<new variant selector>` is declared in
the current family but it can use fonts from another family represented by
the `\<family selector>`.

When you are mixing fonts from more families then you probably run
into a problem with incompatible ex-heights. This problem can be solved using
\^`\setfontsize` and \^`\famvardef` macros:
\begtt
\fontfam[Heros]  \fontfam[Termes]

\def\exhcorr{\setfontsize{mag.88}}
\famvardef\rmsans{\Heros\exhcorr\rm}
\famvardef\itsans{\Heros\exhcorr\it}

Compare ex-height of Termes \rmsans with Heros \rm and Termes.
\endtt

The variant selectors (declared by \~`\famvardef`) or font
modifiers (declared by \~`\moddef`) are (typically) control sequences in user name
space (`\mf`, `\caps`). They are most often declared in font family files and
they are loaded by \^`\fontfam`. A conflict with such names in
user namespace can be here. For example: if `\mf` is defined by a user and then
`\fontfam[Roboto]` is used then `\famvardef\mf` is performed for Roboto
family and the original meaning of `\mf` is lost. But \OpTeX/ prints warning
about it. There are two cases:

\begtt
\def\mf{Metafont}
\fontfam[Roboto]  % warning: "The \mf is redefined by \famvardef" is printed
  or
\fontfam[Roboto]
\def\mf{Metafont} % \mf variant selector redefined by user, we suppose that \mf
                  % is used only in the meaning of "Metafont" in the document.
\endtt

\secc[tt] The `\tt` variant selector

\^`\tt` is an additional special variant selector which is defined as \"select typewriter
font independently of the current font family". By default, the typewriter font-face
from LatinModern font family is used.

The \^`\tt` variant selector is used in \OpTeX/ internal macros
\^`\_ttfont` (verbatim texts) and \^`\_urlfont` (printing URL's).

You can redefine the behavior of `\tt` by \^`\famvardef`. For example:

\begtt
\fontfam[Cursor]
\fontfam[Heros]
\fontfam[Termes]
\famvardef\tt{\Cursor\setff{-liga;-tlig}\rm}

Test in Termes: {\tt text}. {\Heros\rm Test in Heros: {\tt text}}.
Test in URL \url{http://something.org}.
\endtt
%
You can see that `\tt` stay family independent. This is a special feature only
for `\tt` selector. New definition is used in \^`\_ttfont` and \^`\_urlfont` too.
It is recommended to use `\setff{-liga;-tlig}` to suppress the
ligatures in typewriter fonts.

If Unicode math font is loaded then the `\tt` macro selects typewriter
font-face in math mode too. This face
is selected from used Unicode math font and it is independent of
`\famvardef\tt` declaration.


\secc[fontmacros] Font commands defined by `\def`

Such font commands can be used as fonts selectors for titles, footnotes,
citations, etc. Users can define them.

The following example shows how to define a \"title-font selector".
Titles are not only bigger but they are typically in the bold variant. When a user puts
`{\it...}` into the title text then he/she expects bold italic here, no normal
italic. You can remember the great song by John Lennon \"Let It Be" and
define:

\begtt
\def\titlefont{\setfontsize{at14pt}\bf \let\it\bi}
...
{\titlefont Title in bold 14pt font and {\it bold 14pt italics} too}
\endtt

\OpTeX/ defines similar internal commands \^`\_titfont`, \^`\_chapfont`, \^`\_secfont` and
\^`\_seccfont`, see section~\ref[sections]. The commands \^`\typosize` and
\^`\boldify` are used in these macros. They set the math fonts to given size too and they
are defined in section~\ref[opmac-fonts].


\secc[setff] Modifying font features
%----------------------------

Each OTF font provides \"font features". You can list these font features
by `otfinfo -f font.otf`. For example, LinLibertine fonts provide `frac` font
feature. If it is active then fractions like 1/2 are printed in a special
form.

The font features are part of the font context data.
The macro \^`\setff` `{<feature>}` acts like family independent font modifier and
prepares a new <feature>. You must use a variant selector in order to
reinitialize the font with the new font feature. For example
\^`\setff``{+frac}\rm` or \^`\setff``{+frac}`\^`\currvar`. You can declare a new variant
selector too:

\begtt
\fontfam[LinLibertine]
\famvardef \fraclig {\setff{+frac}\currvar}
Compare 1/2 or 1/10 \fraclig to 1/2 or 1/10.
\endtt

If the used font does not support the given font feature then the font is reloaded
without warning nor error, silently. The font feature is not activated.

The `onum` font feature (old-style digits) is connected to `\caps` macro for
Caps+SmallCaps variant in \OpTeX/ font family files. So you need not
create a new modifier, just use `{\caps`\^`\currvar`` 012345}`.


\secc[specff] Special font modifiers
%---------------------------

Despite the font modifiers declared in the font family file (and dependent on
the font family), we have following font modifiers (independent of font
family):

\begtt \catcode`\<=13
\setfontsize{<sizespec>}    % sets the font size
\setff{<font feature>}       % adds the font feature
\setfontcolor{<color>}     % sets font color
\setletterspace{<number>} % sets letter spacing
\setwordspace{<scaling>}    % modifies word spacing
\endtt

The \^`\setfontsize` command is described in the section \ref[setfontsize].
The \^`\setff` command was described in previous subsection.

\^`\setfontcolor` `{<color>}` specifies the color and the opacity of the text.
The <color> parameter should be in the hexadecimal format of four bytes
`<red><green><blue><opacity>`, for example `FF0080FF` means full red, zero
green, half blue and full opacity. You can use names `red`, `green`, `blue`,
`yellow`, `cyan`, `magenta`, `white`, `grey`, `lgrey` (without the backslash)
instead of the hexadecimal specification.
The empty parameter `<color>` means default black color.

These colors of fonts are implemented using \LuaTeX/ internal font feature. This
is different approach than using colors in section \ref[colors].

\^`\setletterspace` `{<number>}` specifies the letter spacing of the font. The
`<number>` is a decimal number without unit. The unit is supposed as 1/100 of
the font size. I.e. `2.5` means 0.25 pt when the font is at 10 pt size. The
empty parameter `<number>` means no letter spacing which is the default.

\^`\setwordspace` `{<scaling>}` scales the default interword space (defined in the
font) and its stretching and shrinking parameters by given `<scaling>`
factor. For example `\setwordspace{2.5}` multiplies interword space by 2.5.
\^`\setwordspace` can use different multiplication factors if its parameter is in the
format `{/<default>/<stretching>/<shrinking>}`. For example,
`\setwordspace{/1/2.5/1}` enlarges only stretching 2.5~times.

You can use `\setff` with other font features provided by Lua\TeX/ and `luaotfload` package
(see documentation of `loaotfload` package for more information):

\begtt
\setff{embolden=1.5}\rm  % font is bolder because outline has nonzero width
\setff{slant=0.2}\rm     % font is slanted by a linear transformation
\setff{extend=1.2}\rm    % font is extended by a linear transformation.
\setff{colr=yes}\rm      % if the font includes colored characters, use colors
\setff{upper}\rm         % to uppercase (lower=lowecase) conversion at font level
\setff{fallback=name}\rm % use fonts from a list given by name if missing chars
\endtt

Use font transformations `embolden`, `slant`, `extend` and \^`\setletterspace`,
\^`\setwordspace` with care. The best setting of these values is the default
setting in every font, of course. If you really need to set a different
letter spacing then it is strongly recommended to add `\setff{-liga}`
to disable ligatures. And setting a positive letter spacing probably
needs to scale interword spacing too.

All mentioned font modifiers (except for `\setfontsize`) work only
with Unicode fonts loaded by \^`\fontfam`.

\secc[fontfamfiles] How to create the font family file
%------------------------------------------------------

\printdoctail f-heros.opm

\printdoctail f-lmfonts.opm

\secc How to register the font family in the Font Selection System
%---------------------------------------------------------------

\printdoctail fams-ini.opm

\secc[exfont] Notices about extension of `\font` primitive
%---------------------------------------------------------

Unicode fonts are loaded by extended `\font` primitive. This extension is
not activated in \OpTeX/ by default, \^`\initunifonts` macro activates it.
You need not use \^`\initunifonts` explicitly if \^`\fontfam` macro is
used because \^`\fontfam` runs it internally.

The \^`\initunifonts` loads the Lua code from the Luaotfload package which
implements the `\font` primitive extension. See its
documentation `luaotfload-latex.pdf` for information about
all possibilities of extended `\font` primitive.

The \OpTeX/ format is initialized by `luatex` engine by default but
you can initialize it by `luahbtex` engine too. Then the harfbuzz library is
ready to use for font rendering as an alternative to build-in font renderer
from Luaotfload. The harfbuzz library gives more features for rendering
Indic and Arabic scripts. But it is not used as default, you need to specify
`mode=harf` in the fontfeatures field when `\font` is used. Moreover, when
`mode=harf` is used, then you must specify `script` too. For example

\begtt
\font\devafont=[NotoSansDevanagari-Regular]:mode=harf;script=dev2
\endtt
%
If the `luahbtex` engine is not used then `mode=harf` is ignored. See
Luaotfload documentation for more information.

\endinput

2021-04-22  \_ffonum introduced
2021-04-19  \setwordspace: parameter format {/A/B/C} implemented.
2021-02-25  \_ttunifont introduced
2021-01-27  lua hack (print function) removed because luaotfload 3.17 removes bug.
2020-12-12  \_modlist added, doc improved
2020-04-18  \_tryloadfamslocal introduced
            \_fontdecl -> \_famdecl with different concept
2020-03-18  released