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
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
|
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
\_codedecl \fontfam {Fonts selection system <2022-12-01>} % preloaded in format
\_doc -----------------------------
The main principle of the Font Selection System is: run one or more
modifiers followed by \^`\fontsel`. Modifiers save data and \^`\fontsel`
selects the font considering saved data. Each basic variant selector
\`\rm`, \`\bf`, \`\it`, \`\bi`, and \`\tt` runs internal variant modifier
\`\_fmodrm`, \`\_fmodbf`, \`\_fmodit`, \`\_fmodbi` and \`\_fmodtt`.
These modifiers save their data to the \`\_famv` macro which is
`rm` or `bf` or `it` or `bi` or `tt`. The \`\currvar` selector
is \^`\fontsel` by default, but variant selectors declared by
\^`\famvardef` change it.
\_cod -----------------------------
\_def\_famv{rm} % default value
\_protected\_def \_fmodrm {\_def\_famv{rm}}
\_protected\_def \_fmodbf {\_def\_famv{bf}}
\_protected\_def \_fmodit {\_def\_famv{it}}
\_protected\_def \_fmodbi {\_def\_famv{bi}}
\_protected\_def \_fmodtt {\_def\_famv{tt}}
\_protected\_def \_rm {\_fmodrm \_fontsel \_marm}
\_protected\_def \_bf {\_fmodbf \_fontsel \_mabf}
\_protected\_def \_it {\_fmodit \_fontsel \_mait}
\_protected\_def \_bi {\_fmodbi \_fontsel \_mabi}
\_protected\_def \_tt {\_fmodtt \_fontsel \_matt}
\_protected\_def \_currvar {\_fontsel} \_protected\_def \currvar{\_currvar}
\_public \rm \bf \it \bi \tt ;
\_doc -----------------------------
The \`\fontsel` creates the <font switch> in the format `\_ten<famv>`
and loads the font associated to the <font switch>.
The loading is done by:
\begitems \style a
* `\letfont <font switch> = \savedswitch \_sizespec`
* `\font <font switch> = \fontnamegen \_sizespec`
\enditems
The a) variant is used when \~`\_fontnamegen` isn't defined, i.e.\
\^`\fontfam` wasn't used: only basic variant and \^`\_sizespec` is taken
into account. The b) variant is processed when \^`\fontfam` was used:
all data saved by all font modifiers are used during expansion of \^`\_fontnamegen`.\nl
After the font is loaded, final job is done by \`\_fontselA``<font-switch>`.
\_cod -----------------------------
\_protected\_def \_fontsel {%
\_ifx\_fontnamegen\_undefined % \fontfam was not used
\_ea\_let \_ea\_tmpf \_csname _ten\_famv\_endcsname
\_ea\_fontlet \_csname _ten\_xfamv\_endcsname \_tmpf \_sizespec
\_else % \fontfam is used
\_ea\_font \_csname _ten\_xfamv\_endcsname {\_fontnamegen}\_sizespec
\_fi \_relax
\_ea \_fontselA \_csname _ten\_xfamv\_endcsname
}
\_def\_fontselA #1{%
\_protected\_def \_currvar {\_fontsel}% default value of \_currvar
\_logfont #1% font selecting should be logged.
\_setwsp #1% wordspace setting
\_fontloaded #1% initial settings if font is loaded firstly
#1% select the font
}
\_def \_logfont #1{}
\_def \_xfamv {\_famv}
\_public \fontsel ;
\_doc -----------------------------
If a font is loaded by macros \^`\fontsel` or \^`\resizethefont` then the
\`\_fontloaded``<font switch>` is called immediately after it. If the font
is loaded first then its `\skewchar` is equal to $-1$. We run
\`\_newfontloaded``<font switch>` and set `\skewchar=-2` in this case.
A user can define a `\_newfontloaded` macro. We are sure that
`\_newfontloaded` macro is called only once for each instance of the font
given by its name, OTF features and size specification. The `\skewchar` value is
globally saved to the font (like `\fontdimen`). If it is used in math
typesetting then it is set to a positive value.\nl
The `\_newfontloaded` should be defined for micro-typographic configuration of
fonts, for example. The `mte.opm` package uses it. See also
\ulink[http://petr.olsak.net/optex/optex-tricks.html\#fontexpand]{\OpTeX/ trick 0058}.
\_cod -----------------------------
\_def\_fontloaded #1{\_ifnum\_skewchar#1=-1 \_skewchar#1=-2 \_newfontloaded#1\_fi}
\_def\_newfontloaded #1{}
\_doc -----------------------------
\`\_ttunifont` is default font for \^`\tt` variant when \^`\initunifonts` is declared.
User can re-define it or use \^`\famvardef``\tt`.
The \`\_unifmodtt` macro is used instead \^`\_fmodtt` after
\^`\initunifonts`. It ignores the loading part of the following \^`\fontsel`
and do loading itself.
\_cod -----------------------------
\_def\_ttunifont{[lmmono10-regular]:\_fontfeatures-tlig;}
\_def\_unifmodtt\_fontsel{% ignore following \_fontsel
\_ea\_font \_csname _ten\_ttfamv\_endcsname {\_ttunifont}\_sizespec \_relax
\_ea\_fontselA \_csname _ten\_ttfamv\_endcsname
\_def \_currvar{\_tt}%
}
\_def\_ttfamv{tt}
\_doc ----------------------------
A large part of the Font Selection System was re-implemented in Feb. 2022.
We want to keep backward compatibility:
\_cod ----------------------------
\_def \_tryloadrm\_tenrm {\_fmodrm \_fontsel}
\_def \_tryloadbf\_tenbf {\_fmodbf \_fontsel}
\_def \_tryloadit\_tenit {\_fmodit \_fontsel}
\_def \_tryloadbi\_tenbi {\_fmodbi \_fontsel}
\_def \_tryloadtt\_tentt {\_fmodtt \_fontsel}
\_def \_reloading {}
\_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 current 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 \_unichars \_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 \_rm \_ea \_endinput \_fi
}
\_def\_initfontfamily{%
\_csname _f:\_currfamily:main.fam\_endcsname \_rm
}
\_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,\_fin,` 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{\_trycs{_fvar:\_famv}{rm}}
\_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,\_fin,}{,\_cs{_#1V},}}\_act
\_iftrue #3\_fi
}
\_def\_prepcommalist#1,{\_ifx\_fin#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.
\`\_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}%
\_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
\_ifcsname _f:\_currfamily:\_ea\_csstring \_currvar \_endcsname
\_else \_ea\_ifx\_currvar\_tt \_else \_def\_currvar{\_fontsel}\_fi
\_fi % corrected \_currvar in the new family
}
\_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 -----------------------------
\`\fontdef` `<font-switch> {<data>}` does:
\begtt \catcode`\<=13
\begingroup <data> \ea\endgroup \ea\let \ea<font-switch> \the\font
\endtt
It means that font modifiers used in <data> are applied in the group and the
resulting selected font (current at the end of the group) is set to the
<font-switch>.
We want to declare <font-switch> in its real name directly by `\font` primitive in
order to save this name for reporting later (in overfull messages, for
example). This is the reason why \`\_xfamv` and \`\_ttfamv` are re-defined locally here.
They have precedence when \^`\fontsel` constructs the <font switch> name.
\_cod -----------------------------
\_protected\_def \_fontdef #1#2{\_begingroup
\_edef\_xfamv{\_csstring#1}\_let\_ttfamv\_xfamv #2%
\_ea\_endgroup\_ea \_let\_ea #1\_the\_font
}
\_public \fontdef ;
\_doc -----------------------------
The \`\famvardef` `\xxx {<data>}` does, roughly speaking:
\begtt \catcode`\<=13
\def \xxx {{<data>\ea}\the\font \def\_currvar{\xxx}}
\endtt
but the macro `\xxx` is declared as family-dependent.
It is analogically as in `\moddef`.
The `\xxx` is defined as `\_famdepend\xxx{_f:\_currfamily:xxx}`
and `\_f:<currfam>:xxx` is defined as mentioned.\nl
`\famvardef\tt` behaves somewhat differently: it defines internal version
`\_tt` (it is used in \^`\_ttfont` and \^`\_urlfont`) and set `\tt` to
the same meaning.
\_cod -----------------------------
\_protected\_def \_famvardef #1#2{%
\_sdef{_f:\_currfamily:\_csstring#1}%
{{\_edef\_xfamv{\_csstring#1}\_let\_ttfamv\_xfamv #2\_ea}\_the\_font \_def\_currvar{#1}}%
\_protected\_edef\_tmpa {%
\_noexpand\_famdepend\_noexpand#1{_f:\_noexpand\_currfamily:\_csstring#1}}%
\_ifx #1\tt
\_protected\_def\_tt{{\_def\_xfamv{tt}#2\_ea}\_the\_font \_def\_currvar{\_tt}}%
\_let\tt=\_tt
\_else \_setnewmeaning #1=\_tmpa \famvardef
\_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 -----------------------------
\_protected\_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>}` (only if <file-name> differs
from `f-<familyname>`) or prints information on the terminal. The
<mod-plus-vars> data are used when printing the font catalog.
\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 {} }}%
\_edef\_tmpa{f-\_tmp}\_def\_famfile{#3}%
\_unless\_ifx\_tmpa\_famfile \_sdef{_famf:\_tmp}{#3}\_fi
}
\_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.
It expands to
\begitems
* \`\_defaultfontfeatures` -- used for each font,
* \`\_ffadded` -- features added by \^`\setff`,
* \`\_ffcolor` -- features added by \^`\setfontcolor` (this is obsolette)
* \`\_ffletterspace` -- features added by \^`\setletterspace`,
* \`\_ffwordspace` -- features added by \^`\setwordspace`.
\enditems
The macros \^`\_ffadded`, \^`\_ffcolor`, \^`\_ffletterspace`,
\^`\_ffwordspace` are empty by default.
\_cod -----------------------------
\_def \_fontfeatures{\_defaultfontfeatures\_ffadded\_ffcolor\_ffletterspace\_ffwordspace}
\_def \_defaultfontfeatures {+tlig;}
\_def \_ffadded{}
\_def \_ffcolor{}
\_def \_ffletterspace{}
\_def \_ffwordspace{}
\_doc -----------------------------
The \`\setff` `{<features>}` adds next font features to \^`\_ffadded`.
Usage \^`\setff{}` resets empty set of all \^`\_ffadded` features.
\_cod -----------------------------
\_def \_setff #1{%
\_ifx^#1^\_def\_ffadded{}\_else \_edef\_ffadded{\_ffadded #1;}\_fi
}
\_public \setff ;
\_doc -----------------------------
\`\setletterspace` is based on the
special font features provided by `luaotfload` package.
The \`\setwordspace` recalculates the `\fontdimen2,3,4`
of the font using the \`\setwsp` macro which is used by the
\^`\_fontselA` macro. It activates a dummy font feature `+Ws` too in
order the font is reloded by the `\font` primitive (with independent
`\fontdimen` registers).
\`\setfontcolor` is kept here only for backward compatibility but not
recommended. Use real color switches and the \^`\transparency` instead.
\_cod -----------------------------
\_def \_setfontcolor #1{%
\_edef\_tmp{\_calculatefontcolor{#1}}%
\_ifx\_tmp\_empty \_def\_ffcolor{}\_else \_edef\_ffcolor{color=\_tmp;}\_fi
}
\_def \_setletterspace #1{%
\_if^#1^\_def\_ffletterspace{}\_else \_edef\_ffletterspace{letterspace=#1;}\_fi
}
\_def \_setwordspace #1{%
\_if^#1^\_def\_setwsp##1{}\_def\_ffwordspace{}%
\_else \_def\_setwsp{\_setwspA#1/}\_def\_ffwordspace{+Ws;}\_fi
}
\_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 ;
\_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}}
\_setfontsize {at10pt} % default font size
\_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 switches}, 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
\"built-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 name 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` `{<size spec>}` 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]).
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 \"built-in" or declared by \~`\moddef` command.
They do modifications in the font context but don't select any font.
\begitems
* \"built-in" font modifiers are \^`\setfontsize` (see
section~\ref[setfontsize]), \~`\setff` (see section~\ref[setff]),
\~`\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
You can declare `\<font-switch>` by the \^`\fontdef` command.
\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 resulting `\<font-switch>` declared by \~`\fontdef` is \"fixed font switch"
independent of the font context. More exactly, it is
a fixed font switch when it is {\em used}. But it can depend on the current font
modifiers and font family and given font modifiers when it is {\em declared}.
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.
\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>` declared by `\famvardef` 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 the public
namespace (`\mf`, `\caps`). They are most often declared in font family files and
they are loaded by \^`\fontfam`. A conflict with such names in
the public 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).
The behavior of \^`\tt` can be re-defined 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 definitions of \^`\_ttfont` and \^`\_urlfont` are done 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{<size spec>} % sets the font size
\setff{<font feature>} % adds the font feature
\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.
\^`\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
\endinput
2022-12-01 \faminfo saves f-<filename> to the format only when needed
2022-11-08 \protected: \fontdef, \famvardef, \fontfam
2022-02-22 Font Selection System reimplemented, \fontsel introduced
2021-09-24 \_unichars used in \initunifonts
2021-07-16 \initunifonts: optex_hook_into_luaotfload added.
2021-05-23 concept of \_fontfeatures macro re-implemented
2021-05-02 simpler \_resizefont, better concept of doc, moving parts from fonts-resize
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
|