%% This is part of the OpTeX project, see http://petr.olsak.net/optex \_codedecl \fontfam {Fonts selection system <2021-07-16>} % preloaded in format \_doc ----------------------------- The variant selectors \^`\rm`, \^`\bf`, \^`\it`, \^`\bi`, \^`\tt` are defined (roughly speaking) by \begtt \catcode`\<=13 \def\ {\_tryload\_ten} \endtt where is \"internal variant name" `rm` or `bf` or `it` or `bi` or `tt`. There are five \"internal font switchers" `\_tenrm`, `\_tenbf`, `\_tenit`, `\_tenbi` and `\_tentt`. They are used almost for all fonts selected by the Fonts Selection System. For example, `\_tenbf` is the switcher for bold variant of the current family in the current font context. The \^`\bf` macro is defined as `\_tryloadbf \_tenbf`. If the font context (font family, font size, features) is not changed, then `\_tryloadbf` is `\relax` and `\_tenbf` font switcher selects given font. If the font context is changed, then `\_tryloadbf` is re-defined (see \^`\_reloading` macro) to load new bold variant of the font using \^`\_resizefont` The loaded font is saved to `\_tenbf` switcher and `\_tryloadbf` returns back to the `\relax` meaning. So, `\bf` macro loads new font with current font context and then selects it by `\_tenbf` selector. The word \"ten" is used here only for historical reason; the font can be at arbitrary size. \nl The \`\_reloading` macro is run whenever font context is changed. It activates `\_tryload` for `` in `rm`, `bf`, `it` and `bi`. The \`\_loadf``{}\ten` is processed for this. \nl The \`\_tryloadtt` is implemented differently because we want to keep family independence for `\tt` macro, see section~\ref[tt]. So, `\_tryloadtt` is defined constantly as \"loading `\tt` font" and it is not re-defined to `\relax`. On the other hand, `\_tryloadtt` is re-defined in the \^`\initunifonts` macro or when \~`\famvardef``\tt` is used. \_cod ----------------------------- \_def\_reloading{\_loadf{rm}\_tenrm \_loadf{bf}\_tenbf \_loadf{it}\_tenit \_loadf{bi}\_tenbi} \_def\_loadf#1#2{\_sdef{_tryload#1}{\_ifmmode \_else \_resizefont{#1}#2\_fi}} \_def\_tryloadtt{\_resizefont{tt}\_tentt} % only in TFM mode \_let\_tryloadrm=\_relax \_let\_tryloadbf=\_relax \_let\_tryloadit=\_relax \_let\_tryloadbi=\_relax \_doc ---------------------------- The Font Selection system allows to use \`\currvar` instead of an explicitly specified variant selector. The current variant is extracted from `\the\font` output which could be the `\_ten` control sequence. Then `\currvar` expands to `\_rm` or `\_it` etc. \_cod ---------------------------- \_protected \_def \_currvar{\_cs{_currvar:\_ea \_csstring \_the\_font}} \_sdef{_currvar:_tenrm}{\_rm} \_sdef{_currvar:_tenbf}{\_bf} \_sdef{_currvar:_tenit}{\_it} \_sdef{_currvar:_tenbi}{\_bi} \_sdef{_currvar:_tentt}{\_tt} \_public \currvar ; \_doc ----------------------------- The \`\_resizefont` `{}\` is the heart of the Fonts Selection System. It resizes the font given by the variant with respect to the current font context and sets a new . The is `rm` or `bf` or `it` or `bi` or `tt`. The new is declared (roughly speaking) by: \begtt \catcode`<=13 \_font = \_ten \_sizespec % in TFM mode \_font = {\_fontnamegen} \_sizespec % in OTF mode \endtt The font is loaded by \`\_doresizefont```. This macro has meaning \`\_doresizetfmfont` in TFM mode (default in format) and it switches to \^`\_doresizeunifont` when \^`\initunifonts` is used.\nl The `` is generated by the `\fontname` \TeX/ primitive where \`\_rfontskipat` removes the `at` part of the `\fontname` output.\nl The \`\_whatresize` is defined as ``.\nl The \^`\_fontloaded``` is a macro which can be used for post-processing when a font is loaded. \_cod ----------------------------- \_def\_resizefont#1#2{% \_edef\_whatresize{#1}\_doresizefont#2\_relax \_fontloaded #2% \_lastmagsize=\_zo \_if t\_ignoresecond#1\_else \_slet{_tryload#1}{_relax}\_fi } \_def\_doresizetfmfont#1{\_logfont{#1}% \_ea\_font\_ea#1\_ea\_rfontskipat \_fontname \_cs{_ten\_whatresize} \_relax\_space \_sizespec \_relax } \_let\_doresizefont=\_doresizetfmfont \_def\_logfont#1{} % default is no logging of used fonts \_def\_rfontskipat#1{\_ifx#1"\_ea\_rfskipatX \_else\_ea\_rfskipatN\_ea#1\_fi} \_def\_rfskipatX #1" #2\_relax{"\_whichtfm{#1}"} \_def\_rfskipatN #1 #2\_relax{\_whichtfm{#1}} \_doc ----------------------------- \`\_doresizeunifont``` implements the OTF mode of loading fonts \^`\_doresizefont`. There is a fallback to TFM mode if \^`\_fontnamegen` is not defined.\nl The \^`\_fontnamegen` expands to the font name/file:font-features depending on the current font context. \_cod ----------------------------- \_def\_doresizeunifont #1{\_logfont{#1}% \_ifx\_fontnamegen\_undefined \_doresizetfmfont#1\_else \_font#1={\_fontnamegen} \_sizespec \_relax \_setwsp#1\_relax \_fi } \_doc ----------------------------- If a font is loaded by \^`\_resizefont` or \^`\resizethefont` then the \`\_fontloaded``` is called immediately after it. If the font is loaded first then its `\skewchar` is equal to $-1$. We run \`\_newfontloaded``` and set `\skewchar=-2` in this case. A user can define a `\_newfontloaded` macro. We are sure that `\_newfontloaded` macro is called only once for each instance of the font given by its name, OTF features and size specification. The `\skewchar` value is globally saved to the font (like `\fontdimen`). If it is used in math typesetting then it is set to a positive value.\nl The `\_newfontloaded` should be defined for micro-typographic configuration of fonts, for example. See \ulink[http://petr.olsak.net/optex/optex-tricks.html\#fontexpand]{\OpTeX/ trick 0058}. \_cod ----------------------------- \_def\_fontloaded #1{\_ifnum\_skewchar#1=-1 \_skewchar#1=-2 \_newfontloaded#1\_fi} \_def\_newfontloaded #1{} \_doc ----------------------------- \`\initunifonts` macro extends \LuaTeX's font capabalities, in order to be able to load Unicode fonts. Unfortunately, this part of \OpTeX/ depends on the `luaotfload` package, which adapts Con\TeX/t's generic font loader for plain \TeX/ and \LaTeX. `luaotfload` uses Lua functions from \LaTeX's `luatexbase` namespace, we provide our own replacements. Moreover, `\initunifont` switches with the \^`\_doresizefont` macro to OTF mode which is represented by the macro \^`\_doresizeunifont`. Finally, \^`\initunifonts` sets itself to relax because we don't want to do this work twice.\nl \`\_ttunifont` is default font for `\tt` variant. User can re-define it or use \^`\famvardef``\tt`. \_cod ----------------------------- \_def\_initunifonts {% \_directlua{% require('luaotfload-main') luaotfload.main() optex_hook_into_luaotfload() }% \_gdef\_rfskipatX ##1" ##2\_relax{"##1"}% \_global\_let \_doresizefont=\_doresizeunifont \_gdef\_tryloadtt {\_begingroup \_let\_fontnamegen\_ttunifont % \tt uses \_ttunifont \_resizefont{tt}\_tentt\_relax \_ea\_endgroup \_ea\_let \_ea\_tentt \_the\_tentt}% \_global\_let \_initunifonts=\_relax % we need not to do this work twice \_global\_let \initunifonts=\_relax } \_def\_ttunifont{[lmmono10-regular]:\_fontfeatures-tlig;} \_public \initunifonts ; \_doc ----------------------------- The \`\_famdecl` `[] \ {} {} {} {}`\nl `{} {\def`\^`\_fontnamegen``{}}` runs \^`\initunifonts`, then checks if `\` is defined. If it is true, then closes the file by `\endinput`. Else it defines `\` and saves it to the internal `\_f::main.fam` command. The macro \`\_initfontfamily` needs it. The \`\_currfamily` is set to the `` because the following \^`\moddef` commands need to be in the right font family context. The `\_currfamily` is set to the `` by the `\` too, because `\` must set the right font family context. The font family context is given by the current `\_currfamily` value and by the current meaning of the \^`\_fontnamegen` macro. The \`\_mathfaminfo` is saved for usage in the catalog. \_cod ----------------------------- \_def\_famdecl [#1]#2#3#4#5#6#7#8{% \_initunifonts \_uniaccents \_unless\_ifcsname _f:\_csstring#2:main.fam\_endcsname \_isfont{#7}\_iffalse \_opwarning{Family [#1] skipped, font "#7" not found}\_ea\_ea\_ea\_endinput \_else \_edef\_currfamily {\_csstring #2}\_def\_mathfaminfo{#6}% \_wterm {FONT: [#1] -- \_string#2 \_detokenize{(#3)^^J mods:{#4} vars:{#5} math:{#6}}}% \_unless \_ifx #2\_undefined \_opwarning{\_string#2 is redefined by \_string\_famdecl\_space[#1]}\_fi \_protected\_edef#2{\_def\_noexpand\_currfamily{\_csstring #2}\_unexpanded{#8\_resetfam}}% \_ea \_let \_csname _f:\_currfamily:main.fam\_endcsname =#2% \_fi \_else \_csname _f:\_csstring#2:main.fam\_endcsname \_reloading \_rm \_ea \_endinput \_fi } \_def\_initfontfamily{% \_csname _f:\_currfamily:main.fam\_endcsname \_reloading \_rm } \_doc ----------------------------- \`\_fvars` ` ` saves data for usage by the `\_currV` macro. If a template is only dot then previous template is used (it can be used if the font family doesn't dispose with all standard variants). \nl \`\_currV` expands to a template declared by `\_fvars` depending on the ``. Usable only of standard four variants. Next variants can be declared by the \^`\famvardef` macro. \nl \`\_fsetV` `=,...,=` expands to `\def\_V{}` in the loop. \nl \`\_onlyif` `=,...,: {}` runs only if the `\_V` is defined as `` or `` or ... or ``. \nl \`\_prepcommalist` `ab,{},cd,\_end,` expands to `ab,,cd,` (auxiliary macro used in `\_onlyif`).\nl \`\_ffonum` is a shortcut for oldstyle digits font features used in font family files. You can do `\let\_ffonum=\ignoreit` if you don't want to set old digits together with `\caps`. \_cod ----------------------------- \_def\_fvars #1 #2 #3 #4 {% \_sdef{_fvar:rm}{#1}% \_sdef{_fvar:bf}{#2}% \_ifx.#2\_slet{_fvar:bf}{_fvar:rm}\_fi \_sdef{_fvar:it}{#3}% \_ifx.#3\_slet{_fvar:it}{_fvar:rm}\_fi \_sdef{_fvar:bi}{#4}% \_ifx.#4\_slet{_fvar:bi}{_fvar:it}\_fi } \_def\_currV{\_cs{_fvar:\_whatresize}} \_def\_V{ } \_def \_fsetV #1 {\_fsetVa #1,=,} \_def \_fsetVa #1=#2,{\_isempty{#1}\_iffalse \_ifx,#1\_else\_sdef{_#1V}{#2}\_ea\_ea\_ea\_fsetVa\_fi\_fi } \_def \_onlyif #1=#2:#3{% \_edef\_act{\_noexpand\_isinlist{,\_prepcommalist #2,\_end,}{,\_cs{_#1V},}}\_act \_iftrue #3\_fi } \_def\_prepcommalist#1,{\_ifx\_end#1\_empty\_else #1,\_ea\_prepcommalist\_fi} \_def\_ffonum {+onum;+pnum} \_doc ----------------------------- The \`\moddef` `\ {}` simply speaking does `\def\{}`, but we need to respect the family context. In fact, `\protected\def\_f::{}` is performed and the `\` is defined as \`\_famdepend``\{_f:\_currfamily:}`. It expands to `\_f:\_currfamily:` value if it is defined or it prints the warning. When the `\_currfamily` value is changed then we can declare the same `\` with a different meaning. When a user declares a prefixed variant of the `\` then unprefixed modifier name is used in internal macros, this is the reason why we are using the \`\_remifirstunderscore``\_tmp` (where `\_tmp` expands to `_` or to ``. The `\_remifirstunderscore` redefines `\_tmp` in the way that it expands only to `` without the first `_`. \`\_setnewmeaning` `=\_tmpa ` does exactly `\_let =\_tmpa` but warning is printed if is defined already and it is not a variant selector or font modifier. \`\_addtomodlist` `` adds given modifier to \`\_modlist` macro. This list is used after `\resetmod` when a new family is selected by a family selector, see \`\_resetfam` macro. This allows reinitializing the same current modifiers in the font context after the family is changed. \_cod ----------------------------- \_def \_moddef #1#2{\_edef\_tmp{\_csstring#1}% \_sdef{_f:\_currfamily:\_tmp}{\_addtomodlist#1#2\_reloading}% \_protected \_edef \_tmpa{\_noexpand\_famdepend\_noexpand#1{_f:\_noexpand\_currfamily:\_tmp}}% \_setnewmeaning #1=\_tmpa \moddef } \_protected \_def\_resetmod {\_cs{_f:\_currfamily:resetmod}} % private variant of \resetmod \_def \_resetfam{\_def\_addtomodlist##1{}\_resetmod \_edef \_modlist{\_ea}\_modlist \_let\_addtomodlist=\_addtomodlistb } \_def \_currfamily{} % default current family is empty \_def \_modlist{} % list of currently used modifiers \_def \_addtomodlist#1{\_addto\_modlist#1} \_let \_addtomodlistb=\_addtomodlist \_def\_famdepend#1#2{\_ifcsname#2\_endcsname \_csname#2\_ea\_endcsname \_else \_ifx\_addtomodlist\_addtomodlistb \_opwarning{\_string#1 is undeclared in family "\_currfamily", ignored}\_fi\_fi } \_def\_setnewmeaning #1=\_tmpa#2{% \_ifx #1\_undefined \_else \_ifx #1\_tmpa \_else \_opwarning{\_string#1 is redefined by \_string#2}% \_fi\_fi \_let#1=\_tmpa } \_public \moddef ; \_doc ----------------------------- \`\fontdef` ` {}` does: \begtt \catcode`\<=13 \begingroup \ea\endgroup \ea\let \ea \the\font \endtt It means that font modifiers used in are applied in the group and the resulting selected font (current at the end of the group) is set to the . We want to declare in its real name directly by `\font` primitive in order to save this name for reporting later (in overfull messages, for example). This is the reason why \^`\_loadf` is re-defined locally here. The used in expands to `\_tryload \_ten`. The modified `\_tryload` removes `\_ten` and does `\_resizefont{}`, i.e.\ a font is loaded using real `` name and then it is selected as the current font. \_cod ----------------------------- \_def\_fontdef #1#2{\_begingroup \_def\_loadf##1##2{\_sdef{_tryload##1}####1{\_resizefont{##1}#1#1}}% \_reloading \_let\_reloading=\_relax #2\_ea\_endgroup \_ea\_let \_ea#1\_the\_font } \_public \fontdef ; \_doc ----------------------------- The \`\famvardef` `\ {}` does, roughly speaking: \begtt \catcode`\<=13 \def \ {\fontdef\_ten {}\_ten} \endtt but the macro `\` is declared as family-dependent. So, the real \^`\famvardef` `\ {}` uses analogical trick like \^`\moddef` with the \^`\_famdepend` macro. The \^`\famvardef` loads the auxiliary \`\_famvardefA` `\ \_ten \_tryload {}`. It does: \begitems * `\def \_tryload:: {`\^`\fontdef`` \_ten {}}` loads font `\_ten`, * `\protected\def \ {\_famdepend \ {_f::}}`, * `\def \_f:: {\_tryload::\_ten}` keeps family dependent definition, * `\def \_currvar:_ten {\}` in order to the \^`\currvar` macro work correctly. \enditems `\famvardef\tt` behaves somewhat differently: it doesn't re-define the `\tt` macro which is defined as `\_tryloadtt \_tentt` in sections~\ref[math-preload] and~\ref[unimath-codes]. It only re-defines the internal `\_tryloadtt` macro. Note, that you cannot use `\tt` inside `\famvardef\tt`. So, new `\tt` macro does not load \^`\_ttunifont` but uses font from a standard variant rm, bf, it or bi with given font context. \_cod ----------------------------- \_def\_famvardef#1{\_edef\_tmp{\_csstring#1}% \_ea\_famvardefA \_ea#1\_csname _ten\_tmp\_ea\_endcsname \_csname _tryload:\_currfamily:\_tmp\_endcsname } \_def\_famvardefA #1#2#3#4{% #1=\XX #2=\_tenXX #3=\_tryload:currfam:XX #4=data \_isinlist{.\_rm\_bf\_it\_bi\currvar\_currvar}#1\_iftrue \_opwarning{\_string\famvardef: You cannot re-declare standard variant selector \_string#1}% \_else \_def#3{\_fontdef#2{#4}}% \_protected\_edef\_tmpa{\_noexpand\_famdepend\_noexpand#1{_f:\_noexpand\_currfamily:\_tmp}}% \_ifx #1\_tt \_let\_tryloadtt=#3\_else \_setnewmeaning #1=\_tmpa \famvardef \_fi \_sdef{_f:\_currfamily:\_tmp}{#3#2}% \_sdef{_currvar:\_csstring#2}{#1}% \_fi } \_public \famvardef ; \_doc ----------------------------- The \`\fontfam` `[]` does: \begitems * Convert its parameter to lower case and without spaces, e.g.\ ``. * If the file `f-.opm` exists read it and finish. * Try to load user defined `fams-local.opm`. * If the `` is declared in `fams-local.opm` or `fams-ini.opm` read relevant file and finish. * Print the list of declared families. \enditems The `fams-local.opm` is read by the \`\_tryloadfamslocal` macro. It sets itself to `\_relax` because we need not load this file twice. The \`\_listfamnames` macro prints registered font families to the terminal and to the log file. \_cod ----------------------------- \_def\_fontfam[#1]{% \_lowercase{\_edef\_famname{\_ea\_removespaces #1 {} }}% \_isfile {f-\_famname.opm}\_iftrue \_opinput {f-\_famname.opm}% \_else \_tryloadfamslocal \_edef\_famfile{\_trycs{_famf:\_famname}{}}% \_ifx\_famfile\_empty \_listfamnames \_else \_opinput {\_famfile.opm}% \_fi\_fi } \_def\_tryloadfamslocal{% \_isfile {fams-local.opm}\_iftrue \_opinput {fams-local.opm}\_famfrom={}% \_fi \_let \_tryloadfamslocal=\_relax % need not to load fams-local.opm twice } \_def\_listfamnames {% \_wterm{===== List of font families ======} \_begingroup \_let\_famtext=\_wterm \_def\_faminfo [##1]##2##3##4{% \_wterm{ \_space\_noexpand\fontfam [##1] -- ##2}% \_let\_famalias=\_famaliasA}% \_opinput {fams-ini.opm}% \_isfile {fams-local.opm}\_iftrue \_opinput {fams-local.opm}\_fi \_message{^^J}% \_endgroup } \_def\_famaliasA{\_message{ \_space\_space\_space\_space -- alias:} \_def\_famalias[##1]{\_message{[##1]}}\_famalias } \_public \fontfam ; \_doc ----------------------------- When the `fams-ini.opm` or `fams-local.opm` files are read then we need to save only a mapping from family names or alias names to the font family file names. All other information is ignored in this case. But if these files are read by the `\_listfamnames` macro or when printing a catalog then more information is used and printed.\nl \`\_famtext` does nothing or prints the text on the terminal. \nl \`\_faminfo` `[] {} {} {}` does\nl `\_def \_famf: {}` or prints information on the terminal. \nl \`\_famalias` `[]` does `\def \_famf: {}` where `` is stored from the previous `\_faminfo` command. Or prints information on the terminal. \nl \`\_famfrom` declares type foundry or owner or designer of the font family. It can be used in `fams-ini.opm` or `fams-local.opm` and it is printed in the font catalog. \_cod ----------------------------- \_def\_famtext #1{} \_def\_faminfo [#1]#2#3#4{% \_lowercase{\_edef\_tmp{\_ea\_removespaces #1 {} }}% \_sdef{_famf:\_tmp}{#3}% \_def\_famfile{#3}% } \_def\_famalias [#1]{% \_lowercase{\_edef\_tmpa{\_ea\_removespaces #1 {} }}% \_sdef{_famf:\_tmpa\_ea}\_ea{\_famfile}% } \_newtoks\_famfrom \_input fams-ini.opm \_let\_famfile=\_undefined \_famfrom={} \_doc ----------------------------- When the \^`\fontfam``[catalog]` is used then the file `fonts-catalog.opm` is read. The macro \^`\_faminfo` is redefined here in order to print catalog samples of all declared modifiers/variant pairs. The user can declare different samples and different behavior of the catalog, see the end of catalog listing for more information. The default parameters \`\catalogsample`, \`\catalogmathsample`, \`\catalogonly` and \`\catalogexclude` of the catalog are declared here. \_cod ----------------------------- \_newtoks \_catalogsample \_newtoks \_catalogmathsample \_newtoks \_catalogonly \_newtoks \_catalogexclude \_catalogsample={ABCDabcd Qsty fi fl áéíóúüů řžč ÁÉÍÓÚ ŘŽČ 0123456789} \_public \catalogonly \catalogexclude \catalogsample \catalogmathsample ; \_doc ----------------------------- The font features are managed in the \`\_fontfeatures` macro. It expands to \begitems * \`\_defaultfontfeatures` -- used for each font, * \`\_ffadded` -- features added by \^`\setff`, * \`\_ffcolor` -- features added by \^`\setfontcolor`, * \`\_ffletterspace` -- features added by \^`\setletterspace`, * \`\_ffwordspace` -- features added by \^`\setwordspace`. \enditems The macros \^`\_ffadded`, \^`\_ffcolor`, \^`\_ffletterspace`, \^`\_ffwordspace` are empty by default. \_cod ----------------------------- \_def \_fontfeatures{\_defaultfontfeatures\_ffadded\_ffcolor\_ffletterspace\_ffwordspace} \_def \_defaultfontfeatures {+tlig;} \_def \_ffadded{} \_def \_ffcolor{} \_def \_ffletterspace{} \_def \_ffwordspace{} \_doc ----------------------------- The \`\setff` `{}` adds next font features to \^`\_ffadded`. Usage \^`\setff{}` resets empty set of all \^`\_ffadded` features. \_cod ----------------------------- \_def \_setff #1{% \_ifx^#1^\_def\_ffadded{}\_else \_edef\_ffadded{\_ffadded #1;}\_fi \_reloading } \_public \setff ; \_doc ----------------------------- The \`\setfontcolor` and \`\setletterspace` are macros based on the special font features provided by \LuaTeX/ (and by \XeTeX/ too but it is not our business). The \`\setwordspace` recalculates the `\fontdimen2,3,4` of the font using the \`\setwsp` macro which is used by the \^`\_doresizeunifont` macro. It activates a dummy font feature `+Ws` too in order the font is reloded by the `\font` primitive (with independent `\fontdimen` registers). \_cod ----------------------------- \_def \_setfontcolor #1{% \_edef\_tmp{\_calculatefontcolor{#1}}% \_ifx\_tmp\_empty \_def\_ffcolor{}\_else \_edef\_ffcolor{color=\_tmp;}\_fi \_reloading } \_def \_setletterspace #1{% \_if^#1^\_def\_ffletterspace{}\_else \_edef\_ffletterspace{letterspace=#1;}\_fi \_reloading } \_def \_setwordspace #1{% \_if^#1^\_def\_setwsp##1{}\_def\_ffwordspace{}% \_else \_def\_setwsp{\_setwspA#1/}\_def\_ffwordspace{+Ws;}\_fi \_reloading } \_def\_setwsp #1{} \_def\_setwspA #1{\_ifx/#1\_ea\_setwspB \_else\_afterfi{\_setwspC#1}\_fi} \_def\_setwspB #1/#2/#3/#4{\_fontdimen2#4=#1\_fontdimen2#4% \_fontdimen3#4=#2\_fontdimen3#4\_fontdimen4#4=#3\_fontdimen4#4} \_def\_setwspC #1/{\_setwspB #1/#1/#1/} \_def\_calculatefontcolor#1{\_trycs{_fc:#1}{#1}} % you can define more smart macro ... \_sdef{_fc:red}{FF0000FF} \_sdef{_fc:green}{00FF00FF} \_sdef{_fc:blue}{0000FFFF} \_sdef{_fc:yellow}{FFFF00FF} \_sdef{_fc:cyan}{00FFFFFF} \_sdef{_fc:magenta}{FF00FFFF} \_sdef{_fc:white}{FFFFFFFF} \_sdef{_fc:grey}{00000080} \_sdef{_fc:lgrey}{00000025} \_sdef{_fc:black}{} % ... you can declare more colors... \_public \setfontcolor \setletterspace \setwordspace ; \_doc ----------------------------- \`\_regoptsizes` ` ? ` prepares data for using by the \`\_optname` `` macro. The data are saved to the `\_oz:` macro. When the `\_optname` is expanded then the data are scanned by the macro \`\_optnameA` `? `\code{<}`` in the loop.\nl \`\_optfontalias` `{ is undeclared in the current family" and nothing happens. But you can declare the same variant selector by \^`\famvardef` macro in the context of a new family. Then the same command may do different work depending on the current font family. Suppose that the selected font family provides the font modifier `\medium` for mediate weight of fonts. Then you can declare: \begtt \famvardef \mf {\medium\rm} \famvardef \mi {\medium\it} \endtt Now, you can use six independent variant selectors `\rm`, `\bf`, `\it`, `\bi`, `\mf` and `\mi` in the selected font family. A `\` can be written before `` in the `\famvardef` parameter. Then the `\` is declared in the current family but it can use fonts from another family represented by the `\`. When you are mixing fonts from more families then you probably run into a problem with incompatible ex-heights. This problem can be solved using \^`\setfontsize` and \^`\famvardef` macros: \begtt \fontfam[Heros] \fontfam[Termes] \def\exhcorr{\setfontsize{mag.88}} \famvardef\rmsans{\Heros\exhcorr\rm} \famvardef\itsans{\Heros\exhcorr\it} Compare ex-height of Termes \rmsans with Heros \rm and Termes. \endtt The variant selectors (declared by \~`\famvardef`) or font modifiers (declared by \~`\moddef`) are (typically) control sequences in user name space (`\mf`, `\caps`). They are most often declared in font family files and they are loaded by \^`\fontfam`. A conflict with such names in user namespace can be here. For example: if `\mf` is defined by a user and then `\fontfam[Roboto]` is used then `\famvardef\mf` is performed for Roboto family and the original meaning of `\mf` is lost. But \OpTeX/ prints warning about it. There are two cases: \begtt \def\mf{Metafont} \fontfam[Roboto] % warning: "The \mf is redefined by \famvardef" is printed or \fontfam[Roboto] \def\mf{Metafont} % \mf variant selector redefined by user, we suppose that \mf % is used only in the meaning of "Metafont" in the document. \endtt \secc[tt] The `\tt` variant selector \^`\tt` is an additional special variant selector which is defined as \"select typewriter font independently of the current font family". By default, the typewriter font-face from LatinModern font family is used. The \^`\tt` variant selector is used in \OpTeX/ internal macros \^`\_ttfont` (verbatim texts) and \^`\_urlfont` (printing URL's). You can redefine the behavior of `\tt` by \^`\famvardef`. For example: \begtt \fontfam[Cursor] \fontfam[Heros] \fontfam[Termes] \famvardef\tt{\Cursor\setff{-liga;-tlig}\rm} Test in Termes: {\tt text}. {\Heros\rm Test in Heros: {\tt text}}. Test in URL \url{http://something.org}. \endtt % You can see that `\tt` stay family independent. This is a special feature only for `\tt` selector. New definition is used in \^`\_ttfont` and \^`\_urlfont` too. It is recommended to use `\setff{-liga;-tlig}` to suppress the ligatures in typewriter fonts. If Unicode math font is loaded then the `\tt` macro selects typewriter font-face in math mode too. This face is selected from used Unicode math font and it is independent of `\famvardef\tt` declaration. \secc[fontmacros] Font commands defined by `\def` Such font commands can be used as fonts selectors for titles, footnotes, citations, etc. Users can define them. The following example shows how to define a \"title-font selector". Titles are not only bigger but they are typically in the bold variant. When a user puts `{\it...}` into the title text then he/she expects bold italic here, no normal italic. You can remember the great song by John Lennon \"Let It Be" and define: \begtt \def\titlefont{\setfontsize{at14pt}\bf \let\it\bi} ... {\titlefont Title in bold 14pt font and {\it bold 14pt italics} too} \endtt \OpTeX/ defines similar internal commands \^`\_titfont`, \^`\_chapfont`, \^`\_secfont` and \^`\_seccfont`, see section~\ref[sections]. The commands \^`\typosize` and \^`\boldify` are used in these macros. They set the math fonts to given size too and they are defined in section~\ref[opmac-fonts]. \secc[setff] Modifying font features %---------------------------- Each OTF font provides \"font features". You can list these font features by `otfinfo -f font.otf`. For example, LinLibertine fonts provide `frac` font feature. If it is active then fractions like 1/2 are printed in a special form. The font features are part of the font context data. The macro \^`\setff` `{}` acts like family independent font modifier and prepares a new . You must use a variant selector in order to reinitialize the font with the new font feature. For example \^`\setff``{+frac}\rm` or \^`\setff``{+frac}`\^`\currvar`. You can declare a new variant selector too: \begtt \fontfam[LinLibertine] \famvardef \fraclig {\setff{+frac}\currvar} Compare 1/2 or 1/10 \fraclig to 1/2 or 1/10. \endtt If the used font does not support the given font feature then the font is reloaded without warning nor error, silently. The font feature is not activated. The `onum` font feature (old-style digits) is connected to `\caps` macro for Caps+SmallCaps variant in \OpTeX/ font family files. So you need not create a new modifier, just use `{\caps`\^`\currvar`` 012345}`. \secc[specff] Special font modifiers %--------------------------- Despite the font modifiers declared in the font family file (and dependent on the font family), we have following font modifiers (independent of font family): \begtt \catcode`\<=13 \setfontsize{} % sets the font size \setff{} % adds the font feature \setfontcolor{} % sets font color \setletterspace{} % sets letter spacing \setwordspace{} % modifies word spacing \endtt The \^`\setfontsize` command is described in the section \ref[setfontsize]. The \^`\setff` command was described in previous subsection. \^`\setfontcolor` `{}` specifies the color and the opacity of the text. The parameter should be in the hexadecimal format of four bytes ``, for example `FF0080FF` means full red, zero green, half blue and full opacity. You can use names `red`, `green`, `blue`, `yellow`, `cyan`, `magenta`, `white`, `grey`, `lgrey` (without the backslash) instead of the hexadecimal specification. The empty parameter `` means default black color. These colors of fonts are implemented using \LuaTeX/ internal font feature. This is different approach than using colors in section \ref[colors]. \^`\setletterspace` `{}` specifies the letter spacing of the font. The `` is a decimal number without unit. The unit is supposed as 1/100 of the font size. I.e. `2.5` means 0.25 pt when the font is at 10 pt size. The empty parameter `` means no letter spacing which is the default. \^`\setwordspace` `{}` scales the default interword space (defined in the font) and its stretching and shrinking parameters by given `` factor. For example `\setwordspace{2.5}` multiplies interword space by 2.5. \^`\setwordspace` can use different multiplication factors if its parameter is in the format `{///}`. For example, `\setwordspace{/1/2.5/1}` enlarges only stretching 2.5~times. You can use `\setff` with other font features provided by Lua\TeX/ and `luaotfload` package (see documentation of `loaotfload` package for more information): \begtt \setff{embolden=1.5}\rm % font is bolder because outline has nonzero width \setff{slant=0.2}\rm % font is slanted by a linear transformation \setff{extend=1.2}\rm % font is extended by a linear transformation. \setff{colr=yes}\rm % if the font includes colored characters, use colors \setff{upper}\rm % to uppercase (lower=lowecase) conversion at font level \setff{fallback=name}\rm % use fonts from a list given by name if missing chars \endtt Use font transformations `embolden`, `slant`, `extend` and \^`\setletterspace`, \^`\setwordspace` with care. The best setting of these values is the default setting in every font, of course. If you really need to set a different letter spacing then it is strongly recommended to add `\setff{-liga}` to disable ligatures. And setting a positive letter spacing probably needs to scale interword spacing too. All mentioned font modifiers (except for `\setfontsize`) work only with Unicode fonts loaded by \^`\fontfam`. \secc[fontfamfiles] How to create the font family file %------------------------------------------------------ \printdoctail f-heros.opm \printdoctail f-lmfonts.opm \secc How to register the font family in the Font Selection System %--------------------------------------------------------------- \printdoctail fams-ini.opm \secc[exfont] Notices about extension of `\font` primitive %--------------------------------------------------------- Unicode fonts are loaded by extended `\font` primitive. This extension is not activated in \OpTeX/ by default, \^`\initunifonts` macro activates it. You need not use \^`\initunifonts` explicitly if \^`\fontfam` macro is used because \^`\fontfam` runs it internally. The \^`\initunifonts` loads the Lua code from the Luaotfload package which implements the `\font` primitive extension. See its documentation `luaotfload-latex.pdf` for information about all possibilities of extended `\font` primitive. The \OpTeX/ format is initialized by `luatex` engine by default but you can initialize it by `luahbtex` engine too. Then the harfbuzz library is ready to use for font rendering as an alternative to built-in font renderer from Luaotfload. The harfbuzz library gives more features for rendering Indic and Arabic scripts. But it is not used as default, you need to specify `mode=harf` in the fontfeatures field when `\font` is used. Moreover, when `mode=harf` is used, then you must specify `script` too. For example \begtt \font\devafont=[NotoSansDevanagari-Regular]:mode=harf;script=dev2 \endtt % If the `luahbtex` engine is not used then `mode=harf` is ignored. See Luaotfload documentation for more information. \endinput 2021-07-16 \initunifonts: optex_hook_into_luaotfload added. 2021-05-23 concept of \_fontfeatures macro re-implemented 2021-05-02 simpler \_resizefont, better concept of doc, moving parts from fonts-resize 2021-04-22 \_ffonum introduced 2021-04-19 \setwordspace: parameter format {/A/B/C} implemented. 2021-02-25 \_ttunifont introduced 2021-01-27 lua hack (print function) removed because luaotfload 3.17 removes bug. 2020-12-12 \_modlist added, doc improved 2020-04-18 \_tryloadfamslocal introduced \_fontdecl -> \_famdecl with different concept 2020-03-18 released