%% This is part of the OpTeX project, see http://petr.olsak.net/optex \_famdecl [Heros] \Heros {TeX Gyre Heros fonts based on Helvetica} {\caps \cond} {\rm \bf \it \bi} {FiraMath} {[texgyreheros-regular]} {\_def\_fontnamegen{[texgyreheros\_condV-\_currV]:\_capsV\_fontfeatures}} \_wlog{\_detokenize{% Modifiers:^^J \caps ...... caps & small caps^^J \cond ...... condensed variants^^J }} \_moddef \resetmod {\_fsetV caps={},cond={} \_fvars regular bold italic bolditalic } \_moddef \caps {\_fsetV caps=+smcp;\_ffonum; } \_moddef \nocaps {\_fsetV caps={} } \_moddef \cond {\_fsetV cond=cn } \_moddef \nocond {\_fsetV cond={} } \_initfontfamily % new font family must be initialized \_ifmathloading \_loadmath {[FiraMath-Regular]} \_addUmathfont \_xits {[XITSMath-Regular]}{} {[XITSMath-Bold]}{} {} \_addto\_frak{\_fam\_xits}\_addto\_cal{\_fam\_xits} \_public \frak \cal ; % \bf, \bi from FiraMath: \_let\_bsansvariables=\_bfvariables \_let\_bsansGreek=\_bfGreek \_let\_bsansgreek=\_bfgreek \_let\_bsansdigits=\_bfdigits \_let\_bisansvariables=\_bivariables \_let\_bisansgreek=\_bigreek % \_resetmathchars ; \_mathchars \_xits {\bigtriangleup \bigblacktriangleup \blacktriangle \vartriangle \smallblacktriangleright \unicodevdots \unicodeadots \unicodeddots} % ... etc. you can add more \_fi \_endcode The font family file declares the font family for selecting fonts from this family at the arbitrary size and with various shapes. Unicode fonts (OTF) are preferred. The following example declares the Heros family: \printdoc f-heros.opm If you want to write such a font family file, you need to keep the following rules. \begitems * Use the \^`\_famdecl` command first. It has the following syntax: \begtt \catcode`\<=13 \_famdecl [] \ {} {} {} {} {} {\_def\_fontnamegen{}} \endtt This writes information about font family at the terminal and prevents loading such file twice. Moreover, it probes existence of `` in your system. If it doesn't exist, the file loading is skipped with a warning on the terminal. The \^`\_ifexistfam` macro returns false in this case. The \^`\_fontnamegen` macro must be defined in the last parameter of the \^`\_famdecl`. More about it is documented below. * You can use `\_wlog{\_detokenize{...` to write additional information into a log file. * You can declare optical sizes using \~`\_regoptsizes` if there are more font files with different optical sizes (like in Latin Modern). See `f-lmfonts.opm` file for more information about this special feature. * Declare font modifiers using \~`\moddef` if they are present. The \`\resetmod` must be declared in each font family. * Check if all your declared modifiers do not produce any space in horizontal mode. For example check: `X\caps Y`, the letters `XY` must be printed without any space. * Optionally, declare new variants by the \^`\famvardef` macro. * Run `\_initfontfamily` to start the family (it is mandatory). * If math font should be loaded, use `\_loadmath{}`. \enditems {\noindent \bf The \`\_fontnamegen` macro} (declared in the last parameter of the \^`\_famdecl`) must expand (at the expand processor level only) to a file name of the loaded font (or to its font name) and to optional font features appended. The Font Selection System uses this macro at the primitive level in the following sense: \begtt \catcode`\<=13 \font \ {\_fontnamegen} \_sizespec \endtt % Note that the extended `\font` syntax `\font\ {:} ` or `\font\ {[]:} ` is expected here. \seccc Example 1 Assume an abstract font family with fonts `xx-Regular.otf`, `xx-Bold.otf`, `xx-Italic.otf` and `xx-BoldItalic.otf`. Then you can declare the \^`\resetmod` (for initializing the family) by: \begtt \_moddef\resetmod{\_fvars Regular Bold Italic BoldItalic } \endtt and define the \^`\_fontnamegen` in the last parameter of the \^`\_famdecl` by: \begtt \_famdecl ... {\def\_fontnamegen{[xx-\_currV]}} \endtt The following auxiliary macros are used here: \begitems * \^`\moddef` declares the family dependent modifier. The \^`\resetmod` saves initial values for the family. * \^`\_fvars` saves four names to the memory, they are used by the \^`\_currV` macro. * \^`\_currV` expands to one of the four names dependent on `\rm` or `\bf` or `\it` or `\bi` variant is required. \enditems Assume that the user needs `\it` variant in this family. Then the `\_fontnamegen` macro expands to `[xx-\_currV]` and it expands to `[xx-Italic]`. The Font Selection System uses `\font {[xx-Italic]}`. This command loads the `xx-Italic.otf` font file. See more advanced examples are in `f-.opm` files. \seccc Example 2 The `f-heros.opm` is listed here. Look at it. When Heros family is selected and `\bf` is asked then `\font {[texgyreheros-bold]:+tlig;} at10pt` is processed. You can use any expandable macros or expandable primitives in the `\_fontnamegen` macro. The simple macros in our example with names `\_V` are preferred. They expand typically to their content. The macro \^`\_fsetV` `=` (terminated by a space) is equivalent to `\def\_V{}` and you can use it in font modifiers. You can use the \^`\_fsetV` macro in more general form: \begtt \catcode`\<=13 \_fsetV =,= ...etc. terminated by a space \endtt % with obvious result `\def\_V {}\def\_V {}` etc. \seccc Example 3 If both font modifiers `\caps`, `\cond` were applied in Heros family, then `\def\_capsV{+smcp;\_ffonum;}` and `\def\_condV{cn}` were processed by these font modifiers. If a user needs the `\bf` variant at 11\,pt now then the \begtt \font {[texgyreheroscn-bold]:+smcp;+onum;+pnum;+tlig;} at11pt \endtt % is processed. We assume that a font file `texgyreheroscn-bold.otf` is present in your \TeX/ system. \seccc The \code{\\_onlyif} macro has the syntax \^`\_onlyif` `=,,...: {}`. It can be used inside `\moddef` as simple IF statement: the `` is processed only if `` has `` or `` \dots or ``. See `f-roboto.opm` for examples of usage of many `\_onlyif`'s. Recommendation: use the \^`\_fontfeatures` macro at the end of the `\_fontnamegen` macro in order to the \^`\setff`, \^`\setfontcolor`, \^`\setletterspace` macros can work. \seccc The \code{\\moddef} macro has the syntax \^`\moddef\{}`. It does more things than simple `\_def`: \begitems * The modifier macros are defined as `\_protected`. * The modifier macros are defined as family-dependent. * If the declared control sequence is defined already (and it is not a font modifier) then it is re-defined with a warning. \enditems \noindent The \^`\famvardef` macro has the same features. \bigskip {\noindent\bf The `\`} is defined by the \^`\_famdecl` macro as: \begtt \catcode`<=13 \protected\def\ {% \_def\_currfamily {}% \_def\_fontnamegen {...}% this is copied from 7-th parameter of \_famdecl \resetmod \endtt {\noindent\bf The \^`\_initfontfamily`}\nl must be run after modifier's decaration. It runs the `\` and it runs `\_rm`, so the first font from the new family is loaded and it is ready to use it. \seccc Name conventions Create font modifiers, new variants, and the `\` only in public namespace without `_` prefix. We assume that if a user re-defines them then he/she needs not them, so we have no problems. If the user's definition was done before loading the font family file then it is re-defined and \OpTeX/ warns about it. See the end of section~\ref[fontcommands]. If you need to use an internal control sequence declared in your fontfile, use the reserved name space with names starting with two `_` followed by family identifier or by `vf` if it relates to variable fonts. The name of `\` should begin with an uppercase letter. Please, look at \ulink[http://petr.olsak.net/ftp/olsak/optex/op-catalog.pdf]{\OpTeX/ font catalogue} before you will create your font family file and use the same names for analogical font modifiers (like `\cond`, `\caps`, `\sans`, `\mono` etc.)\ and for extra variant selectors (like `\lf`, `\li`, `\kf`, `\ki` etc.\ used in Roboto font family). If you are using the same font modifier names to analogical font shapes then such modifiers are kept when the family is changed. For example: \begtt \fontfam [Termes] \fontfam[Heros] \caps\cond\it Caps+Cond italic in Heros \Termes\currvar Caps italic in Termes. \endtt % The family selector first resets all modifiers data by \^`\resetmod` and then it tries to run all currently used family-dependent modifiers before the family switching (without warnings if such modifier is unavailable in the new family). In this example, `\Termes` does `\resetmod` followed by `\caps\cond`. The `\caps` is applied and `\cond` is silently ignored in Termes family. If you need to declare your private modifier (because it is used in other modifiers or macros, for example), use the name `\_wordM`. You can be sure that such a name does not influence the private namespace used by \OpTeX/. \seccc Additional notes See the font family file `f-libertine-s.opm` which is another example where no font files but font names are used. See the font family file `f-lmfonts.opm` or `f-poltawski.opm` where you can find the the example of the optical sizes declaration including documentation about it. Several fonts don't switch to the font features if the features are specified directly as documented above. You must add the `script=latn;` specification to the features string when using these fonts, see `f-baskerville.opm` for example. The reason: these fonts don't follow the OpenType specification and they don't set the `DFLT` script but only scripts with given names like `latn`. And the tables implementing all font features are included here. You can check the internals of the font by FontForge: View / Show~ATT / OpenType Tables / GSUB. Do you see the `DFLT` script here? If you need to create a font family file with a non-Unicode font, you can do it. The `\_fontnamegen` must expand to the name of TFM file in this case. But we don't prefer such font family files, because they are usable only with languages with alphabet subset to ISO-8859-1 (Unicodes are equal to letter's codes of such alphabets), but middle or east Europe use languages where such a condition is not true.