%% This is part of the OpTeX project, see http://petr.olsak.net/optex \_codedecl \fontfam {Fonts selection system <2021-02-25>} % preloaded in format \_doc ----------------------------- \`\initunifonts` macro extends \LuaTeX's font capabalities, in order to be able to load Unicode fonts. Unfortunately, this part of \OpTeX/ depends on `luaotfload` package, which adapts Con\TeX/t's generic font loader for plain \TeX/ and \LaTeX. `luaotfload` uses Lua functions from \LaTeX's `luatexbase` namespace, we provide our own replacements. Moreover, `\initunifont` switches with the \^`\_doresizefont` macro to OTF mode which is represented by the macro \`\_doresizeunifont`. This mode includes a fallback to TFM mode if \^`\_fontnamegen` is not defined. Finally, `\initunifonts` sets itself to relax because we don't want to do this work twice.\nl \`\_ttunifont` is default font for `\tt` variant if `f-lmfonts.opm` (or another font file where `\tt` is declared) is not loaded. \_cod ----------------------------- \_def\_initunifonts {% \directlua{% require('luaotfload-main') luaotfload.main() }% \_gdef\_rfskipatX ##1" ##2\_relax{"##1"}% \_global\_let \_doresizefont=\_doresizeunifont \_gdef\_tryloadtt {\_fontdef\_tentt{\_let\_fontnamegen=\_ttunifont\_rm}}% \_global\_let \_initunifonts=\_relax % we need not to do this work twice \_global\_let \initunifonts=\_relax } \_gdef\_doresizeunifont #1{\_logfont{#1}% \_ifx\_fontnamegen\_undefined \_doresizetfmfont#1\_else \_font#1={\_fontnamegen} \_sizespec \_relax \_setwsp#1\_relax \_fi } \_def\_ttunifont{[lmmono10-regular]:\_fontfeatures-tlig;} \_public \initunifonts ; \_doc ----------------------------- The \`\_famdecl` `[] \ {} {} {} {}`\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 actual meaning of the \^`\_fontnamegen` macro. The \`\_mathfaminfo` is saved for usage in the catalog. \_cod ----------------------------- \_def\_famdecl [#1]#2#3#4#5#6#7#8{% \_initunifonts \_uniaccents \_unless\_ifcsname _f:\_csstring#2:main.fam\_endcsname \_isfont{#7}\_iffalse \_opwarning{Family [#1] skipped, font "#7" not found}\_ea\_ea\_ea\_endinput \_else \_edef\_currfamily {\_csstring #2}\_def\_mathfaminfo{#6}% \_wterm {FONT: [#1] -- \_string#2 \_detokenize{(#3)^^J mods:{#4} vars:{#5} math:{#6}}}% \_unless \_ifx #2\_undefined \_opwarning{\_string#2 is redefined by \_string\_famdecl\_space[#1]}\_fi \_protected\_edef#2{\_def\_noexpand\_currfamily{\_csstring #2}\_unexpanded{#8\_resetfam}}% \_ea \_let \_csname _f:\_currfamily:main.fam\_endcsname =#2% \_fi \_else \_csname _f:\_csstring#2:main.fam\_endcsname \_reloading \_rm \_ea \_endinput \_fi } \_def\_initfontfamily{% \_csname _f:\_currfamily:main.fam\_endcsname \_reloading \_rm } \_doc ----------------------------- \`\_regoptsizes` ` ? ` 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. If you need another font transformations, you can use `\setff` with following font features provided by Lua\TeX/: \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 \endtt Use font transformations mentioned above and \^`\setletterspace`, \^`\setwordspace` with care. The best setting of these values is the default setting in every font, of course. If you really need to set a different letter spacing then it is strongly recommended to add `\setff{-liga}` to disable ligatures. And setting a positive letter spacing probably needs to scale interword spacing too. All mentioned font modifiers (except for `\setfontsize`) work only with Unicode fonts loaded by \^`\fontfam`. \secc[fontfamfiles] How to create the font family file %------------------------------------------------------ \printdoctail f-heros.opm \printdoctail f-lmfonts.opm \secc How to register the font family in the Font Selection System %--------------------------------------------------------------- \printdoctail fams-ini.opm \secc[exfont] Notices about extension of `\font` primitive %--------------------------------------------------------- Unicode fonts are loaded by extended `\font` primitive. This extension is not activated in \OpTeX/ by default, \^`\initunifonts` macro activates it. You need not use \^`\initunifonts` explicitly if \^`\fontfam` macro is used because \^`\fontfam` runs it internally. The \^`\initunifonts` loads the Lua code from the Luaotfload package which implements the `\font` primitive extension. See its documentation `luaotfload-latex.pdf` for information about all possibilities of extended `\font` primitive. The \OpTeX/ format is initialized by `luatex` engine by default but you can initialize it by `luahbtex` engine too. Then the harfbuzz library is ready to use for font rendering as an alternative to build-in font renderer from Luaotfload. The harfbuzz library gives more features for rendering Indic and Arabic scripts. But it is not used as default, you need to specify `mode=harf` in the fontfeatures field when `\font` is used. Moreover, when `mode=harf` is used, then you must specify `script` too. For example \begtt \font\devafont=[NotoSansDevanagari-Regular]:mode=harf;script=dev2 \endtt % If the `luahbtex` engine is not used then `mode=harf` is ignored. See Luaotfload documentation for more information. \endinput 2021-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