font-ini.mklx /size: 102 Kb    last modification: 2021-10-28 13:51
1%D \module
2%D   [       file=font-ini,
3%D        version=1998.09.11, % (second)
4%D        version=2001.02.20, % (third)
5%D          title=\CONTEXT\ Font Macros,
6%D       subtitle=Initialization,
7%D         author=Hans Hagen,
8%D           date=\currentdate,
9%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
10%C
11%C This module is part of the \CONTEXT\ macro||package and is
12%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
13%C details.
14
15% todo: frozen tolerant iftok etc
16
17% todo: < 3 pt => 3pt
18% todo: check where more class usage
19% todo: split font-nam (style/alternative/size)
20% todo: split font-dim (scales etc)
21% todo: reconsider defaultfontclass
22
23%D Beware, we use a special set of parameters here:
24%D
25%D \starttabulate[|l|l|]
26%D \NC system variable (fixed) \NC \type {\s!text}           \NC \NR
27%D \NC system variable (fixed) \NC \type {\s!script}         \NC \NR
28%D \NC system variable (fixed) \NC \type {\s!scriptscript}   \NC \NR
29%D \NC system variable (fixed) \NC \type {\s!x}              \NC \NR
30%D \NC system variable (fixed) \NC \type {\s!xx}             \NC \NR
31%D \NC variable (value)        \NC \type {\v!big}            \NC \NR
32%D \NC variable (value)        \NC \type {\v!small}          \NC \NR
33%D \NC constant (regular key)  \NC \type {\c!interlinespace} \NC \NR
34%D \NC constant (regular key)  \NC \type {\c!em}             \NC \NR
35%D \stoptabulate
36%D
37%D The math related ones are similar to the ones used in \TEX\ itself,
38%D the size related ones show up as keywords in the user interface
39%D when switching sizes, and the two constants are used in key|/|value
40%D situations.
41
42%D We should consider design sizes ... maybe kick 'm out which removes
43%D the size code and simplifies things considerably. After all, there
44%D will be no latin modern math in sizes.
45
46\writestatus{loading}{ConTeXt Font Macros / Initialization}
47
48%D Documentation is somewhat messy as it contains bits and pieces of
49%D previous versions.
50
51\unprotect
52
53%D There are several ways to specify a font. Three of them are pure \TEX\ ones, the
54%D fourth one is new:
55%D
56%D \starttyping
57%D \font\name=cmr12
58%D \font\name=cmr12 at 10pt
59%D \font\name=cmr12 scaled 2
60%D \font\name=cmr12 sa 1.440
61%D \stoptyping
62%D
63%D The non||\TEX\ alternative \type{sa} stands for {\em scaled at}. This means as
64%D much as: scale the bodyfontsize with this factor. The scaled option is not that
65%D useful as one needs to know the design size.
66%D
67%D Because \type {sa} (scaled at) and \type {mo} (mapped on) are not low level \TEX\
68%D supported alternatives, we have to test for it ourselves. In doing so, we need an
69%D auxiliary \DIMENSION. We cannot use \type{\scratchdimen} because font loading can
70%D happen at any moment due to postponed loading. We could instead have used dirty
71%D grouping tricks, but this one works too.
72
73% \enableexperiments[fonts.autorscale]
74%
75% \starttypescript[mscore]
76%     \definetypeface [mscore] [rm] [serif] [mscoretimes]   [default]
77%     \definetypeface [mscore] [ss] [sans]  [mscorearial]   [default] [rscale=auto] % 0.860]
78%     \definetypeface [mscore] [tt] [mono]  [mscorecourier] [default] [rscale=auto] % 1.065]
79%     \definetypeface [mscore] [mm] [math]  [times]         [default] [rscale=auto] % 1.020]
80% \stoptypescript
81%
82% \starttext
83%    \setupbodyfont[mscore,12pt]
84%    \startTEXpage
85%        test \ss test \tt test
86%    \stopTEXpage
87% \stoptext
88
89% \definetypeface[one][rm][serif][computer-roman][default]
90% \definetypeface[two][rm][serif][computer-roman][default][rscale=.9]
91%
92% {\one \bf test \two test}
93% {\one \bf test \pushcurrentfont \two \popcurrentfont test}
94
95%D \macros
96%D   {rm,ss,tt,hw,cg}
97%D
98%D Fonts are defined in separate files. When we define a font, we distinguish
99%D between several styles. In most cases we will use:
100%D
101%D \startlinecorrection
102%D \starttable[|l||]
103%D \HL
104%D \NC roman regular serif    \NC \type{\rm} \NC\FR
105%D \NC sansserif sans support \NC \type{\ss} \NC\MR
106%D \NC type teletype mono     \NC \type{\tt} \NC\LR
107%D \HL
108%D \stoptable
109%D \stoplinecorrection
110%D
111%D The number of styles is not limited to these three. When using Lucida Bright we
112%D can for instance also define:
113%D
114%D \startlinecorrection
115%D \starttable[|l||]
116%D \HL
117%D \NC handwritten  \NC \type{\hw} \NC\FR
118%D \NC calligraphic \NC \type{\cg} \NC\LR
119%D \HL
120%D \stoptable
121%D \stoplinecorrection
122%D
123%D Within such a font set (\type{cmr}) and style (\type{\rm}) we can define a number
124%D of text font alternatives:
125%D
126%D \startlinecorrection
127%D \starttable[|l||]
128%D \HL
129%D \NC typeface    \NC \type{\tf} \NC\FR
130%D \NC boldface    \NC \type{\bf} \NC\MR
131%D \NC slanted     \NC \type{\sl} \NC\MR
132%D \NC italic      \NC \type{\it} \NC\MR
133%D \NC boldslanted \NC \type{\bs} \NC\MR
134%D \NC bolditalic  \NC \type{\bi} \NC\MR
135%D \NC smallcaps   \NC \type{\sc} \NC\LR
136%D \HL
137%D \stoptable
138%D \stoplinecorrection
139%D
140%D Internally fonts are stored as combination of size, style
141%D and alternative, e.g. \type{12pt}+\type{\ss}+\type{\bf}. Users are not confronted
142%D with sizes, but use the style or style+alternative to activate them.
143%D
144%D During the definition of a bodyfont one can also declare the available larger
145%D alternatives:
146%D
147%D \starttyping
148%D \tf \tfa \tfb \tfc ...
149%D \bf \bfa \bfb \bfc ...
150%D \sl \sla \slb \slc ...
151%D \stoptyping
152%D
153%D The smaller ones are automatically supplied and derived from
154%D the the bodyfont environment.
155%D
156%D \starttyping
157%D \tfx \tfxx
158%D \bfx \bfxx
159%D \slx \slxx
160%D \stoptyping
161%D
162%D There are only two smaller alternatives per style. The larger alternatives on the
163%D other hand have no limitations.
164%D
165%D These larger alternatives are mostly used in chapter and section titles or on
166%D title pages. When one switches to a larger alternative, the bold an other ones
167%D automatically adapt themselves:
168%D
169%D \startbuffer
170%D \tfd Hi \bf there\sl, here \tfb I \bf am
171%D \stopbuffer
172%D
173%S \startnarrower
174%D \typebuffer
175%S \stopnarrower
176%D
177%D therefore becomes:
178%D
179%D \startexample
180%D \getbuffer
181%D \stopexample
182%D
183%D Maybe this mechanism isn't always as logic, but as said before, we tried to make
184%D it as intuitive as possible.
185%D
186%D So a specific kind of glyph can be characterized by:
187%D
188%D \startnarrower
189%D family (cmr) + bodyfont (12pt) + style (rm) + alternative (bf) + size (a)
190%D \stopnarrower
191%D
192%D The last component (the size) is optional.
193%D
194%D We introduced \type {\tf} as command to call for the current normally sized
195%D typeface. This commands results in roman, sans serif, teletype or whatever style
196%D is in charge. Such rather massive switches of style sometimes take more
197%D processing time than comfortable. Of course there is a workaround for this: we
198%D can call fonts directly by means of commands like:
199%D
200%D \starttyping
201%D \rmtf \sssl \tttf \rmbsa
202%D \stoptyping
203%D
204%D One should realize that this fast calls have limitations, they lack for instance
205%D automatic super- and subscript support.
206%D
207%D This leaves us two more commands: \type {\tx} and \type {\txx}. These activate a
208%D smaller and even more smaller font than the current one and adapt themselves to
209%D the current alternative, so when \type {\bf} is active, \type {\tx} gives a
210%D smaller boldface, which in turn can be called directly by \type {\bfx}.
211%D
212%D These two smaller alternatives are specified by the bodyfont environment and
213%D therefore not necessarily have similar sizes as \type {\scriptsize} and \type
214%D {\scriptscriptsize}. The main reason for this incompatibility (which can easily
215%D be undone) lays in the fact that we often want a bit bigger characters than in
216%D math mode. In \CONTEXT\ for instance the \type {\tx} and \type {\txx} commands
217%D are used for surrogate \cap {smallcaps} which support both nesting and
218%D alternatives, like in {\bf \cap {a \cap {small} world}}, which was typeset by
219%D
220%D \starttyping
221%D \bf\cap{a \cap{small} world}
222%D \stoptyping
223%D
224%D And compare $\rm \scriptstyle THIS$ with the slightly larger \cap {THIS}:
225%D \ruledhbox {$\rm \scriptstyle scriptstyle: THIS$} or \ruledhbox {\cap {x style:
226%D THIS}} makes a big difference.
227%D
228%D The \type {x..d} sizes should be used grouped. If you don't group them, i.e. call
229%D them in a row, \CONTEXT\ will not be able to sort out your intention (\type {x}
230%D inside \type {d} inside \type {x}. etc.). The following table demonstrates this:
231%D
232%D \def\FontState{\setstrut\ruledhbox{\strut Hello}}
233%D
234%D \starttabulate[|||||]
235%D \HL
236%D \NC \rlap{\quad\bf grouped} \NC \NC \type {\tx} \NC \type {\txx} \NC \NR
237%D \HL
238%D \NC \type{\tfx}  \NC \tfx  \FontState \NC \tfx \tx \FontState \NC \tfx \txx \FontState  \NC \NR
239%D \NC \type{\tfxx} \NC \tfxx \FontState \NC \tfxx\tx \FontState \NC \tfxx\txx \FontState  \NC \NR
240%D \NC \type{\tf}   \NC \tf   \FontState \NC \tf  \tx \FontState \NC \tf  \txx \FontState  \NC \NR
241%D \NC \type{\tfa}  \NC \tfa  \FontState \NC \tfa \tx \FontState \NC \tfa \txx \FontState  \NC \NR
242%D \NC \type{\tfb}  \NC \tfb  \FontState \NC \tfb \tx \FontState \NC \tfb \txx \FontState  \NC \NR
243%D \NC \type{\tfc}  \NC \tfc  \FontState \NC \tfc \tx \FontState \NC \tfc \txx \FontState  \NC \NR
244%D \NC \type{\tfd}  \NC \tfd  \FontState \NC \tfd \tx \FontState \NC \tfd \txx \FontState  \NC \NR
245%D \NC \type{\tfx}  \NC \tfx  \FontState \NC \tfx \tx \FontState \NC \tfx \txx \FontState  \NC \NR
246%D \NC \type{\tfxx} \NC \tfxx \FontState \NC \tfxx\tx \FontState \NC \tfxx\txx \FontState  \NC \NR
247%D \HL
248%D \stoptabulate
249%D
250%D \blank
251%D
252%D \starttabulate[|||||]
253%D \HL
254%D \NC \rlap{\quad\bf stacked} \NC \NC \type {\tx} \NC \type {\txx} \NC \NR
255%D \HL
256%D \NC \type{\tfx}
257%D \NC \tfx                                   \FontState
258%D \NC \tfx                              \tx  \FontState
259%D \NC \tfx                              \txx \FontState
260%D \NC \NR
261%D \NC \type{\tfxx}
262%D \NC \tfx\tfxx                              \FontState
263%D \NC \tfx\tfxx                         \tx  \FontState
264%D \NC \tfx\tfxx                         \txx \FontState
265%D \NC \NR
266%D \NC \type{\tf}
267%D \NC \tfx\tfxx\tf                           \FontState
268%D \NC \tfx\tfxx\tf                      \tx  \FontState
269%D \NC \tfx\tfxx\tf                      \txx \FontState
270%D \NC \NR
271%D \NC \type{\tfa}
272%D \NC \tfx\tfxx\tf\tfa                       \FontState
273%D \NC \tfx\tfxx\tf\tfa                  \tx  \FontState
274%D \NC \tfx\tfxx\tf\tfa                  \txx \FontState
275%D \NC \NR
276%D \NC \type{\tfb}
277%D \NC \tfx\tfxx\tf\tfa\tfb                   \FontState
278%D \NC \tfx\tfxx\tf\tfa\tfb              \tx  \FontState
279%D \NC \tfx\tfxx\tf\tfa\tfb              \txx \FontState
280%D \NC \NR
281%D \NC \type{\tfc}
282%D \NC \tfx\tfxx\tf\tfa\tfb\tfc               \FontState
283%D \NC \tfx\tfxx\tf\tfa\tfb\tfc          \tx  \FontState
284%D \NC \tfx\tfxx\tf\tfa\tfb\tfc          \txx \FontState
285%D \NC \NR
286%D \NC \type{\tfd}
287%D \NC \tfx\tfxx\tf\tfa\tfb\tfd               \FontState
288%D \NC \tfx\tfxx\tf\tfa\tfb\tfd          \tx  \FontState
289%D \NC \tfx\tfxx\tf\tfa\tfb\tfd          \txx \FontState
290%D \NC \NR
291%D \NC \type{\tfx}
292%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx           \FontState
293%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx      \tx  \FontState
294%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx      \txx \FontState
295%D \NC \NR
296%D \NC \type{\tfxx}
297%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx      \FontState
298%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx \tx  \FontState
299%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx \txx \FontState
300%D \NC \NR
301%D \HL
302%D \stoptabulate
303
304\fontslantperpoint   \nullfont      0\scaledpoint
305\fontinterwordspace  \nullfont 256377\scaledpoint
306\fontinterwordstretch\nullfont 128188\scaledpoint
307\fontinterwordshrink \nullfont  85459\scaledpoint
308\fontexheight        \nullfont 338952\scaledpoint
309\fontemwidth         \nullfont 786432\scaledpoint
310\fontextraspace      \nullfont  85459\scaledpoint
311
312\appendtoks
313    \fontslantperpoint   \nullfont      0\scaledpoint
314    \fontinterwordspace  \nullfont 256377\scaledpoint
315    \fontinterwordstretch\nullfont 128188\scaledpoint
316    \fontinterwordshrink \nullfont  85459\scaledpoint
317    \fontexheight        \nullfont 338952\scaledpoint
318    \fontemwidth         \nullfont 786432\scaledpoint
319    \fontextraspace      \nullfont  85459\scaledpoint
320\to \everyjob
321
322%D Tracing
323
324\newtoks\t_font_tracers_definitions
325
326\permanent\protected\def\tracefontdefinitions
327  {\the\t_font_tracers_definitions}
328
329%D Some housekeeping macros:
330
331\permanent\protected\def\setfontparameters
332  {\setfalse\c_font_synchronize
333   \the\everybodyfont
334   \settrue\c_font_synchronize}
335
336\mutable\let\savedfont\empty
337
338\installmacrostack\savedfont
339
340% \fontname\font               : string
341% \fontid  \font               : integer
342% \the     \font               : token (reference to font)
343%          \fontspecifiedname  : string
344% \the     \fontspecifiedsize  : dimension
345
346\permanent\protected\def\savefont
347  {\edef\savedfont{\the\font}%
348   \push_macro_savedfont}
349
350\permanent\protected\def\restorefont
351  {\pop_macro_savedfont
352   \savedfont}
353
354\aliased\let\popcurrentfont\relax
355
356\permanent\protected\def\pushcurrentfont
357  {\enforced\permanent\protected\edef\popcurrentfont
358     {\def\noexpand\fontbody       {\fontbody}%
359      \def\noexpand\fontstyle      {\fontstyle}%
360      \def\noexpand\fontalternative{\fontalternative}%
361      \def\noexpand\fontsize       {\fontsize}%
362      \font_helpers_check_big_math_synchronization
363      \font_helpers_synchronize_font}}
364
365%D \macros{definedfont}
366
367\mutable\let\thedefinedfont\relax % not to be confused with \everydefinefont
368
369\permanent\tolerant\protected\def\definedfont[#specification]%
370  {\ifarguments
371      \c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly
372   \or
373      \c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly
374      \font_basics_define_font_without_parameters{thedefinedfont}{#specification}%
375   \fi
376   \thedefinedfont
377   \the\everydefinedfont}
378
379%D \macros{startfont}
380
381\permanent\protected\def\startfont{\begingroup\definedfont}
382\permanent\protected\def\stopfont {\endgroup}
383
384%D \macros
385%D   {everybodyfont,everyglobalbodyfont}
386%D
387%D Every change in bodyfont size has conseqences for the baseline distance and skips
388%D between paragraphs. These are initialized in other modules. Here we only provide
389%D the hooks that garantees their handling.
390%D
391%D At the system level one can initialize thing like:
392%D
393%D \starttyping
394%D \appendtoks \setupspacing \to \everybodyfont
395%D \stoptyping
396
397%D \macros
398%D   {globalbodyfontsize,localbodyfontsize,bodyfontsize}
399%D
400%D Here we have to distinguish between the global (overal) bodyfont size and the
401%D local (sometimes in the textflow) size. We store these dimensions in two
402%D \DIMENSION\ registers. These registers are not to be misused in calculations.
403
404\ifdefined\globalbodyfontsize \else \newdimen\globalbodyfontsize \fi \globalbodyfontsize=12pt
405\ifdefined\localbodyfontsize  \else \newdimen\localbodyfontsize  \fi \localbodyfontsize =\globalbodyfontsize
406\ifdefined\bodyfontsize       \else \newdimen\bodyfontsize       \fi \bodyfontsize      =\globalbodyfontsize
407
408%D When we assign for instance 12pt to a \DIMENSION\ register the \type {\the}'d
409%D value comes out as 12.0pt, which is often not the way users specify the bodyfont
410%D size. Therefore we use normalized values. They are cached to save overhead in
411%D \LUA\ calls.
412
413\installcorenamespace{fontnormalizedbody}
414
415\permanent\protected\def\normalizebodyfontsize#macro#body%
416  {\expandafter\let\expandafter#macro\csname\??fontnormalizedbody\number\dimexpr#body\endcsname
417   \ifrelax#macro%
418      \normalizebodyfontsize_indeed#macro{#body}%
419   \fi}
420
421\def\normalizebodyfontsize_indeed#macro#body%
422  {\edef#macro{\clf_nbfs\dimexpr#body\relax}%
423   \gletcsname\??fontnormalizedbody\number\dimexpr#body\endcsname#macro}
424
425\permanent\def\thenormalizedbodyfontsize#body%
426  {\clf_nbfs\dimexpr#body\relax}
427
428\mutable\edef\normalizedglobalbodyfontsize{\thenormalizedbodyfontsize\bodyfontsize}
429\mutable\edef\normalizedlocalbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize}
430\mutable\edef\normalizedbodyfontsize      {\thenormalizedbodyfontsize\bodyfontsize}
431
432%D \macros
433%D   {mapfontsize}
434%D
435%D For special purposes, like in math, you may want to use slightly different sizes
436%D than the ones given. This happens for instance with the Math Times fonts. Mapped
437%D font sizes can be specified by using the \type {mo} key instead of \type {sa} in
438%D font definitions.
439%D
440%D \startbuffer
441%D \mapfontsize[10pt][11pt]
442%D \mapfontsize[11pt][12pt]
443%D \mapfontsize[12pt][13pt]
444%D
445%D \definefont[test][Serif]\test TEST \par
446%D \definefont[test][Serif sa 5]\test TEST \par
447%D \definefont[test][Serif mo 5]\test TEST \par
448%D \definefont[test][Serif sa d]\test TEST \par
449%D \definefont[test][Serif at 60pt]\test TEST \par
450%D \definefont[test][Serif scaled 6000]\test TEST \par
451%D \stopbuffer
452%D
453%D \typebuffer
454%D
455%D \startpacked
456%D \getbuffer
457%D \stoppacked
458
459\installcorenamespace{mappedfontsize}
460
461\permanent\tolerant\protected\def\mapfontsize[#from]#spacer[#to]%
462  {\ifarguments\or\or\defcsname\??mappedfontsize\the\dimexpr#from\relax\endcsname{#to}\fi}
463
464\def\font_basics_set_mapped_fontsize#from%
465  {\ifcsname\??mappedfontsize\the\dimexpr#from\relax\endcsname
466     \lastnamedcs\else#from%
467   \fi}
468
469\installcorenamespace{fontbodyknown}
470\installcorenamespace{fontclassyes}   % fontclass
471\installcorenamespace{fontclassnop}   % nofontclass
472
473\def\font_helpers_process_relative_size_list#command% could be a toks
474  {#command\v!big
475   #command\v!small}
476
477\let\v_font_size_relative  \plusone
478\def\v_font_size_absolute {\fontbody}
479
480\let\v_font_rscale_default\!!plusone
481\let\p_font_rscale        \v_font_rscale_default
482
483\def\font_helpers_check_relative_font_id % can be plugged in later
484  {\let\p_font_rscale\minusone
485   \let\p_font_rscale\v_font_rscale_default}
486
487\def\font_helpers_check_relative_font_size#style%
488  {\edef\p_font_rscale
489     {\ifcsname\??fontclass\fontclass#style\s!rscale\endcsname
490        \lastnamedcs
491      \orelse\ifcsname\??fontclass\defaultfontclass#style\s!rscale\endcsname % brr
492        \lastnamedcs
493      \else
494        \v_font_rscale_default
495      \fi}%
496   % move elsewhere
497   \ifx\p_font_rscale\v!auto
498     \let\p_font_rscale\plusone
499     \font_helpers_check_relative_font_id
500   \fi}
501
502\def\font_rscale_xx#style%
503  {\ifcsname\??fontclass\fontclass#style\s!rscale\endcsname
504     \lastnamedcs
505   \else
506     \v_font_rscale_default
507   \fi}
508
509\def\font_rscale_mm
510  {\ifcsname\??fontclass\fontclass\s!mm\s!rscale\endcsname
511     \lastnamedcs
512   \else
513     \v_font_rscale_default
514   \fi}
515
516\def\font_helpers_register_fontbody#body%
517  {\letcsname\??fontbodyknown#body\endcsname\empty}
518
519%D \macros
520%D   {definefontstyle,definefontsize,definefontalternative}
521%D
522%D When setting of switching the overall style we can use the short identifier like
523%D rm and ss, but when defined we can also use more verbose names like roman or
524%D sansserif. Such names are defined by:
525%D
526%D \starttyping
527%D \definefontstyle [serif,rm] [rm]
528%D \definefontstyle [sansserif,ss] [ss]
529%D \stoptyping
530
531\installcorenamespace{fontstyle}      % full style prefix (roman etc)
532\installcorenamespace{fontshortstyle} % short style prefix (rm etc)
533
534\installcorenamespace{fontstyleknown}
535\installcorenamespace{fontalternativeknown}
536\installcorenamespace{fontsizeknown}
537
538\newtoks\t_font_style_commands
539\newtoks\t_font_size_commands
540\newtoks\t_font_alternative_commands
541
542\setnewmacro\m_font_style_command      \gobbleoneargument
543\setnewmacro\m_font_size_command       \gobbleoneargument
544\setnewmacro\m_font_alternative_command\gobbleoneargument
545
546\def\font_helpers_process_style_list      #command{\def\m_font_style_command      {#command}\the\t_font_style_commands}
547\def\font_helpers_process_size_list       #command{\def\m_font_size_command       {#command}\the\t_font_size_commands}
548\def\font_helpers_process_alternative_list#command{\def\m_font_alternative_command{#command}\the\t_font_alternative_commands}
549
550\def\font_helpers_register_style            #style{\letcsname\??fontstyleknown            #style\endcsname\empty}
551\def\font_helpers_register_size              #size{\letcsname\??fontsizeknown              #size\endcsname\empty}
552\def\font_helpers_register_alternative#alternative{\letcsname\??fontalternativeknown#alternative\endcsname\empty}
553
554\permanent\protected\def\definefontstyle[#commands]#spacer[#style]% style: rm ss tt ...
555  {\ifcsname\??fontstyleknown#style\endcsname \else % can be delayed till used (cg, hw)
556     \font_helpers_register_style{#style}%
557     \toksapp\t_font_style_commands{\m_font_style_command{#style}}%
558   \fi
559   \processcommalist[#commands]{\font_basics_define_fontstyle_indeed{#style}}}
560
561\def\font_basics_define_fontstyle_indeed#style#command%
562  {\defcsname\??fontshortstyle#command\endcsname{#style}%
563   \defcsname\??fontstyle     #command\endcsname{\csname#style\endcsname}}
564
565\permanent\protected\def\definefontsize[#size]%
566  {\ifcsname\??fontsizeknown#size\endcsname \else
567     \font_helpers_register_size{#size}%
568     \toksapp\t_font_size_commands{\m_font_size_command{#size}}%
569   \fi
570   \font_helpers_check_fontname_combinations}
571
572\permanent\protected\def\definefontalternative[#alternative]%
573  {\ifcsname\??fontalternativeknown#alternative\endcsname \else
574     \font_helpers_register_alternative{#alternative}%
575     \toksapp\t_font_alternative_commands{\m_font_alternative_command{#alternative}}%
576   \fi
577   \font_helpers_check_fontname_combinations}
578
579\protected\def\font_helpers_check_fontname_combinations % we need to split math and text here ... todo (math only has mr and mb)
580  {\font_helpers_process_style_list\font_helpers_check_fontname_combinations_s}
581
582\def\font_helpers_check_fontname_combinations_s#style%
583  {\font_helpers_process_alternative_list{\font_helpers_check_fontname_combinations_indeed_s_a{#style}}}
584
585\def\font_helpers_check_fontname_combinations_indeed_s_a#style#alternative%
586  {\font_helpers_process_size_list{\font_basics_check_fontname_combination{#style}{#alternative}}}
587
588\definefontstyle [\s!mm] [\s!mm]
589\definefontstyle [\s!rm] [\s!rm]
590\definefontstyle [\s!ss] [\s!ss]
591\definefontstyle [\s!tt] [\s!tt]
592
593%D We define all the font switching commands globally. After all they are part of
594%D the formal font interface once defined. The size can be empty (so checking is
595%D needed as \type {\bf} is already defined).
596%D
597%D The \type {\normal..} variants are available as extras for cases where the \type
598%D {..} is overloaded.
599
600\newmacro\m_font_mm
601
602\def\font_basics_check_fontname_combination#style% alternative size
603  {\edef\m_font_mm{#style}%
604   \ifx\m_font_mm\s!mm % prevents \max and alike (re)defs
605     \expandafter\font_basics_check_math_bodyfont
606   \else
607     \expandafter\font_basics_check_text_bodyfont
608   \fi{#style}} % no \m_font_mm, not expanded later on
609
610\def\font_basics_check_math_bodyfont#style#alternative#size%
611  {}
612
613\def\font_basics_check_text_bodyfont_step#whatever#body% size can be empty (checking needed as \bf is already defined)
614  {\ifcsname#whatever\endcsname\else
615     \permanent\setugvalue{#whatever}{#body}%
616   \fi}
617
618\def\font_basics_check_text_bodyfont#style#alternative#size% size can be empty (checking needed as \bf is already defined)
619  {\font_basics_check_text_bodyfont_step{#style#size}{\font_helpers_set_current_font_style_size{#style}{#size}}% \rma
620   \font_basics_check_text_bodyfont_step{#alternative#size}{\font_helpers_set_current_font_alternative_size{#alternative}{#size}}% \sla
621   \font_basics_check_text_bodyfont_step{#style#alternative#size}{\font_helpers_set_current_font_style_alternative_size{#style}{#alternative}{#size}}% \rmsla
622   \font_basics_check_text_bodyfont_step{#style}{\font_helpers_set_current_font_style{#style}}% \rm
623   \font_basics_check_text_bodyfont_step{#alternative}{\font_helpers_set_current_font_alternative{#alternative}}% \sl
624   \font_basics_check_text_bodyfont_step{#style\s!x }{\font_helpers_set_current_font_x_style_alternative{#style}}% \rmx
625   \font_basics_check_text_bodyfont_step{#style\s!xx}{\font_helpers_set_current_font_xx_style_alternative{#style}}% \rmxx
626   \font_basics_check_text_bodyfont_step{#alternative\s!x }{\font_helpers_set_current_font_x_alternative{#alternative}}% \slx
627   \font_basics_check_text_bodyfont_step{#alternative\s!xx}{\font_helpers_set_current_font_xx_alternative{#alternative}}% \slxx
628   \font_basics_check_text_bodyfont_step{#style#alternative}{\font_helpers_set_current_font_style_alternative{#style}{#alternative}}}% \rmsl
629
630%D Scaling macros:
631%D
632%D This system is somewhat complicated by two (possible conflicting) demands:
633%D
634%D \startitemize
635%D \item We support wildcards like \type {sa *} which will adapt to the current
636%D       size. This is also the default specification.
637%D \item We support named scales like \type {sa d}; beware: \type {x} and \type {xx}
638%D       are valid scales but they are not alway the same as the ones used in for
639%D       instance \type {\bfx} because there the sized come from the bodyfont
640%D       environment. In the future there maybe a switch that also honors the
641%D       environment in named scales.
642%D \stopitemize
643%D
644%D Keep in mind that the smaller sizes are just for text super and subscripts while
645%D larger sizes can be used in titles where for instance math follows the size.
646
647% b:x{\definedfont[SerifBold sa  b]x}{\bfb  x $x^x$}\par
648% 1:x{\definedfont[SerifBold sa  1]x}{\bf   x $x^x$}\par
649% x:x{\definedfont[SerifBold sa  x]x}{\bfx  x $x^x$}\par
650% xx:x{\definedfont[SerifBold sa xx]x}{\bfxx x $x^x$}\par
651%
652% *:x{\definedfont[Serif sa *]x}\par
653% 1:x{\definedfont[Serif sa 1]x}\par
654% 2:x{\definedfont[Serif sa 2]x}\par
655% 3:x{\definedfont[Serif sa 3]x}\par
656% 4:x{\definedfont[Serif sa 4]x}\par
657% 5:x{\definedfont[Serif sa 5]x}\par
658
659\permanent\def\safontscale{\number\dimexpr\v_font_size_absolute\relax}
660\permanent\def\mofontscale{\number\dimexpr\font_basics_set_mapped_fontsize\v_font_size_absolute\relax}
661
662\mutable\let\somefontname \s!unknown
663\mutable\let\somefontspec \s!unknown
664\mutable\let\somefontfile \s!unknown
665\mutable\let\somefontsize \zerocount
666\mutable\let\somefontsizex\empty
667\mutable\let\somefontsizey\empty
668
669\newcount\scaledfontmode  % also used at the lua end
670\newcount\scaledfontsize  % also used at the lua end
671\newcount\lastfontid      % also used at the lua end / tex end
672\newtoks \everydefinefont
673
674\aliased\let\c_font_feature_inheritance_fontnone  \zerocount  % none
675\aliased\let\c_font_feature_inheritance_fontonly  \plusone    % fontonly
676\aliased\let\c_font_feature_inheritance_classonly \plustwo    % classonly
677\aliased\let\c_font_feature_inheritance_fontfirst \plusthree  % fontfirst
678\aliased\let\c_font_feature_inheritance_classfirst\plusfour   % classfirst
679
680\aliased\let\c_font_feature_inheritance_default   \c_font_feature_inheritance_fontfirst
681
682\setnewconstant\c_font_feature_inheritance_mode \c_font_feature_inheritance_default
683
684\newdimen      \d_font_scaled_text_face
685\newdimen      \d_font_scaled_font_size
686\newconditional\c_font_body_scale
687\newfraction   \f_font_body_scale
688
689\newconditional\c_font_compact
690\newcount      \c_font_scaled_glyph_scale
691
692\immutable\dimensiondef\d_font_scaled_default 10pt
693
694\newcount\c_font_future_glyph_scale
695
696% todo: move all to lua: use localcall for resolving filename
697
698\newcount\c_font_future_glyph_scale
699\newcount\c_font_scaled_font_mode_saved
700\newcount\c_font_scaled_points
701
702\mutable\let\somefontspec         \empty
703\mutable\let\lastrawfontcall      \relax
704\mutable\let\lastglobalrawfontcall\relax
705
706\protected\def\font_helpers_low_level_define
707  {\ifconditional\c_font_compact
708     \expandafter\font_helpers_low_level_define_compact
709   \else
710     \expandafter\font_helpers_low_level_define_normal
711   \fi}
712
713\protected\def\font_helpers_low_level_define_normal#specification#csname%
714  {% we can now set more at the lua end
715   \glet\somefontname\defaultfontfile
716   \let\somefontsize\empty
717   \let\somefontsizex\empty
718   \let\somefontsizey\empty
719   \clf_definefont_one{\detokenize\expandafter{\normalexpanded{#specification}}}% the escapestring catches at \somedimen
720   % sets \scaledfontmode and \somefontname and \somefontsize
721   \ifcase\fontface\relax
722   % \let\v_font_size_absolute\textface % fontbody
723   \or
724     \let\v_font_size_absolute\textface
725   \or
726     \let\v_font_size_absolute\scriptface
727   \or
728     \let\v_font_size_absolute\scriptscriptface
729   \or
730     \let\v_font_size_absolute\xtextface
731   \or
732     \let\v_font_size_absolute\xxtextface
733   \fi
734   %
735   \ifcase\scaledfontmode\relax
736     % none, avoid the designsize if possible
737     \d_font_scaled_font_size-\plusthousand\scaledpoint
738   \or
739     % at
740     \d_font_scaled_font_size\somefontsize
741   \or
742     % sa
743     \d_font_scaled_font_size\v_font_size_absolute\relax
744     \d_font_scaled_font_size\currentfontbodysize\d_font_scaled_font_size % uses \somefontsize set by lua
745   \or
746     % mo
747     \d_font_scaled_font_size\font_basics_set_mapped_fontsize\v_font_size_absolute
748     \d_font_scaled_font_size\currentfontbodysize\d_font_scaled_font_size
749   \or
750     % scaled, don't use this one as it's unpredictable
751     \d_font_scaled_font_size-\somefontsize\scaledpoint
752   \else % ht cp
753     % experiment, yet undocumented
754     \d_font_scaled_font_size\somefontsize
755   \fi
756   \relax
757   \d_font_scaled_font_size\v_font_size_relative\d_font_scaled_font_size
758   \relax
759   %
760   \ifconditional\c_font_auto_size
761     \font_helpers_check_body_scale\fontsize
762     \ifconditional\c_font_body_scale
763       \d_font_scaled_font_size\f_font_body_scale\d_font_scaled_font_size
764       \d_font_scaled_text_face\f_font_body_scale\dimexpr\textface\relax
765     \else
766       \d_font_scaled_font_size\f_font_body_scale
767       \d_font_scaled_text_face\textface
768     \fi
769   \else
770     \d_font_scaled_text_face\textface
771   \fi
772   %
773   \edef\somefontspec{at \number\d_font_scaled_font_size sp}%
774   \edef\somefontfile{\truefontname\somefontname}%
775   \ifx\somefontfile\s!unknown
776     \edef\somefontfile{\defaultfontfile}%
777   \fi
778   \font_helpers_update_font_parameters
779   \font_helpers_update_font_class_parameters
780  %\writestatus{fonts}{low level define: #csname/\somefontfile/\number\d_font_scaled_font_size/\fontface/\number\d_font_scaled_text_face}%
781%    \clf_definefont_two
782%       \ifempty\fontclass\s!false\else\s!true\fi
783%       {#csname}%
784%       {\somefontfile}%
785%       \d_font_scaled_font_size
786%       \c_font_feature_inheritance_mode
787%       {\m_font_class_features}%
788%       {\m_font_features}%
789%       {\m_font_class_fallbacks}%
790%       {\m_font_fallbacks}%
791%       \fontface
792%       \d_font_scaled_text_face
793%       {\m_font_class_goodies}%
794%       {\m_font_goodies}%
795%       {\m_font_class_designsize}%
796%       {\m_font_designsize}%
797%       \scaledfontmode
798   \clf_definefont_two
799      \ifempty\fontclass\s!false\else\s!true\fi
800      {#csname}%
801      \somefontfile
802      \d_font_scaled_font_size
803      \c_font_feature_inheritance_mode
804      \m_font_class_features
805      \m_font_features
806      \m_font_class_fallbacks
807      \m_font_fallbacks
808      \fontface
809      \d_font_scaled_text_face
810      \m_font_class_goodies
811      \m_font_goodies
812      \m_font_class_designsize
813      \m_font_designsize
814      \scaledfontmode
815   \relax
816   \ifcase\scaledfontsize
817    %\scaledfontsize\plusone
818     \let\somefontspec\empty
819     \let\lastrawfontcall\relax
820     \mutable\letcsname#csname\endcsname\relax
821   \else
822     \edef\somefontspec{at \number\scaledfontsize sp}% we need the resolved designsize (for fallbacks)
823     \expandafter\let\expandafter\lastrawfontcall\csname#csname\endcsname
824     \the\everydefinefont
825   \fi
826   \c_font_feature_inheritance_mode\c_font_feature_inheritance_default}
827
828\protected\def\font_helpers_low_level_define_compact#specification#csname%
829  {% we can now set more at the lua end
830   \glet\somefontname\defaultfontfile
831   \let\somefontsize\empty
832   \let\somefontsizex\empty
833   \let\somefontsizey\empty
834   \clf_definefont_one{\detokenize\expandafter{\normalexpanded{#specification}}}% the escapestring catches at \somedimen
835   % sets \scaledfontmode and \somefontname and \somefontsize
836   \ifcase\fontface\relax
837   % \let\v_font_size_absolute\textface % fontbody
838   \or
839     \let\v_font_size_absolute\textface
840   \or
841     \let\v_font_size_absolute\scriptface
842   \or
843     \let\v_font_size_absolute\scriptscriptface
844   \or
845     \let\v_font_size_absolute\xtextface
846   \or
847     \let\v_font_size_absolute\xxtextface
848   \fi
849   %
850   \ifcase\scaledfontmode\relax
851     % none, avoid the designsize if possible
852     \d_font_scaled_font_size-\plusthousand\scaledpoint
853   \or
854     % at
855     \d_font_scaled_font_size\somefontsize
856   \or
857     % sa
858     \d_font_scaled_font_size\v_font_size_absolute\relax
859     \d_font_scaled_font_size\currentfontbodysize\d_font_scaled_font_size % uses \somefontsize set by lua
860   \or
861     % mo
862     \d_font_scaled_font_size\font_basics_set_mapped_fontsize\v_font_size_absolute
863     \d_font_scaled_font_size\currentfontbodysize\d_font_scaled_font_size
864   \or
865     % scaled, don't use this one as it's unpredictable
866     \d_font_scaled_font_size-\somefontsize\scaledpoint
867   \else % ht cp
868     % experiment, yet undocumented
869     \d_font_scaled_font_size\somefontsize
870   \fi
871   \relax
872   \d_font_scaled_font_size\v_font_size_relative\d_font_scaled_font_size
873   \relax
874   %
875   \ifconditional\c_font_auto_size
876     \font_helpers_check_body_scale\fontsize
877     \ifconditional\c_font_body_scale
878       \d_font_scaled_font_size\f_font_body_scale\d_font_scaled_font_size
879       \d_font_scaled_text_face\f_font_body_scale\dimexpr\textface\relax
880     \else
881       \d_font_scaled_font_size\f_font_body_scale
882       \d_font_scaled_text_face\textface
883     \fi
884   \else
885     \d_font_scaled_text_face\textface
886   \fi
887   %
888   \ifnum\c_font_scaled_font_mode_saved>\plusfour
889     \c_font_scaled_font_mode_saved\scaledfontmode
890     \scaledfontmode\zerocount
891   \fi
892   \c_font_future_glyph_scale\numexpr\plushundred*\d_font_scaled_font_size/\maxcard\relax
893   \glyphscale\numexpr\plushundred*\d_font_scaled_font_size/\maxcard\relax % needed ? for math i guess
894 % \d_font_scaled_font_size\d_font_scaled_default
895 % \d_font_scaled_text_face\d_font_scaled_default
896   %
897   \edef\somefontspec{at \number\d_font_scaled_font_size sp}%
898   % this has to happen at the tex end ...
899   \edef\somefontfile{\truefontname\somefontname}%
900   \ifx\somefontfile\s!unknown
901     \edef\somefontfile{\defaultfontfile}%
902   \fi
903   \font_helpers_update_font_parameters
904   \font_helpers_update_font_class_parameters
905   % ... till here
906  %\writestatus{fonts}{low level define: #csname/\somefontfile/\number\d_font_scaled_font_size/\fontface/\number\d_font_scaled_text_face}%
907   \clf_definefont_two
908      \ifempty\fontclass\s!false\else\s!true\fi
909      {#csname}%
910      \somefontfile
911      \d_font_scaled_font_size
912      \c_font_feature_inheritance_mode
913      \m_font_class_features
914      \m_font_features
915      \m_font_class_fallbacks
916      \m_font_fallbacks
917      \fontface
918      \d_font_scaled_default
919      \m_font_class_goodies
920      \m_font_goodies
921      \m_font_class_designsize
922      \m_font_designsize
923      \scaledfontmode
924   \relax
925   \ifcase\scaledfontsize
926    %\scaledfontsize\plusone
927     \let\somefontspec\empty
928     \let\lastrawfontcall\relax
929     \mutable\letcsname#csname\endcsname\relax
930   \else
931     \edef\somefontspec{at \number\scaledfontsize sp}% we need the resolved designsize (for fallbacks)
932     %
933     \glyphscale
934       \ifnum\c_font_scaled_font_mode_saved>\plusfour
935         \numexpr\plusthousand*\dimexpr\d_font_scaled_default\relax/\c_font_scaled_points\relax
936       \else
937         \c_font_future_glyph_scale
938       \fi
939     \ifempty\somefontsizex\else
940        \edef\somefontsizex{\glyphxscale\somefontsizex\relax}% todo: inserts relax
941     \fi
942     \ifempty\somefontsizey\else
943        \edef\somefontsizey{\glyphyscale\somefontsizey\relax}%
944     \fi
945     \ifempty\fontclass\else\global\fi
946     \mutable\protected\edefcsname#csname\endcsname
947       {\setfontid\the\fontid\csname#csname\endcsname\relax
948        \glyphscale\the\glyphscale\relax
949        \somefontsizex
950        \somefontsizey}%
951     %
952     \expandafter\let\expandafter\lastrawfontcall\csname#csname\endcsname
953     \the\everydefinefont
954   \fi
955   \c_font_feature_inheritance_mode\c_font_feature_inheritance_default}
956
957\def\font_helpers_check_body_scale#fontsize%  gets character (x xx a etc)
958  {\ifcsname\??fontenvironments\fontclass\fontbody#fontsize\endcsname
959     \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
960     \setfalse\c_font_body_scale % !
961   \orelse\ifcsname\??fontenvironments\fontclass\s!default#fontsize\endcsname
962     \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
963     \settrue\c_font_body_scale
964   \orelse\ifcsname\??fontenvironments\fontbody#fontsize\endcsname
965     \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
966     \setfalse\c_font_body_scale % !
967   \orelse\ifcsname\??fontenvironments\s!default#fontsize\endcsname
968     \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
969     \settrue\c_font_body_scale
970   \orelse\ifcsname\??fontenvironments\fontclass\s!default\s!text\endcsname
971     \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
972     \settrue\c_font_body_scale
973   \orelse\ifcsname\??fontenvironments\s!default\s!text\endcsname
974     \expandafter\let\expandafter\f_font_body_scale\lastnamedcs
975     \settrue\c_font_body_scale
976   \else
977     \let\f_font_body_scale\plusone
978     \settrue\c_font_body_scale
979   \fi}
980
981\newif\ifskipfontcharacteristics \skipfontcharacteristicstrue
982
983\tracingfonts\plussix % <id: name @ size>
984
985%D When fontclasses are used, we define the font global, since namespaces are
986%D used. Otherwise we parse the specs each time.
987
988\mutable\let\fontfile\s!unknown
989
990%D Relatively new:
991
992\installcorenamespace{fonts}
993\installcorenamespace{fontslanguage}
994
995\installsetuponlycommandhandler \??fonts {fonts}
996
997\newconstant\c_fonts_auto_language
998
999\letcsname\??fontslanguage\v!auto\endcsname\plusone % experimental
1000%letcsname\??fontslanguage\v!yes \endcsname\plustwo % less efficient, for experiments
1001
1002\appendtoks
1003    \c_fonts_auto_language
1004      \ifcsname\??fontslanguage\fontsparameter\c!language\endcsname
1005        \lastnamedcs
1006      \else
1007        \zerocount
1008      \fi
1009\to \everysetupfonts
1010
1011\appendtoks
1012    \ifcase\c_fonts_auto_language
1013        % nothing
1014    \or
1015        \addfflanguage
1016  % \or
1017        % font
1018    \fi
1019\to \everylanguage
1020
1021% \setupfonts
1022%   [\c!language=\v!auto]
1023
1024%D \macros
1025%D  {everyfont,everyfontswitch}
1026
1027\ifdefined\everyfont       \else \newtoks\everyfont       \fi
1028\ifdefined\everyfontswitch \else \newtoks\everyfontswitch \fi
1029
1030\permanent\def\setfontcharacteristics{\the\everyfont}
1031
1032% \appendtoks
1033%     \ifcase\c_fonts_auto_language
1034%         % nothing
1035%     \or
1036%         % auto
1037%     \or
1038%         \addfflanguage
1039%     \fi
1040% \to \everyfont
1041
1042%D \macros
1043%D   {definefont}
1044%D
1045%D We also accept \type{sa a}||\type{sa d} as specification.
1046%D
1047%D Before we implement the main definition macro, we first show one for local use:
1048%D
1049%D \starttyping
1050%D \definefont[Some][LucidaBright at 100pt]    \Some some
1051%D \definefont[More][LucidaBright scaled 3000] \More more
1052%D \definefont[Nice][LucidaBright mo 2]        \Nice nice
1053%D \definefont[Text][LucidaBright sa 5.4]      \Text last
1054%D \stoptyping
1055%D
1056%D The implementation looks as follows:
1057
1058\permanent\tolerant\protected\def\definefont[#1]#*[#2]#*[#3]%  [name][spec][1.6 | line=10pt | setup_id]
1059  {\ifparameter#3\or
1060     \expandafter\font_basics_define_font_a
1061   \else
1062     \expandafter\font_basics_define_font_b
1063   \fi[#1][#2][#3]}
1064
1065\def\font_basics_define_font_a[#name][#specification][#settings]% [name][spec][1.6 | line=10pt | setup_id]
1066  {\doifelsesetups{#settings}%
1067     {\mutable\protected\defcsname#name\endcsname{\font_basics_define_font_with_setups    {#name}{#specification}{#settings}}}
1068     {\mutable\protected\defcsname#name\endcsname{\font_basics_define_font_with_parameters{#name}{#specification}{#settings}}}}
1069
1070\def\font_basics_define_font_b[#name][#specification][#dummy]%
1071  {\mutable\protected\defcsname#name\endcsname{\font_basics_define_font_without_parameters{#name}{#specification}}}
1072
1073\def\font_basics_define_font_with_parameters#name#specification#settings%
1074  {\font_basics_define_font_without_parameters{#name}{#specification}%
1075   \setuplocalinterlinespace[#settings]%
1076   \setupspacing\relax} % is this really needed ?
1077
1078\def\font_basics_define_font_with_setups#name#specification#settings%
1079  {\font_basics_define_font_without_parameters{#name}{#specification}%
1080   \setups[#settings]}
1081
1082%D Beware, in the frozen variants no settings are supported yet, but that might happen
1083%D some day.
1084
1085\permanent\tolerant\protected\def\definefrozenfont[#name]#spacer[#specification]#spacer[#settings]%
1086  {\ifparameter#name\or
1087     \begingroup
1088       \definefont[#name][#specification][#settings]%
1089       \csname#name\endcsname
1090       \glet\lastglobalrawfontcall\lastrawfontcall
1091     \endgroup
1092     \aliased\letcsname#name\endcsname\lastglobalrawfontcall
1093   \fi}
1094
1095%D The instance namespace protection makes the switch local so that we can redefine a
1096%D logical name and/or change the size in between.
1097
1098% todo: now mathsize twice in name (so it can go here)
1099% todo: check when mathsize is needed
1100
1101\ifdefined\??fontinstanceready \else \installcorenamespace{fontinstanceready} \fi
1102\ifdefined\??fontinstancebasic \else \installcorenamespace{fontinstancebasic} \fi
1103\ifdefined\??fontinstanceclass \else \installcorenamespace{fontinstanceclass} \fi
1104
1105\newconditional\c_font_auto_size \settrue\c_font_auto_size
1106
1107\mutable\let\lastfontidentifier\empty
1108
1109\def\v_font_identifier_basic{\??fontinstancebasic           \lastfontidentifier-\fontsize-\fontface}
1110\def\v_font_identifier_class{\??fontinstanceclass\fontclass-\lastfontidentifier-\fontsize-\fontface}
1111
1112\let\v_font_identifier_basic_saved\v_font_identifier_basic
1113\let\v_font_identifier_class_saved\v_font_identifier_class
1114
1115% \def\v_font_identifier_class{\??fontinstanceclass\fontclass-\lastfontidentifier-\fontstyle-\fontsize} % no \fontface
1116
1117\def\font_basics_define_font_without_parameters#identifier#2%
1118  {\c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly
1119   \edef\lastfontidentifier{#identifier}%
1120   \let\v_font_size_relative\v_font_rscale_default
1121   \let\v_font_size_absolute\fontbody
1122   \font_helpers_low_level_define{#2}\v_font_identifier_basic
1123   \csname\v_font_identifier_basic\endcsname
1124   \setfalse\c_font_auto_size
1125   \the\everyfont % \setfontcharacteristics
1126   \the\everyfontswitch
1127   \let\v_font_identifier_basic\v_font_identifier_basic_saved}
1128
1129\protected\def\font_helpers_trigger#identifier% make a traced variant
1130  {\edef\lastfontidentifier{#identifier}%
1131   \ifcsname\v_font_identifier_class\endcsname
1132     % \writestatus{fonts}{trigger: reusing \v_font_identifier_class}%
1133     \expandafter\font_helpers_trigger_reuse
1134   \else
1135     % \writestatus{fonts}{trigger: defining \v_font_identifier_class}%
1136     \expandafter\font_helpers_trigger_define
1137   \fi}
1138
1139\def\font_helpers_trigger_define#relative#absolute#specification%
1140  {\def\v_font_size_relative{#relative}%
1141   \def\v_font_size_absolute{#absolute}%
1142   \font_helpers_low_level_define{#specification}\v_font_identifier_class
1143   \csname\v_font_identifier_class\endcsname
1144   \setfalse\c_font_auto_size
1145   \ifskipfontcharacteristics \else
1146     \the\everyfont % \setfontcharacteristics
1147     \the\everyfontswitch
1148   \fi
1149   \let\v_font_identifier_class\v_font_identifier_class_saved}
1150
1151\def\font_helpers_trigger_reuse#relative#absolute#specification%
1152  {\csname\v_font_identifier_class\endcsname
1153   \setfalse\c_font_auto_size
1154   \ifskipfontcharacteristics \else
1155     \the\everyfont % \setfontcharacteristics
1156     \the\everyfontswitch
1157   \fi
1158   \let\v_font_identifier_class\v_font_identifier_class_saved}
1159
1160%D \macros
1161%D   {currentfontbodyscale}
1162%D
1163%D Sometimes we need to have access to the font scale including the \type {a}||\type
1164%D {d} sizes. The next macro returns the current scaling factor. Take a look at
1165%D \type {cont-log.tex} for an example of its use.
1166
1167\installcorenamespace{fontenvironments}
1168
1169\permanent\def\currentfontbodysize % gets number (the normal sa 1 etc)
1170  {\ifcsname\??fontenvironments\fontclass\s!default\somefontsize\endcsname
1171     \lastnamedcs
1172   \orelse\ifcsname\??fontenvironments\s!default\somefontsize\endcsname
1173     \lastnamedcs
1174   \else
1175     \somefontsize
1176   \fi}
1177
1178\permanent\def\currentfontbodyscale % gets character (x xx a etc)
1179  {\csname\??fontenvironments
1180     \ifcsname\??fontenvironments\fontclass\s!default\fontsize\endcsname\fontclass\s!default\fontsize\orelse
1181     \ifcsname\??fontenvironments          \s!default\fontsize\endcsname          \s!default\fontsize\orelse
1182     \ifcsname\??fontenvironments\fontclass\s!default\s!text  \endcsname\fontclass\s!default\s!text  \orelse
1183     \ifcsname\??fontenvironments          \s!default\s!text  \endcsname          \s!default\s!text  \else
1184                                                                                  \s!default         \fi
1185   \endcsname}
1186
1187\def\font_currentfontbodyscale % gets character (x xx a etc)
1188  {\ifcsname\??fontenvironments\fontclass\s!default\fontsize\endcsname\lastnamedcs\orelse
1189   \ifcsname\??fontenvironments          \s!default\fontsize\endcsname\lastnamedcs\orelse
1190   \ifcsname\??fontenvironments\fontclass\s!default\s!text  \endcsname\lastnamedcs\orelse
1191   \ifcsname\??fontenvironments          \s!default\s!text  \endcsname\lastnamedcs\else
1192     \csname\??fontenvironments          \s!default         \endcsname            \fi}
1193
1194\permanent\def\currentfontscale % used in default definition
1195  {\csname\??fontenvironments
1196     \ifcsname\??fontenvironments\fontclass\s!default\xfontsize\endcsname\fontclass\s!default\fontsize\orelse
1197     \ifcsname\??fontenvironments          \s!default\xfontsize\endcsname          \s!default\fontsize\orelse
1198     \ifcsname\??fontenvironments\fontclass\s!default\s!text   \endcsname\fontclass\s!default\s!text  \orelse
1199     \ifcsname\??fontenvironments          \s!default\s!text   \endcsname          \s!default\s!text  \else
1200                                                                                   \s!default         \fi
1201   \endcsname}
1202
1203\def\font_currentfontscale % used in default definition
1204  {\ifcsname\??fontenvironments\fontclass\s!default\xfontsize\endcsname\lastnamedcs\orelse
1205   \ifcsname\??fontenvironments          \s!default\xfontsize\endcsname\lastnamedcs\orelse
1206   \ifcsname\??fontenvironments\fontclass\s!default\s!text   \endcsname\lastnamedcs\orelse
1207   \ifcsname\??fontenvironments          \s!default\s!text   \endcsname\lastnamedcs\else
1208     \csname\??fontenvironments          \s!default          \endcsname            \fi}
1209
1210\setvalue{\??fontenvironments\s!default}{1}
1211
1212%D In the following macros we use \type {\currentxfontsize} to hold the current
1213%D x||size of the font. This enables us to support for instance \type {\sl} inside a
1214%D \type {\tx} switch.
1215
1216\newconstant\currentxfontsize
1217
1218\permanent\def\xfontsize{\ifcase\currentxfontsize\fontsize\or\s!x\else\s!xx\fi}
1219
1220%D Now we enter the area of font switching. The switching mechanism has to take care
1221%D of several situations, like:
1222%D
1223%D \startitemize[packed]
1224%D \item changing the overal document fonts (including margins, headers and footers)
1225%D \item changing local fonts (only the running text)
1226%D \item smaller and even more smaller alternatives (super- and subscripts)
1227%D \stopitemize
1228%D
1229%D \TEX\ offers a powerful family mechanism for super- and subscripts in math mode.
1230%D In text mode however, we don't use families for the smaller alternatives, and
1231%D therefore have to take care of it otherwise.
1232%D
1233%D \macros
1234%D   {definebodyfontenvironment,setupbodyfontenvironment}
1235%D
1236%D The relationship between the several sizes of a font, is
1237%D defined by:
1238%D
1239%D \showsetup{definebodyfontenvironment}
1240%D
1241%D Later on we will see how these parameters are used, so for the moment we stick
1242%D with an example:
1243%D
1244%D \starttyping
1245%D \definebodyfontenvironment
1246%D   [12pt]
1247%D   [        text=12pt,
1248%D          script=9pt,
1249%D    scriptscript=7pt,
1250%D               x=10pt,
1251%D              xx=8pt,
1252%D             big=12pt,
1253%D           small=10pt]
1254%D \stoptyping
1255%D
1256%D The first argument specifies the bodyfont size to which the settings apply. All
1257%D second parameters are specified in dimensions and tell us more about related
1258%D sizes.
1259%D
1260%D Afterwards, one can change values with
1261%D
1262%D \showsetup{setupbodyfontenvironment}
1263%D
1264%D When instead of a size the keyword \type{unknown} is
1265%D passed, fractions (relations) are used instead of fixed
1266%D sizes.
1267
1268%D {\bf Remark:} We need to cover the following cases, otherwise users can get
1269%D confused:
1270%D
1271%D \starttyping
1272%D \setupbodyfont[23pt]
1273%D
1274%D \definebodyfontenvironment[23pt]
1275%D \setupbodyfont[23pt]
1276%D
1277%D \definebodyfontenvironment[23pt]
1278%D \definebodyfont[23pt][rm,ss,tt][default]
1279%D \setupbodyfont[23pt]
1280%D \stoptyping
1281%D
1282%D Beware: while some font defs can be global, the bodyfont environment checks
1283%D local. This means that multiple local checks resulting in definitions are not
1284%D that efficient. So, apart from an occasional switch, one should define an
1285%D environment at the outer level.
1286
1287% \definebodyfontenvironment[33pt]
1288% \definebodyfontenvironment[dejavu][default][1=.5]
1289% \definebodyfontenvironment[dejavu][default][x=1.2]
1290% \definebodyfontenvironment[dejavu][default][a=5]
1291% \definebodyfontenvironment[dejavu][33pt][x=100pt]
1292
1293% the lookup order is:
1294%
1295% [class] [dimension] [parameters]
1296% [class] [default]   [parameters] % factors
1297%         [dimension] [parameters]
1298%         [default]   [parameters] % factors
1299%
1300% with defaults providing factors
1301
1302% todo: class:size
1303% todo: make assignments global
1304
1305\letvalue\??fontenvironments\empty % so we default to empty
1306
1307\permanent\def\bodyfontvariable#parameter%
1308  {\csname\??fontenvironments
1309     \ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname\fontclass\normalizedbodyfontsize#parameter\orelse
1310     \ifcsname\??fontenvironments\fontclass                       #parameter\endcsname\fontclass                       #parameter\orelse
1311     \ifcsname\??fontenvironments          \normalizedbodyfontsize#parameter\endcsname          \normalizedbodyfontsize#parameter\orelse
1312     \ifcsname\??fontenvironments\s!default                       #parameter\endcsname\s!default                       #parameter\fi
1313   \endcsname}
1314
1315\def\font_bodyfontvariable#parameter%
1316  {\ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname\lastnamedcs\orelse
1317   \ifcsname\??fontenvironments\fontclass                       #parameter\endcsname\lastnamedcs\orelse
1318   \ifcsname\??fontenvironments          \normalizedbodyfontsize#parameter\endcsname\lastnamedcs\orelse
1319   \ifcsname\??fontenvironments\s!default                       #parameter\endcsname\lastnamedcs\fi}
1320
1321\permanent\def\bodyfontsizevariable#size#parameter%
1322  {\csname\??fontenvironments
1323     \ifcsname\??fontenvironments\fontclass#size#parameter\endcsname\fontclass#size#parameter\orelse
1324     \ifcsname\??fontenvironments\fontclass     #parameter\endcsname\fontclass     #parameter\orelse
1325     \ifcsname\??fontenvironments          #size#parameter\endcsname          #size#parameter\orelse
1326     \ifcsname\??fontenvironments\s!default     #parameter\endcsname\s!default     #parameter\fi
1327   \endcsname}
1328
1329\def\font_bodyfontsizevariable#size#parameter%
1330  {\ifcsname\??fontenvironments\fontclass#size#parameter\endcsname\lastnamedcs\orelse
1331   \ifcsname\??fontenvironments\fontclass     #parameter\endcsname\lastnamedcs\orelse
1332   \ifcsname\??fontenvironments          #size#parameter\endcsname\lastnamedcs\orelse
1333   \ifcsname\??fontenvironments\s!default     #parameter\endcsname\lastnamedcs\fi}
1334
1335\permanent\def\bodyfontinterlinespace{\bodyfontvariable\c!interlinespace} % used elsewhere
1336
1337\permanent\def\bodyfontdimension#class#size#parameter#body%
1338  {\the\dimexpr
1339     \ifcsname\??fontenvironments     #class#size#parameter\endcsname \lastnamedcs                   \orelse
1340     \ifcsname\??fontenvironments#class\s!default#parameter\endcsname \lastnamedcs\dimexpr#body\relax\orelse % factor
1341     \ifcsname\??fontenvironments           #size#parameter\endcsname \lastnamedcs                   \else
1342                                                                      \lastnamedcs\dimexpr#body\relax\fi     % factor
1343   \relax}
1344
1345\installcorenamespace{fontenvironmentknown}
1346
1347\def\font_helpers_register_environment#class#body%
1348  {\letcsname\??fontenvironmentknown#class#body\endcsname\empty}
1349
1350\newmacro\m_font_body
1351\newmacro\m_font_body_normalized
1352
1353\permanent\tolerant\protected\def\definebodyfontenvironment[#1]#*[#2]#*[#3]% todo
1354  {\ifarguments
1355     \expandafter\font_basics_define_body_font_environment_unset
1356   \or
1357     \expandafter\font_basics_define_body_font_environment_unset
1358   \or
1359     \expandafter\font_basics_define_body_font_environment_empty
1360   \or
1361     \expandafter\font_basics_define_body_font_environment_class
1362   \fi[#1][#2][#3]}
1363
1364\aliased\let\setupbodyfontenvironment\definebodyfontenvironment
1365
1366%D First we handle the class specific case. Beware: you can change values before
1367%D a bodyfont is loaded but changing them afterwards can be sort of tricky as
1368%D values are not consulted afterwards.
1369
1370\permanent\def\processbodyfontenvironmentlist#1% no \protected as then we cannot use it in alignments (still?)
1371  {\clf_processbodyfontsizes{\strippedcsname#1}}
1372
1373\permanent\def\bodyfontenvironmentlist
1374  {\clf_getbodyfontsizes}
1375
1376\def\font_basics_define_body_font_environment_class[#class][#body][#settings]%
1377  {\edef\m_font_body{#body}%
1378   \ifx\m_font_body\s!default
1379     % these are the last resort within a class
1380     \getrawparameters[\??fontenvironments#class\s!default][#settings]%
1381   \else
1382     \normalizebodyfontsize\m_font_body_normalized\m_font_body
1383     \font_basics_define_body_font_environment_size[#class][\m_font_body_normalized][#settings]%
1384     \clf_registerbodyfontsize{\m_font_body_normalized}%
1385   \fi}
1386
1387%D The empty case uses the same code but needs to ignore the current class settings
1388%D (just to be sure, as it's not really needed).
1389
1390\def\font_basics_define_body_font_environment_empty[#body][#settings][#dummy]%
1391  {\push_macro_fontclass
1392   \let\fontclass\empty
1393   \font_basics_define_body_font_environment_class[][#body][#settings]%
1394   \pop_macro_fontclass}
1395
1396\def\font_basics_define_body_font_environment_unset[#body][#dummya][#dummyb]%
1397  {\push_macro_fontclass
1398   \let\fontclass\empty
1399   \font_basics_define_body_font_environment_class[][#body][]%
1400   \pop_macro_fontclass}
1401
1402%D We don't check too soon as we can refer to later definitions.
1403
1404\newconditional\c_font_defining_environment_state % controls messages
1405
1406\def\font_basics_define_body_font_environment_size[#class][#normalizedbody][#settings]% normalized body
1407  {\getrawparameters[\??fontenvironments#class#normalizedbody][#settings]%
1408   \ifcsname\??fontenvironmentknown#class#normalizedbody\endcsname
1409     % environment and size already defined
1410   \orelse\ifproductionrun
1411     \push_macro_fontclass
1412     \edef\fontclass{#class}%
1413     \font_helpers_register_environment{#class}{#normalizedbody}%
1414     \settrue\c_font_defining_environment_state
1415     \font_helpers_define_unknown_font{#normalizedbody}% current class
1416     \setfalse\c_font_defining_environment_state
1417     \pop_macro_fontclass
1418   \fi
1419   \font_helpers_register_fontbody{#normalizedbody}}
1420
1421%D Checking
1422
1423\def\font_helpers_check_bodyfont_environment#normalizedbody#body%
1424  {\ifcsname\??fontenvironmentknown\fontclass#normalizedbody\endcsname
1425     % already defined
1426   \else
1427     \font_helpers_check_bodyfont_environment_indeed{#normalizedbody}{#body}%
1428   \fi}
1429
1430\def\font_helpers_check_bodyfont_environment_indeed#normalizedbody#body%
1431  {\font_helpers_register_environment\fontclass{#normalizedbody}%
1432   \ifcsname\??fontbodyknown#normalizedbody\endcsname
1433   \else
1434     \font_helpers_define_unknown_font{#normalizedbody}%
1435   \fi}
1436
1437%D We default all parameters to the main bodyfont size, so the next setup is valid
1438%D too:
1439%D
1440%D \starttyping
1441%D \definebodyfontenvironment[24pt]
1442%D \stoptyping
1443%D
1444%D All parameters can be redefined when needed, so one doesnot have to stick to the
1445%D default ones.
1446
1447%D \macros
1448%D   {definebodyfont}
1449%D
1450%D The next step in defining a bodyfont involves the actual font files, which can be
1451%D recognized by their extension \type {tfm}. Installing those file is often beyond
1452%D the scope of the user and up to the system administrator.
1453%D
1454%D \showsetup{definebodyfont}
1455%D
1456%D This commands takes three arguments: a (series of) bodyfont size(s), the style
1457%D group to which the definitions belong, and an alternative, as specified by the
1458%D \TEX\ (math) families, extended with~a, b~\unknown.
1459%D
1460%D We show two examples, that show all the alternative scaling options. The \type
1461%D {\tfa} alternatives can be extended with \type {\bfa}, \type {\slb}, etc. or even
1462%D \type {e} and higher alternatives. The magic scaled values are derived from plain
1463%D \TEX's \type {\magstep}:
1464%D
1465%D \starttyping
1466%D \definebodyfont [12pt] [rm]
1467%D   [tf=cmr12,
1468%D    bf=cmbx12,
1469%D    it=cmti12,
1470%D    sl=cmsl12,
1471%D    bi=cmbxti10 at 12pt,
1472%D    bs=cmbxsl10 at 12pt,
1473%D   tfa=cmr12    scaled 1.200,
1474%D   tfb=cmr12    scaled 1.440,
1475%D   tfc=cmr12    scaled 1.728,
1476%D   tfd=cmr12    scaled 2.074,
1477%D    sc=cmcsc10  at 12pt]
1478%D
1479%D \definebodyfont [12pt,11pt,10pt,9pt,8pt] [rm]
1480%D   [tf=lbr  sa 1,
1481%D    bf=lbd  sa 1,
1482%D    it=lbi  sa 1,
1483%D    sl=lbsl sa 1,
1484%D    bi=lbdi sa 1,
1485%D    bs=lbdi sa 1,
1486%D   tfa=lbr  sa 1.200,
1487%D   tfb=lbr  sa 1.440,
1488%D   tfc=lbr  sa 1.728,
1489%D   tfd=lbr  sa 2.074,
1490%D    sc=lbr  sa 0.833]
1491%D \stoptyping
1492%D
1493%D The second example shows that we can define more sizes at once. The main
1494%D difference between these examples is that the Computer Modern Roman come in many
1495%D design sizes. This means that there we cannot define them in bulk using \type
1496%D {sa}. Instead of \type {rm} (roman) one can define \type {ss} (sans serif), \type
1497%D {tt} (teletype), \type {hw} (hand written), \type {cg} (calygraphic) and whatever
1498%D styles.
1499%D
1500%D The first argument may be a comma separated list. This, combined with
1501%D specifications using \type{sa} can save a lot of typing. Although all arguments
1502%D should be specified, we treat the second argument as optional.
1503%D
1504%D Defining a bodyfont involves two actions: defining the specific style related
1505%D alternatives, like \type {\rma}, \type {\bfa} and \type {\rmsla}, and storing the
1506%D definitions of their bodyfont size related fonts. The first step is bodyfont
1507%D independant but executed every time. This permits user definitions like \type
1508%D {\tfw} or \type {\bfq} for real large alternatives.
1509%D
1510%D If we move design size info to the lfg file (after all only lm has design sizes)
1511%D we can get rid of much code .. 2012 or so.
1512
1513\installcorenamespace{fontdefinitions}
1514
1515% [class] [name]      [rm,ss] [settings]
1516% [class] [10pt,11pt] [rm,ss] [settings]
1517% [class] [10pt,11pt] [rm,ss] [name]
1518
1519% [class] [name]              [settings]   == [name]      [rm] [settings]
1520% [class] [10pt,11pt]         [settings]   == [name]      [rm] [settings]
1521% [class] [10pt,11pt]         [name]       == [10pt,11pt] [rm] [name]
1522
1523\permanent\tolerant\protected\def\definebodyfont[#1]#*[#2]#*[#3]#*[#4]%
1524  {\ifarguments
1525   \or
1526     \font_basics_define_body_font[#1][\s!rm][]%
1527   \or
1528     \font_basics_define_body_font[#1][\s!rm][#2]%
1529   \or
1530     \font_basics_define_body_font[#1][#2][#3]%
1531   \or
1532     \processcommacommand[#1]{\font_basics_define_body_font_class_given[#2][#3][#4]}%
1533   \fi}
1534
1535\protected\def\font_basics_define_body_font[#whatever]%
1536  {\doifelsenumber{#whatever}\font_basics_define_body_font_body\font_basics_define_body_font_name[#whatever]}
1537
1538\protected\def\font_basics_define_body_font_class_given[#1][#2][#3]#4%
1539  {\push_macro_fontclass
1540   \doifelse{#4}\s!default
1541     {\let\fontclass\empty}
1542     {\def\fontclass{#4}}%
1543   \definebodyfont[#1][#2][#3]%
1544   \pop_macro_fontclass}
1545
1546\protected\def\font_basics_define_body_font_body[#body][#style][#specification]%
1547  {\ifcondition\validassignment{#specification}%
1548     \expandafter\font_basics_define_body_font_body_assignment
1549   \else
1550     \expandafter\font_basics_define_body_font_body_identifier
1551   \fi
1552   [#body][#style][#specification]}%
1553
1554\protected\def\font_basics_define_body_font_name[#name][#style][#specification]%
1555  {\ifcondition\validassignment{#specification}%
1556     \expandafter\font_basics_define_body_font_name_assignment
1557   \else
1558     \expandafter\font_basics_define_body_font_name_identifier
1559   \fi
1560   [#name][#style][#specification]}%
1561
1562\protected\def\font_basics_define_body_font_body_assignment[#bodylist][#stylelist][#assignments]%
1563  {\processcommalist[#bodylist]{\font_basics_define_body_font_body_assignment_a{#stylelist}{#assignments}}}
1564
1565\protected\def\font_basics_define_body_font_body_assignment_a#stylelist#assignments#body%
1566  {\normalizebodyfontsize\m_font_asked_body{#body}%
1567   % normally we define quite a lot in advance, i.e global defs
1568   \font_helpers_check_bodyfont_environment\m_font_asked_body\m_font_asked_body % !!
1569   \processcommalist[#stylelist]{\font_basics_define_body_font_body_assignment_b{#assignments}}}
1570
1571\protected\def\font_basics_define_body_font_body_assignment_b#assignments#style%
1572  {\edef\m_font_asked_style{#style}%
1573   \processcommalist[#assignments]\font_basics_define_body_font_defs}
1574
1575\protected\def\font_basics_define_body_font_defs
1576  {\ifempty\fontclass
1577     \expandafter\font_basics_define_body_font_defs_nop
1578   \else
1579     \expandafter\font_basics_define_body_font_defs_yes
1580   \fi}
1581
1582\protected\def\font_basics_define_body_font_defs_yes_normal#assignment%
1583  {\ifx\m_font_asked_style\s!mm
1584     \expandafter\font_basics_define_body_font_yes_mm
1585   \else
1586     \expandafter\font_basics_define_body_font_yes_xx
1587   \fi[#assignment]}
1588
1589\protected\def\font_basics_define_body_font_defs_nop_normal#assignment%
1590  {\ifx\m_font_asked_style\s!mm
1591     \expandafter\font_basics_define_body_font_nop_mm
1592   \else
1593     \expandafter\font_basics_define_body_font_nop_xx
1594   \fi[#assignment]}
1595
1596\protected\def\font_basics_define_body_font_defs_yes_traced#assignment%
1597  {\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] [#assignment]}%
1598   \ifx\m_font_asked_style\s!mm
1599     \expandafter\font_basics_define_body_font_yes_mm
1600   \else
1601     \expandafter\font_basics_define_body_font_yes_xx
1602   \fi[#assignment]}
1603
1604\protected\def\font_basics_define_body_font_defs_nop_traced#assignment%
1605  {\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] [#assignment]}%
1606   \ifx\m_font_asked_style\s!mm
1607     \expandafter\font_basics_define_body_font_nop_mm
1608   \else
1609     \expandafter\font_basics_define_body_font_nop_xx
1610   \fi[#assignment]}
1611
1612\let\font_basics_define_body_font_defs_yes\font_basics_define_body_font_defs_yes_normal
1613\let\font_basics_define_body_font_defs_nop\font_basics_define_body_font_defs_nop_normal
1614
1615\appendtoks
1616    \let\font_basics_define_body_font_defs_yes\font_basics_define_body_font_defs_yes_traced
1617    \let\font_basics_define_body_font_defs_nop\font_basics_define_body_font_defs_nop_traced
1618\to \t_font_tracers_definitions
1619
1620%D We split into two characters (first part of spec) and the rest: the first two are
1621%D the style and the rest is a size, although in practice one will seldom define the
1622%D size directly. We might even drop that as it gives faster code.
1623
1624\protected\def\font_basics_define_body_font_nop_xx[#one#two#rest=#value]% local
1625  {\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi
1626   \letcsname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname\undefined
1627   \protected\edefcsname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname
1628     {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}%
1629   \letcsname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname\undefined
1630   \protected\edefcsname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname
1631     {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}%
1632   \letcsname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname\undefined
1633   \protected\edefcsname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname
1634     {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}%
1635  }
1636
1637\protected\def\font_basics_define_body_font_yes_xx[#one#two#rest=#value]% global
1638  {\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi
1639   \gletcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-1\endcsname\undefined
1640   \protected\xdefcsname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname
1641     {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-0}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
1642   \gletcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-2\endcsname\undefined
1643   \protected\xdefcsname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname
1644     {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-4}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
1645   \gletcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-3\endcsname\undefined
1646   \protected\xdefcsname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname
1647     {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-5}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
1648  }
1649
1650% \writestatus{fonts}{define \m_asked_style\space yes: {\expandafter\meaning\csname\fontclass\m_font_asked_body\m_font_asked_style#one#two#rest\endcsname}
1651
1652%D Here the rest concerns rl or lr so in this case it is not a size specifier but
1653%D a directional one.
1654
1655\protected\def\font_basics_define_body_font_nop_mm[#one#two#rest=#value]% local
1656  {%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi
1657   \letcsname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined
1658 % \letcsname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined
1659 % \letcsname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined
1660   \protected\xdefcsname\??fontinstanceready\m_font_asked_body-\s!mm-#one#two#rest\endcsname
1661     {\font_helpers_trigger{\m_font_asked_body-\s!mm-#one#two#rest}{\noexpand\font_rscale_mm}{\m_font_asked_body}{\normalunexpanded{#value}}}%
1662  }
1663
1664% \writestatus{fonts}{define \m_asked_style\space nop: \expandafter\meaning\csname\m_font_asked_body\m_font_asked_style#one#two#rest\endcsname}%
1665
1666\protected\def\font_basics_define_body_font_yes_mm[#one#two#rest=#value]% global
1667  {%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi
1668   \gletcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined
1669 % \gletcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined
1670 % \gletcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined
1671   \protected\xdefcsname\??fontinstanceready\fontclass-\m_font_asked_body-\s!mm-#one#two#rest\endcsname
1672     {\font_helpers_trigger{\m_font_asked_body-\s!mm-#one#two#rest}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
1673  }
1674
1675% \writestatus{fonts}{define \m_asked_style\space yes: \expandafter\meaning\csname\fontclass\m_font_asked_body\m_font_asked_style#one#two#rest\endcsname}%
1676
1677\protected\def\font_basics_define_body_font_body_identifier[#bodylist][#stylelist][#name]%
1678  {\processcommalist[#bodylist]{\font_basics_define_body_font_body_identifier_a{#stylelist}{#name}}}
1679
1680\protected\def\font_basics_define_body_font_body_identifier_a#stylelist#name#body%
1681  {\normalizebodyfontsize\m_font_asked_body{#body}%
1682   \font_helpers_check_bodyfont_environment\m_font_asked_body\m_font_asked_body % !!
1683   \processcommalist[#stylelist]{\font_basics_define_body_font_body_identifier_b{#name}}}
1684
1685\protected\def\font_basics_define_body_font_body_identifier_b#name#style%
1686  {\edef\m_font_asked_style{#style}%
1687  %\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] => [#name]}%
1688   \csname\??fontdefinitions#name:\m_font_asked_style\endcsname} % no checking
1689
1690\protected\def\font_basics_define_body_font_name_assignment[#name][#stylelist][#assignments]%
1691  {\processcommalist[#stylelist]{\font_basics_define_body_font_name_assignment_a{#name}{#assignments}}}
1692
1693\protected\def\font_basics_define_body_font_name_assignment_a#name#assignments#style%
1694  {%\writestatus\m!fonts{[#name:#style] => [#assignments]}%
1695   \edefcsname\??fontdefinitions#name:#style\endcsname{\font_basics_define_body_font_default{#assignments}}}
1696
1697\protected\def\font_basics_define_body_font_name_identifier[#name][#stylelist][#identifier]%
1698  {\processcommalist[#stylelist]{\font_basics_define_body_font_name_identifier_a{#name}{#identifier}}}
1699
1700\protected\def\font_basics_define_body_font_name_identifier_a#name#identifier#style%
1701  {%\writestatus\m!fonts{[#name:#style] => [##identifier:#style]}%
1702   \ifcsname\??fontdefinitions#name:#style\endcsname
1703     \letcsname\??fontdefinitions#name:#style\expandafter\endcsname\csname\??fontdefinitions#identifier:#style\endcsname
1704   \else
1705     \defcsname\??fontdefinitions#name:#style\endcsname{\csname\??fontdefinitions#identifier:#style\endcsname}%
1706   \fi}
1707
1708%D The unknown:
1709
1710\newconditional\c_font_defining_unknown
1711\newconditional\c_font_defining_state
1712
1713\protected\def\font_helpers_define_unknown_font#body% one level only
1714  {\font_helpers_register_fontbody{#body}% prevents loop, can go
1715   \setfalse\c_font_defining_state
1716   \font_helpers_process_relative_size_list{\font_helpers_define_unknown_check_sizes{#body}}%
1717   \ifconditional\c_font_defining_state
1718     \setfalse\c_font_defining_state
1719     \font_helpers_process_style_list{\font_helpers_define_unknown_check_definitions{#body}}%
1720     \ifconditional\c_font_defining_state
1721       \ifconditional\c_font_defining_environment_state\else
1722        %\showmessage\m!fonts{14}{#body}% main
1723         \clf_registerunknownbodysize{#body}%
1724       \fi
1725       \setfalse\c_font_defining_state
1726       \font_helpers_register_fontbody{#body}%
1727       % needed ?
1728       \ifconditional\c_font_defining_unknown
1729       \else
1730         \settrue\c_font_defining_unknown
1731         \font_helpers_process_relative_size_list{\font_helpers_define_unknown_check_relatives{#body}}%
1732         \setfalse\c_font_defining_unknown
1733       \fi
1734     \fi
1735   \fi}
1736
1737\def\font_helpers_define_unknown_check_sizes#body#relativesize%
1738  {\ifcsname\??fontenvironments\s!default#relativesize\endcsname % fontclass ?
1739     \expandafter\normalizebodyfontsize\csname\??fontenvironments#body#relativesize\endcsname{\csname\??fontenvironments\s!default#relativesize\endcsname\dimexpr#body\relax}%
1740     \settrue\c_font_defining_state
1741   \fi}
1742
1743\def\font_helpers_define_unknown_check_definitions#body#style%
1744  {\ifcsname\??fontdefinitions\s!default:#style\endcsname
1745     \edef\m_font_asked_body{#body}%
1746     \edef\m_font_asked_style{#style}%
1747     \lastnamedcs
1748     \settrue\c_font_defining_state
1749   \fi}
1750
1751\def\font_helpers_define_unknown_check_relatives#body#relativesize%
1752  {\ifcsname\??fontbodyknown\csname\??fontenvironments#body#relativesize\endcsname\endcsname \else
1753     \expandafter\font_helpers_define_unknown_font\csname\??fontenvironments#body#relativesize\endcsname
1754     \settrue\c_font_defining_state
1755   \fi}
1756
1757\protected\def\font_basics_define_body_font_default#assignments%
1758  {\font_helpers_check_relative_font_size\m_font_asked_style % still needed here?
1759   \ifcsname\m_font_asked_style\endcsname\else
1760     \normalexpanded{\definefontstyle[\m_font_asked_style][\m_font_asked_style]}%
1761   \fi
1762   \processcommalist[#assignments]\font_basics_define_body_font_defs
1763   \let\p_font_rscale\v_font_rscale_default}
1764
1765%D These macros show that quite some definitions take place. Fonts are not loaded
1766%D yet! This means that at format generation time, no font files are present.
1767
1768\protected\def\font_basics_switch_points#body%
1769  {\ifcsname\??fontbodyknown#body\endcsname \else
1770     % we need to check the relative sizes for this body
1771     \font_helpers_define_unknown_font{#body}%
1772   \fi%
1773   \ifcsname\??fontbodyknown#body\endcsname % always true now
1774     \font_basics_complete_switch{#body}%
1775     \localbodyfontsize#body\relax
1776     \normalizebodyfontsize\normalizedbodyfontsize\localbodyfontsize
1777     \font_helpers_check_bodyfont_environment\normalizedbodyfontsize\normalizedbodyfontsize % !!
1778   \else
1779     \showmessage\m!fonts4{#body}%
1780   \fi
1781   \ifconditional\c_font_compact
1782     \glyphscale\numexpr\plushundred*\dimexpr\normalizedbodyfontsize\relax/\maxcard\relax
1783   \fi}
1784
1785% \prependtoks
1786%     \ifconditional\c_font_compact
1787%         % better in lua ... accuracy
1788%         \glyphtextscale         \numexpr\plusthousand*\dimexpr\textface        \relax/\d_font_scaled_default\relax
1789%         \glyphscriptscale       \numexpr\plusthousand*\dimexpr\scriptface      \relax/\d_font_scaled_default\relax
1790%         \glyphscriptscriptscale \numexpr\plusthousand*\dimexpr\scriptscriptface\relax/\d_font_scaled_default\relax
1791%     \fi
1792% \to \everymathematics
1793
1794\protected\def\font_basics_switch_style#style%
1795  {\ifcsname\??fontstyle#style\endcsname
1796     \lastnamedcs
1797     \edef\fontstyle{#style}%
1798     \ifmmode\mr\fi % in order to be compatible with \rm in math mode
1799     % \the\everybodyfont % cleaner, in setting size as well as style
1800   \else
1801     \showmessage\m!fonts5{#style}%
1802   \fi}
1803
1804%D Here comes the main font switching macros. These macros handle changes in size as
1805%D well as returning to the global bodyfont size.
1806
1807\ifdefined\font_preloads_at_definition \else \let\font_preloads_at_definition\relax \fi
1808
1809\def\font_helpers_set_font#method#specification%
1810  {\edef\m_font_specification{#specification}%
1811   \ifempty\m_font_specification \else
1812     \ifx\m_font_specification\v!global % we can have all kind of presets
1813       \restoreglobalbodyfont
1814     \else
1815       \processcommacommand[\m_font_specification]{\font_helpers_set_font_check_size}%
1816       \processcommacommand[\m_font_specification]{\font_helpers_set_font_set_font{#method}}%
1817       \ifproductionrun
1818         \font_preloads_at_definition
1819         \font_basics_switch_points\normalizedbodyfontsize
1820         \font_basics_switch_style\fontstyle
1821         \ifempty\defaultfontclass
1822           \let\defaultfontclass\fontclass
1823         \fi
1824       \fi
1825     \fi
1826     \currentxfontsize\zerocount
1827   \fi}
1828
1829\def\font_helpers_set_font_check_size#option%
1830  {\doifelsenumber{#option}{\font_helpers_check_bodyfont_environment{#option}{#option}}\donothing}
1831
1832\def\font_helpers_set_font_set_font#method#option% method=1: set, method=2: switch
1833  {\doifsomething{#option}{\font_helpers_set_font_set_font_option{#method}{#option}}}
1834
1835\def\font_helpers_set_font_set_font_option#method#option%
1836  {\doifelsenumber{#option}%
1837     \font_helpers_set_font_set_font_option_body
1838     \font_helpers_set_font_set_font_option_keyword
1839     {#method}{#option}{#option}}
1840
1841\newmacro\m_font_keyword
1842
1843\protected\def\font_helpers_set_font_set_font_option_keyword#method#keyword#message%
1844  {\edef\m_font_keyword{#keyword}%
1845   \ifcsname\??fontenvironments\normalizedbodyfontsize\m_font_keyword\endcsname
1846     \edef\m_font_step{\font_bodyfontvariable\m_font_keyword}%
1847     \normalexpanded{\font_helpers_set_font_set_font_option_body{#method}{\m_font_step}{#message}}%
1848   \orelse\ifx\m_font_keyword\v!reset
1849     \let\fontstyle\empty % new 31/7/2006
1850     \let\fontsize \empty
1851   \orelse\ifcsname\??fontstyle\m_font_keyword\endcsname
1852     \let\fontstyle\m_font_keyword
1853   \else
1854     \setcurrentfontclass\m_font_keyword
1855     \ifcase#method\relax
1856       \let\globalfontclass\globalfontclass % -)
1857     \else
1858       \let\globalfontclass\fontclass
1859     \fi
1860     \font_helpers_set_fontstyle_of_fontclass
1861   \fi}
1862
1863\def\font_helpers_set_fontstyle_of_fontclass % will be overloaded later
1864  {\let\fontstyle\s!rm}
1865
1866\protected\def\font_helpers_set_font_set_font_option_body#method#body#message%
1867  {\normalizebodyfontsize\normalizedsetfont{#body}% redundant for some calls
1868   \ifcsname\??fontbodyknown\normalizedsetfont\endcsname \else
1869     \font_helpers_define_unknown_font\normalizedsetfont
1870   \fi
1871   \ifcsname\??fontbodyknown\normalizedsetfont\endcsname
1872     \localbodyfontsize\normalizedsetfont
1873     \let\normalizedbodyfontsize\normalizedsetfont
1874   \else
1875     \showmessage\m!fonts4{#message}%
1876    %\font_helpers_set_font_set_font_option_body_fallbacks{#method}{#body}%
1877   \fi}
1878
1879% we need to check the fontclass
1880
1881\permanent\def\registerfontclass#class%
1882  {\letgvalue{\??fontclassyes#class}\v!yes} % global ?
1883
1884\permanent\def\setcurrentfontclass#class%
1885  {\ifcsname\??fontclassyes#class\endcsname
1886     \edef\fontclass{#class}%
1887   \orelse\ifcsname\??fontclassnop#class\endcsname
1888     % already tried
1889   \else   % too messy: \ifcase\currentgrouplevel % (unpredictable)
1890     \fonts_helpers_try_currentfontclass{#class}%
1891   \fi}
1892
1893\ifdefined\fonts_helpers_try_currentfontclass \else
1894
1895    \protected\def\fonts_helpers_try_currentfontclass#typeface%
1896      {\letcsname\??fontclassnop#typeface\endcsname\empty}
1897
1898\fi
1899
1900% \let\defaultfontstyle      \s!rm
1901% \let\defaultfontalternative\s!tf
1902% \let\defaultfontsize       \empty
1903% \let\defaultfontface       \!!zerocount
1904
1905%D So far for synchronisation. (We can inline the following macros.)
1906
1907\permanent\protected\def\setcurrentfont#body#style#alternative#size% not used
1908  {\edef\fontbody       {#body}%
1909   \edef\fontstyle      {#style}%
1910   \edef\fontalternative{#alternative}%
1911   \edef\fontsize       {#size}%
1912   \font_helpers_check_big_math_synchronization
1913   \font_helpers_synchronize_font}
1914
1915\permanent\protected\def\setcurrentfontbody#body% % not used
1916  {\edef\fontbody{#body}%
1917   \font_helpers_synchronize_font}
1918
1919% For Taco: optional fall backs:
1920
1921\ifdefined\font_typescripts_inherit_check \else
1922    \let\font_typescripts_inherit_check\gobbleoneargument % implemented in type-ini
1923\fi
1924
1925\protected\def\font_helpers_set_current_font_style#style%
1926  {\edef\fontstyle{#style}%
1927   \font_typescripts_inherit_check\fontstyle
1928   \ifmmode\mr\fi % otherwise \rm not downward compatible ... not adapted yet
1929   \font_helpers_synchronize_font}
1930
1931\protected\def\font_helpers_set_current_xsize_alternative#xsize#alternative%
1932  {\edef\fontface{#xsize}%
1933   \edef\fontalternative{#alternative}%
1934   \font_helpers_synchronize_font}
1935
1936\protected\def\font_helpers_set_current_font_alternative#alternative%
1937  {\edef\fontalternative{#alternative}%
1938   \font_helpers_synchronize_font}
1939
1940\protected\def\font_helpers_set_current_font_size#size%
1941  {\edef\fontsize{#size}%
1942   \font_helpers_check_big_math_synchronization % double? better in everymath?
1943   \font_helpers_synchronize_font}
1944
1945\protected\def\font_helpers_set_current_font_style_alternative#style#alternative% \rmsl
1946  {\edef\fontstyle      {#style}%
1947   \edef\fontalternative{#alternative}%
1948   \font_helpers_synchronize_font}
1949
1950\protected\def\font_helpers_set_current_font_style_size#style#size% \rma
1951  {\edef\fontstyle{#style}%
1952   \edef\fontsize {#size}%
1953   \font_helpers_check_big_math_synchronization % double? better in everymath?
1954   \font_helpers_synchronize_font}
1955
1956\protected\def\font_helpers_set_current_font_alternative_size#alternative#size% \sla
1957  {\edef\fontalternative{#alternative}%
1958   \edef\fontsize       {#size}%
1959   \font_helpers_check_big_math_synchronization % double? better in everymath?
1960   \font_helpers_synchronize_font}
1961
1962\protected\def\font_helpers_set_current_font_style_alternative_size#style#alternative#size% \rmsla
1963  {\edef\fontstyle      {#style}%
1964   \edef\fontalternative{#alternative}%
1965   \edef\fontsize       {#size}%
1966   \font_helpers_check_big_math_synchronization % double? better in everymath?
1967   \font_helpers_synchronize_font}
1968
1969\protected\def\font_helpers_synchronize_font % we can have dups i.e. no need to let fontstrategy
1970  {\ifempty\fontclass
1971     \applyfontstrategies
1972   \else
1973     \applyfontclassstrategies
1974   \fi
1975   \setfalse\c_font_auto_size
1976   \ifskipfontcharacteristics
1977     \the\everyfont % \setfontcharacteristics
1978     \the\everyfontswitch
1979   \fi}
1980
1981%D This is the resolver for special cases (sizes) and in practice it is not called
1982%D that often so further optimization makes no sense.
1983
1984\def\font_helpers_check_strategy_class_a % --- --- --- --- % pt tt bf a
1985  {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
1986     \setfalse\c_font_auto_size
1987     \lastnamedcs
1988   \else
1989     \expandafter\font_helpers_check_strategy_class_b
1990   \fi}
1991
1992\def\font_helpers_check_strategy_class_b % --- --- --- def % pt tt bf
1993  {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
1994     \settrue\c_font_auto_size
1995     \lastnamedcs
1996   \else
1997     \expandafter\font_helpers_check_strategy_class_c
1998   \fi}
1999
2000\def\font_helpers_check_strategy_class_c % --- --- def --- % pt tt tf a
2001  {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
2002     \settrue\c_font_auto_size
2003     \lastnamedcs
2004   \else
2005     \expandafter\font_helpers_check_strategy_class_d
2006   \fi}
2007
2008\def\font_helpers_check_strategy_class_d % --- --- def def % pt tt tf
2009  {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
2010     \settrue\c_font_auto_size
2011     \lastnamedcs
2012   \else
2013     \expandafter\font_helpers_check_strategy_class_e
2014   \fi}
2015
2016\def\font_helpers_check_strategy_class_e % --- def def def % pt rm tf
2017  {\ifcsname\??fontinstanceready\fontclass-\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
2018     \setfalse\c_font_auto_size
2019     \lastnamedcs
2020   \else
2021     \expandafter\font_helpers_check_strategy_class_f
2022   \fi}
2023
2024\def\font_helpers_check_strategy_class_f % def def def def % rm tf
2025  {\ifcsname\??fontinstanceready\fontclass-\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
2026     \settrue\c_font_auto_size
2027     \lastnamedcs
2028   \else
2029     \expandafter\font_helpers_check_strategy_a
2030   \fi}
2031
2032% no class
2033
2034\def\font_helpers_check_strategy_a % --- --- --- --- % pt tt bf a
2035  {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
2036     \setfalse\c_font_auto_size
2037     \lastnamedcs
2038   \else
2039     \expandafter\font_helpers_check_strategy_b
2040   \fi}
2041
2042\def\font_helpers_check_strategy_b % --- --- --- --- % pt tt bf a
2043  {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
2044     \settrue\c_font_auto_size
2045     \lastnamedcs
2046   \else
2047     \expandafter\font_helpers_check_strategy_c
2048   \fi}
2049
2050\def\font_helpers_check_strategy_c % --- --- --- --- % pt tt bf a
2051  {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
2052     \settrue\c_font_auto_size
2053     \lastnamedcs
2054   \else
2055     \expandafter\font_helpers_check_strategy_d
2056   \fi}
2057
2058\def\font_helpers_check_strategy_d % --- --- --- --- % pt tt bf a
2059  {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
2060     \settrue\c_font_auto_size
2061     \lastnamedcs
2062   \else
2063     \expandafter\font_helpers_check_strategy_e
2064   \fi}
2065
2066\def\font_helpers_check_strategy_e % --- --- --- --- % pt tt bf a
2067  {\ifcsname\??fontinstanceready\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
2068     \setfalse\c_font_auto_size
2069     \lastnamedcs
2070   \else
2071     \expandafter\font_helpers_check_strategy_f
2072   \fi}
2073
2074\def\font_helpers_check_strategy_f % --- --- --- --- % pt tt bf a
2075  {\ifcsname\??fontinstanceready\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
2076     \settrue\c_font_auto_size
2077     \lastnamedcs
2078   \fi}
2079
2080\permanent\let\applyfontstrategies     \font_helpers_check_strategy_a
2081\permanent\let\applyfontclassstrategies\font_helpers_check_strategy_class_a
2082
2083%D Let's synchronize:
2084
2085\newconditional\c_font_synchronize \settrue\c_font_synchronize
2086
2087\prependtoks
2088    \ifconditional\c_font_synchronize
2089        \font_helpers_synchronize_math
2090        \font_helpers_synchronize_font % problem: syncs last font
2091    \fi
2092\to \everybodyfont
2093
2094%D Setting the normal sizes as well as the x and xx smaller sizes is accomplished by
2095%D the next set of macros. When in math mode, the commands \type {\tx} and \type
2096%D {\txx} are just a switch to the script and double script styles, but in text mode
2097%D the values defined by the bodyfontenvironment are used. Here we also set \type
2098%D {\currentxfontsize}.
2099
2100\def\font_helpers_set_current_font_xxx_alternative#alternative#xsize#scriptstyle%
2101  {\ifmmode
2102     #scriptstyle%
2103   \else
2104     \font_helpers_set_current_xsize_alternative{#xsize}{#alternative}%
2105   \fi}
2106
2107\def\font_helpers_reset_x_fontsize
2108  {\ifcase\currentxfontsize\else
2109     \currentxfontsize\zerocount
2110     % also \sx and \sxx ?
2111     \enforced\let\tx \normaltx
2112     \enforced\let\txx\normaltxx
2113   \fi}
2114
2115\let\font_helpers_check_nested_x_fontsize\relax
2116
2117\def\font_helpers_set_current_font_x_alternative#alternative%
2118  {\font_helpers_check_nested_x_fontsize
2119   \font_helpers_set_current_font_xxx_alternative{#alternative}{4}\scriptstyle
2120   \currentxfontsize\plusone
2121   \enforced\let\tx\txx}
2122
2123\def\font_helpers_set_current_font_xx_alternative#alternative%
2124  {\font_helpers_check_nested_x_fontsize
2125   \font_helpers_set_current_font_xxx_alternative{#alternative}{5}\scriptscriptstyle
2126   \currentxfontsize\plustwo
2127   \enforced\let\tx\empty
2128   \enforced\let\txx\empty}
2129
2130%D This alterative is not really needed, but for old time's sake we keep it there.
2131%D We can speed it up when needed.
2132
2133\def\font_helpers_set_current_font_x_style_alternative #alternative{\csname#alternative\endcsname\tx}
2134\def\font_helpers_set_current_font_xx_style_alternative#alternative{\csname#alternative\endcsname\txx}
2135
2136%D These macros also show us that when we call for \type {\tx}, this macro is
2137%D redefined to be \type {\txx}. Therefore calls like:
2138%D
2139%D \startbuffer
2140%D {small \tx  is \tx  beautiful}
2141%D {small \tx  is \txx beautiful}
2142%D {small \txx is \tx  beautiful}
2143%D {small \txx is \txx beautiful}
2144%D \stopbuffer
2145%D
2146%D \typebuffer
2147%D
2148%D result in:
2149%D
2150%D \startlines
2151%D \getbuffer
2152%D \stoplines
2153%D
2154%D Setting the main size involves the style list and therefore takes a bit more
2155%D time. Keep in mind that the fontsize is represented by a character or empty.
2156
2157\installcorenamespace{fontscalex}
2158\installcorenamespace{fontscalexx}
2159
2160\newconditional\c_font_inherit_scale
2161
2162\def\font_scale_inherit#1%
2163  {\begingroup
2164   \scratchcounterone\fontid\font\relax
2165   \currentxfontsize\plusone
2166   \normalexpanded{\definedfont[\clf_specifiedfont\scratchcounterone\font_currentfontscale\relax]}%
2167   \scratchcountertwo\fontid\font\relax
2168   \currentxfontsize\plustwo
2169   \normalexpanded{\definedfont[\clf_specifiedfont\scratchcounterone\font_currentfontscale\relax]}%
2170   \scratchcounterthree\fontid\font\relax
2171   % parent -> x -> xx
2172   % parent -> xx
2173   %
2174   % this can become \integerdef
2175   %
2176   \global\expandafter\chardef\csname\??fontscalex \number\scratchcounterone\endcsname\scratchcountertwo
2177   \global\expandafter\chardef\csname\??fontscalexx\number\scratchcounterone\endcsname\scratchcounterthree
2178   \global\expandafter\chardef\csname\??fontscalex \number\scratchcountertwo\endcsname\scratchcounterthree
2179   \global\expandafter\chardef\csname\??fontscalexx\number\scratchcountertwo\endcsname\scratchcounterthree
2180   \endgroup
2181   \setfontid\csname#1\number\fontid\font\endcsname}
2182
2183\def\font_scale_inherit_x
2184  {\ifcsname\??fontscalex\number\fontid\font\endcsname
2185     \setfontid\lastnamedcs
2186   \else
2187     \font_scale_inherit\??fontscalex
2188   \fi
2189   \ifskipfontcharacteristics
2190     \the\everyfont % \setfontcharacteristics
2191     \the\everyfontswitch
2192   \fi}
2193
2194\def\font_scale_inherit_xx
2195  {\ifcsname\??fontscalexx\number\fontid\font\endcsname
2196     \setfontid\lastnamedcs
2197   \else
2198     \font_scale_inherit\??fontscalexx
2199   \fi
2200   \ifskipfontcharacteristics
2201     \the\everyfont % \setfontcharacteristics
2202     \the\everyfontswitch
2203   \fi}
2204
2205\def\font_scale_defined_x
2206  {\let\fontface\!!plusfour
2207   \let\fontalternative\fontalternative
2208   \font_helpers_synchronize_font}
2209
2210\def\font_scale_defined_xx
2211  {\let\fontface\!!plusfive
2212   \let\fontalternative\fontalternative
2213   \font_helpers_synchronize_font}
2214
2215% to freeze or not ...
2216
2217\permanent\protected\def\tx
2218  {\currentxfontsize\plusone
2219   \ifmmode
2220     \scriptstyle
2221   \orelse\ifconditional\c_font_inherit_scale
2222     \font_scale_inherit_x
2223   \else
2224     \font_scale_defined_x
2225   \fi
2226   \enforced\let\tx\txx}
2227
2228\permanent\protected\def\txx
2229  {\currentxfontsize\plustwo
2230   \ifmmode
2231     \scriptscriptstyle
2232   \orelse\ifconditional\c_font_inherit_scale
2233     \font_scale_inherit_xx
2234   \else
2235     \font_scale_defined_xx
2236   \fi
2237   \enforced\let\tx \empty
2238   \enforced\let\txx\empty}
2239
2240\permanent\protected\def\sx
2241  {\currentxfontsize\plusone
2242   \ifmmode
2243     \scriptstyle
2244   \else
2245     \font_scale_inherit_x
2246   \fi
2247   \enforced\let\tx\txx
2248   \enforced\let\sx\sxx}
2249
2250\permanent\protected\def\sxx
2251  {\currentxfontsize\plustwo
2252   \ifmmode
2253     \scriptscriptstyle
2254   \else
2255     \font_scale_inherit_xx
2256   \fi
2257   \enforced\let\tx \empty
2258   \enforced\let\txx\empty
2259   \enforced\let\sx \empty
2260   \enforced\let\sxx\empty}
2261
2262\permanent\protected\def\useinheritxsizes{\settrue \c_font_inherit_scale} % not yet public, playground for WS and me
2263\permanent\protected\def\usedefinedxsizes{\setfalse\c_font_inherit_scale} % not yet public, playground for WS and me
2264
2265\aliased\let\normaltx \tx
2266\aliased\let\normaltxx\txx
2267
2268\aliased\let\normalsx \sx
2269\aliased\let\normalsxx\sxx
2270
2271%D When asking for a complete font switch, for instance from 10 to 12~points, the
2272%D next macro does the job. First we normalize the size, next we define the current
2273%D range of text, script and scriptscript sizes, then we set the text fonts and the
2274%D math families and finally we activate the default typeface and also set the font
2275%D specific parameters assigned to \type {\everybodyfont}.
2276
2277\permanent\protected\def\textface        {\currentbodyfontdimension\s!text        }
2278\permanent\protected\def\scriptface      {\currentbodyfontdimension\s!script      }
2279\permanent\protected\def\scriptscriptface{\currentbodyfontdimension\s!scriptscript}
2280\permanent\protected\def\xtextface       {\currentbodyfontdimension\s!x           }
2281\permanent\protected\def\xxtextface      {\currentbodyfontdimension\s!xx          }
2282
2283\installcorenamespace{fontbodyfaces}
2284
2285\protected\def\font_basics_complete_switch#size%
2286  {\bodyfontsize#size\relax
2287   \normalizebodyfontsize\normalizedbodyfontsize\bodyfontsize
2288   \expandafter\let\expandafter\font_basics_set_faces\csname\??fontbodyfaces\fontbody\endcsname
2289   \ifrelax\font_basics_set_faces
2290     \font_basics_set_faces_preset
2291   \fi
2292   \font_basics_set_faces}
2293
2294\def\font_basics_set_faces_preset
2295  {\edef\font_basics_set_faces{% 0.2 sec on 10K \tfa
2296     \enforced\permanent\protected\def\textface        {\currentbodyfontdimension\s!text        }%
2297     \enforced\permanent\protected\def\scriptface      {\currentbodyfontdimension\s!script      }%
2298     \enforced\permanent\protected\def\scriptscriptface{\currentbodyfontdimension\s!scriptscript}%
2299     \enforced\permanent\protected\def\xtextface       {\currentbodyfontdimension\s!x           }%
2300     \enforced\permanent\protected\def\xxtextface      {\currentbodyfontdimension\s!xx          }%
2301   }%
2302   \gletcsname\??fontbodyfaces\fontbody\endcsname\font_basics_set_faces}
2303
2304\permanent\def\currentbodyfontdimension#parameter% there can be factors here
2305  {\the\dimexpr
2306     \ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname
2307       \lastnamedcs
2308     \orelse\ifcsname\??fontenvironments\fontclass\s!default#parameter\endcsname
2309       \lastnamedcs
2310       \dimexpr\normalizedbodyfontsize\relax
2311     \orelse\ifcsname\??fontenvironments\normalizedbodyfontsize#parameter\endcsname
2312       \lastnamedcs
2313     \else
2314       \csname\??fontenvironments\s!default#parameter\endcsname
2315       \dimexpr\normalizedbodyfontsize\relax
2316     \fi
2317   \relax}
2318
2319%D \macros
2320%D   {setupbodyfont,switchtobodyfont}
2321%D
2322%D The next two macros are user ones. With \type {\setupbodyfont} one can set the
2323%D document bodyfont size, font family, style and/or options defined in files, for
2324%D example:
2325%D
2326%D \starttyping
2327%D \setupbodyfont[modern,12pt,roman]
2328%D \stoptyping
2329%D
2330%D This command affects the document as a whole: text, headers and footers. The
2331%D second macro however affects only the text:
2332%D
2333%D \starttyping
2334%D \switchtobodyfont[10pt]
2335%D \stoptyping
2336%D
2337%D So we've got:
2338%D
2339%D \showsetup{setupbodyfont}
2340%D \showsetup{switchtobodyfont}
2341%D
2342%D Both macros look alike. The second one also has to take all kind of keywords into
2343%D account.
2344
2345\ifdefined\saveinterlinespace    \else \let\saveinterlinespace   \relax \fi
2346\ifdefined\restoreinterlinespace \else \let\restoreinterlinespace\relax \fi
2347
2348% \newtoks \everysetupbodyfont
2349% \newtoks \everyswitchtobodyfont
2350
2351\permanent\protected\def\setupbodyfont
2352  {\doifelsenextoptionalcs\font_basics_setupbodyfont_yes\font_basics_setupbodyfont_nop}
2353
2354\def\font_basics_setupbodyfont_nop
2355  {\restoreglobalbodyfont
2356   \saveinterlinespace}
2357
2358\def\font_basics_setupbodyfont_yes[#specification]%
2359  {\doifsomething{#specification}
2360     {\font_helpers_set_font\plusone{#specification}%
2361      \globalbodyfontsize\localbodyfontsize
2362      \normalizebodyfontsize\normalizedglobalbodyfontsize\globalbodyfontsize
2363      \let\globalfontstyle\fontstyle
2364      \ifproductionrun
2365        \the\everybodyfont
2366        \the\everyglobalbodyfont
2367        \saveinterlinespace
2368      \fi
2369      \the\everysetupbodyfont}}
2370
2371\protected\def\font_basics_switchtobodyfont#specification%
2372  {\edef\m_font_step{\font_bodyfontvariable{#specification}}%
2373   \ifempty\m_font_step
2374     \font_helpers_set_font\zerocount{#specification}%
2375   \else
2376     \font_helpers_switch_bodyfont_step % so we have a fast [small] switch
2377   \fi
2378   \the\everybodyfont
2379   \the\everyswitchtobodyfont}
2380
2381\permanent\protected\def\switchtobodyfont[#specification]% could become an ifx
2382  {\doifsomething{#specification}{\font_basics_switchtobodyfont{#specification}}}
2383
2384\permanent\protected\def\usebodyfontparameter#1%
2385  {\edef\m_font_bodyfont_asked{#1\c!bodyfont}%
2386   \ifempty\m_font_bodyfont_asked\else
2387     \font_basics_switchtobodyfont\m_font_bodyfont_asked
2388   \fi}
2389
2390\def\font_helpers_switch_bodyfont_step
2391  {\font_basics_switch_points\m_font_step
2392   \font_basics_switch_style \fontstyle}
2393
2394%D The following alternative is meant for math||to||text switching and will be
2395%D optimized.
2396
2397\permanent\protected\def\fastswitchtobodyfont#name%
2398  {\ifcsname\??fontenvironments\normalizedbodyfontsize#name\endcsname
2399     \edef\p_bodyfont{\lastnamedcs}%
2400     \ifcsname\??fontbodyknown\p_bodyfont\endcsname
2401       \font_basics_complete_switch\p_bodyfont
2402       \localbodyfontsize\p_bodyfont\relax
2403     \fi
2404   \fi
2405   \csname\??fontstyle\fontstyle\endcsname
2406   \the\everybodyfont}
2407
2408%D \starttyping
2409%D $\cases{& \ccaron}$ $x=\hbox{\ccaron $x=\hbox{\ccaron}$}$
2410%D \stoptyping
2411
2412%D \macros
2413%D   {usebodyfont}
2414%D
2415%D This looks nicer then a switch in the preamble
2416%D
2417%D \starttyping
2418%D \usebodyfont[pagella,10pt]
2419%D \usebodyfont[termes,10pt]
2420%D \usebodyfont[dejavu,10pt]
2421%D
2422%D \setupbodyfont[dejavu]
2423%D
2424%D \starttext
2425%D     test
2426%D \stoptext
2427%D \stoptyping
2428
2429\permanent\protected\def\usebodyfont[#1]%
2430  {\ifempty\fontclass
2431     \setupbodyfont[#1]%
2432   \else
2433     \switchtobodyfont[#1]%
2434     \fullrestoreglobalbodyfont
2435   \fi}
2436
2437\fetchmodulecommand \showbodyfontstate \f!font_run
2438
2439%D Handy for manuals:
2440
2441%D The \type {\tochar} commmand takes a specification:
2442%D
2443%D \starttabulate[|l|l|l|]
2444%D \NC e \NC entity                   \NC e:eacute \NC \NR
2445%D \NC x \NC hexadecimal unicode      \NC x:013D   \NC \NR
2446%D \NC d \NC decimal unicode          \NC d:123    \NC \NR
2447%D \NC s \NC hexadecimal index (slot) \NC s:210D   \NC \NR
2448%D \NC i \NC decimal index            \NC i:456    \NC \NR
2449%D \NC n \NC name                     \NC n:eight  \NC \NR
2450%D \NC c \NC name                     \NC c:x      \NC \NR
2451%D \NC u \NC unicode descriptions     \NC u:dog    \NC \NR
2452%D \NC a \NC all (also descriptions)  \NC a:rewind \NC \NR
2453%D \stoptabulate
2454%D
2455%D This is an expandable command!
2456
2457\permanent\protected\def\fontchar       #character{\clf_fontchar{#character}}
2458\permanent\protected\def\fontcharbyindex    #index{\clf_fontcharbyindex#index\relax}
2459\permanent          \def\tochar    #specifications{\clf_tochar{#specifications}} % expanded (also used in edef)
2460
2461%D The next auxilliary macro is an alternative to \type {\fontname}.
2462
2463\permanent\def\purefontname#font{\clf_purefontname{\fontname#font}}
2464
2465%D \macros
2466%D   {switchstyleonly}
2467%D
2468%D For switching a style but keeping the alternative, there
2469%D is:
2470%D
2471%D \starttyping
2472%D {\bf text \switchstyleonly\ss text}
2473%D {\bf text \switchstyleonly[ss]text}
2474%D {\sl text \switchstyleonly[sansserif]text}
2475%D \stoptyping
2476
2477\permanent\protected\def\switchstyleonly
2478  {\doifelsenextoptionalcs\font_basics_switch_style_only_opt\font_basics_switch_style_only_arg}
2479
2480\def\font_basics_switch_style_only_arg#name% stupid version
2481  {\font_helpers_set_current_font_style{\csname\??fontshortstyle\checkedstrippedcsname#name\endcsname}%
2482   \the\everybodyfont} % needed ?
2483
2484\def\font_basics_switch_style_only_opt[#name]% todo : check
2485  {\font_helpers_set_current_font_style{\csname\??fontshortstyle#name\endcsname}%
2486   \the\everybodyfont} % needed ?
2487
2488%D \macros
2489%D   {definebodyfontswitch}
2490%D
2491%D \PLAIN\ \TEX\ defines some macro's like \type {\tenpoint} to switch to a specific
2492%D bodyfontsize. Just for the sake of compatibility we can define them like:
2493%D
2494%D \starttyping
2495%D \definebodyfontswitch [twelvepoint] [12pt]
2496%D \stoptyping
2497%D
2498%D We don't support language specific synonyms here.
2499
2500\permanent\tolerant\protected\def\definebodyfontswitch[#command]#spacer[#specification]% no longer a commalist (not useful)
2501  {\frozen\protected\defcsname#command\endcsname{\switchtobodyfont[#specification]}}%
2502
2503%D \macros
2504%D   {setsmallbodyfont,setmainbodyfont,setbigbodyfont}
2505%D
2506%D When we're typesetting at for instance 10pt, we can call for the \type {small} as
2507%D well as the \type {big} alternative, related to this main size, using \type
2508%D {\switchtobodyfont[small]}. The three alternatives can be activated by the next
2509%D three system calls and are defined by the bodyfontenvironment.
2510
2511\newmacro\m_font_step
2512
2513\def\font_helpers_set_bodyfont_step#step%
2514  {\edef\m_font_step{\font_bodyfontvariable{#step}}% not always \cs
2515   \font_basics_switch_points\m_font_step
2516   \font_basics_switch_style \fontstyle}
2517
2518\permanent\protected\def\setsmallbodyfont{\font_helpers_set_bodyfont_step\v!small\the\everybodyfont}
2519\permanent\protected\def\setbigbodyfont  {\font_helpers_set_bodyfont_step\v!big  \the\everybodyfont}
2520
2521\permanent\protected\def\setmainbodyfont
2522  {\font_basics_switch_points\normalizedbodyfontsize
2523   \font_basics_switch_style\fontstyle
2524   \the\everybodyfont
2525   \the\everyglobalbodyfont
2526   \saveinterlinespace}
2527
2528%D \macros
2529%D   {restoreglobalbodyfont}
2530%D
2531%D Users can set whatever font available while typesetting text. Pagenumbers,
2532%D footers, headers etc. however must be typeset in the main bodyfont and style of
2533%D the document. Returning to the global state can be done with the next macro:
2534%D
2535%D This macro has to be called when entering the pagebody handling routine as well
2536%D as the footnote insert routine. Users can access this feature |<|for instance
2537%D when one wants to typeset tables and alike in the main bodyfont and style while
2538%D the running text is temporary set to a smaller one|>| by saying \type
2539%D {\switchtobodyfont [global]}.
2540
2541\mutable\let\globalfontstyle\s!rm
2542
2543\permanent\protected\def\fullrestoreglobalbodyfont
2544  {\let\fontsize\defaultfontsize
2545   \let\fontbody\defaultfontbody
2546   \let\fontface\defaultfontface
2547   \currentxfontsize\zerocount
2548   \let\fontclass\globalfontclass
2549   \font_basics_switch_points\normalizedglobalbodyfontsize
2550   \font_basics_switch_style\globalfontstyle
2551   \redoconvertfont % just in case a pagebreak occurs
2552   \tf
2553   \the\everybodyfont
2554   \the\everyglobalbodyfont
2555   \saveinterlinespace}
2556
2557\permanent\protected\def\partialrestoreglobalbodyfont
2558  {\let\fontsize\defaultfontsize
2559   \let\fontbody\defaultfontbody
2560   \let\fontface\defaultfontface
2561   \currentxfontsize\zerocount
2562   \redoconvertfont
2563   \tf
2564   \the\everybodyfont % indeed needed
2565   \the\everyglobalbodyfont % indeed needed
2566   \saveinterlinespace}
2567
2568\permanent\protected\def\restoreglobalbodyfont % ook style etc
2569  {\ifx\fontclass\globalfontclass
2570     \ifx\fontstyle\globalfontstyle
2571       \ifx\normalizedbodyfontsize\normalizedglobalbodyfontsize
2572         \partialrestoreglobalbodyfont
2573       \else
2574         \fullrestoreglobalbodyfont
2575       \fi
2576     \else
2577       \fullrestoreglobalbodyfont
2578     \fi
2579   \else
2580     \fullrestoreglobalbodyfont
2581   \fi}
2582
2583% in case of troubles: \let\restorebodyfont\fullrestoreglobalbodyfont
2584
2585%D Here are some fast variants that can be used in cases where no font system is
2586%D needed and where fonts are frozen:
2587%D
2588%D \starttyping
2589%D \definefont   [TestA][Serif at 10pt]
2590%D \predefinefont[TestB][Serif at 20pt]
2591%D
2592%D \testfeatureonce{1000}{{\TestA}}                         %   .312
2593%D \testfeatureonce{1000}{{\TestB}}                         % < .016
2594%D \testfeatureonce{1000}{{\definedfont[Serif at 30pt]}}    %   .312
2595%D \testfeatureonce{1000}{{\predefinedfont[Serif at 40pt]}} % < .016
2596%D \stoptyping
2597
2598\installcorenamespace{predefinedfont}
2599
2600\permanent\protected\def\predefinefont[#1]#*[#2]% global !
2601  {\protected\gdefcsname#1\endcsname{\font_basics_predefine{#1}{#2}}}
2602
2603\permanent\protected\def\predefinedfont[#1]% global !
2604  {\ifcsname\??predefinedfont#1\endcsname
2605     \lastnamedcs
2606   \else
2607     \font_basics_predefined{#1}%
2608   \fi}
2609
2610\protected\def\font_basics_predefine#1#2%
2611  {\definedfont[#2]%
2612   \gletcsname#1\expandafter\endcsname\csname\v_font_identifier_basic\endcsname}
2613
2614\protected\def\font_basics_predefined#1%
2615  {\font_basics_predefine{\??predefinedfont#1}{#1}}
2616
2617%D Handy helper:
2618
2619\permanent\protected\def\savedefinedfont[#1]% hm, how about scales
2620  {\bgroup
2621   \definedfont[#1]%
2622   \xdef\saveddefinedfontid  {\number\fontid\font}%
2623   \xdef\saveddefinedfontname{\fontname\font}%
2624   \egroup}
2625
2626\mutable\def\saveddefinedfontid  {\number\fontid\font}
2627\mutable\def\saveddefinedfontname{\fontname\font}
2628
2629%D Ugly helper:
2630
2631\permanent\protected\def\saverunningstyleandcolor
2632  {\enforced\permanent\protected\edef\restorerunningstyleandcolor
2633     {\setfontid          \number\fontid\font
2634      \c_attr_colormodel  \the\c_attr_colormodel
2635      \c_attr_color       \the\c_attr_color
2636      \c_attr_transparency\the\c_attr_transparency
2637      \relax}}
2638
2639\aliased\let\restorerunningstyleandcolor\relax
2640
2641%D Handy for defining additional glyphs:
2642
2643% todo: public implementors
2644
2645\aliased\let\getprivateglyphslot\clf_getprivateglyphslot % kind of private macro
2646
2647\aliased\let\getprivatechar     \clf_getprivatechar     % gives back a utf !
2648\aliased\let\getprivatemathchar \clf_getprivatemathchar % gives back a utf !
2649\aliased\let\getprivateslot     \clf_getprivateslot     % companion to fonts.helpers.addprivate
2650
2651% \protected\def\getprivatemathchar#1%
2652%   {\begingroup\the\textfont\zerocount\getprivatechar{#1}\endgroup}
2653
2654\permanent\protected\def\privatechar % the text variant gets expanded to utf
2655  {\ifmmode
2656     \expandafter\getprivatemathchar
2657   \else
2658     \expandafter\getprivatechar
2659   \fi}
2660
2661%D Some fonts can have color specifiers:
2662%D
2663%D \starttyping
2664%D \definefontfeature[seguiemj-cl][default][colr=yes,ccmp=yes,dist=yes]
2665%D \definefontsynonym[emoji][seguiemj*seguiemj-cl]
2666%D
2667%D \definecolor[emoji-red] [r=.4]
2668%D \definecolor[emoji-gray][s=1,t=.5,a=1]
2669%D
2670%D %definefontcolorpalette [emoji-r] [emoji-red,emoji-gray,textcolor] % bad
2671%D \definefontcolorpalette [emoji-r] [emoji-red,emoji-gray]           % okay
2672%D
2673%D \definefontfeature[seguiemj-r][ccmp=yes,dist=yes,colr=emoji-r]
2674%D
2675%D \definefont[MyEmojiR][seguiemj*seguiemj-r @ 100pt]
2676%D
2677%D \startTEXpage[offset=10pt]
2678%D     \MyEmojiR\resolvedemoji{triangular ruler}
2679%D \stopTEXpage
2680%D \stoptyping
2681
2682\permanent\tolerant\protected\def\definefontcolorpalette[#1]#*[#2]%
2683  {\clf_definefontcolorpalette{#1}{#2}}
2684
2685%D \macros
2686%D   {addfontpath}
2687%D
2688%D A way to add a path at runtime (no need to generate database):
2689
2690\permanent\protected\def\usefontpath[#1]%
2691  {\clf_addfontpath{#1}}
2692
2693%D Experiment (one can use a list):
2694%D
2695%D \starttyping
2696%D \setupfonts
2697%D   [serif=dejavuserif*default,
2698%D     sans=dejavusans*default,
2699%D     mono=dejavusansmono*none]
2700%D
2701%D {\rm A \char1234\ B \char1236\ C}
2702%D {\ss A \char1234\ B \char1236\ C}
2703%D {\ss A \char1234\ B \char1236\ C}
2704%D \stoptyping
2705
2706\appendtoks
2707    \edef\m_list{\fontsparameter\s!serif}%
2708    \ifempty\m_list\else
2709        \registerfallbackfont[\s!serif][\m_list]%
2710    \fi
2711    \edef\m_list{\fontsparameter\s!sans}%
2712    \ifempty\m_list\else
2713        \registerfallbackfont[\s!sans][\m_list]%
2714    \fi
2715    \edef\m_list{\fontsparameter\s!mono}%
2716    \ifempty\m_list\else
2717        \registerfallbackfont[\s!mono][\m_list]%
2718    \fi
2719\to \everysetupfonts
2720
2721\protect \endinput
2722