diff options
Diffstat (limited to 'macros/optex/base/fonts-select.opm')
-rw-r--r-- | macros/optex/base/fonts-select.opm | 314 |
1 files changed, 239 insertions, 75 deletions
diff --git a/macros/optex/base/fonts-select.opm b/macros/optex/base/fonts-select.opm index eab114fcc4..5dab510453 100644 --- a/macros/optex/base/fonts-select.opm +++ b/macros/optex/base/fonts-select.opm @@ -1,6 +1,131 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \fontfam {Fonts selection system <2021-04-22>} % preloaded in format +\_codedecl \fontfam {Fonts selection system <2021-05-23>} % preloaded in format + + \_doc ----------------------------- + The variant selectors \^`\rm`, \^`\bf`, \^`\it`, \^`\bi`, \^`\tt` + are defined (roughly speaking) by + \begtt \catcode`\<=13 + \def\<XX> {\_tryload<XX>\_ten<XX>} + \endtt + where <XX> 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 varinat 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<XX>` for `<XX>` in `rm`, `bf`, `it` and `bi`. + The \`\_loadf``{<XX>}\ten<XX>` 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 used + \~`\famvardef``\tt`. + \_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 explicitly specified variant selector. The current variant + is extracted from `\the\font` output which could be `\_ten<XX>` 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` `{<variant-name>}\<font switch>` 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 <font-switch>. + The <variant-name> is `rm` or `bf` or `it` or `bi` or `tt`. + The new <font-switch> is declared (roughly speaking) by: + \begtt \catcode`<=13 + \_font <font switch> = <fontname of>\_ten<variant-name> \_sizepec % in TFM mode + \_font <font switch> = {\_fontnamegen} \_sizespec % in OTF mode + \endtt + The font is loaded by \`\_doresizefont``<font switch>`. This macro has + meaning \`\_doresizetfmfont` in TFM mode (default in format) and it + switches to \^`\_doresizeunifont` when \^`\initunifonts` is used.\nl + The `<fontname of>` is generated by the `\fontname` \TeX/ primitive where + \`\_rfontskipat` removes the `at<dimen>` part of the `\fontname` output.\nl + The \`\_whatresize` is defined as `<variant-name>`.\nl + The \^`\_fontloaded``<font switch>` 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``<font-switch>` 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``<font switch>` is called immediately after it. If the font + is loaded first then its `\skewchar` is equal to $-1$. We run + \`\_newfontloaded``<font switch>` and set `\skewchar=-2` in this case. + A user can define a `\_newfontloaded` macro. We are sure that + `\_newfontloaded` macro is called only once for each instance of the font + given by its name, OTF features and size specification. The `\skewchar` value is + globally saved to the font (like `\fontdimen`). If it is used in math + typesetting then it is set to a positive value.\nl + The `\_newfontloaded` should be defined for micro-typographic configuration of + fonts, for example. 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, @@ -10,30 +135,25 @@ 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 + 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 if - `f-lmfonts.opm` (or another font file where `\tt` is declared) is not loaded. + \`\_ttunifont` is default font for `\tt` variant. + User can re-define it or use \^`\famvardef``\tt`. \_cod ----------------------------- \_def\_initunifonts {% - \directlua{% + \_directlua{% require('luaotfload-main') luaotfload.main() }% \_gdef\_rfskipatX ##1" ##2\_relax{"##1"}% \_global\_let \_doresizefont=\_doresizeunifont - \_gdef\_tryloadtt {\_fontdef\_tentt{\_let\_fontnamegen=\_ttunifont\_rm}}% + \_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 } -\_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 ; @@ -72,31 +192,6 @@ } \_doc ----------------------------- - \`\_regoptsizes` `<internal-template> <left-output>?<right-output> <resizing-data>` - prepares data for using by the \`\_optname` `<internal-template>` macro. - The data are saved to the `\_oz:<internal-template>` macro. - When the `\_optname` is expanded then the data are scanned by the macro - \`\_optnameA` `<left-output>?<right-output> <mid-output> `\code{<}`<size>` - in the loop.\nl - \`\_optfontalias` `{<template A>}{<template B>}` is defined as - `\let\_oz:<templateA>=\_oz:<templateB>`. - \_cod ----------------------------- - -\_def\_regoptsizes #1 #2?#3 #4*{\_sdef{_oz:#1}{#2?#3 #4* }} -\_def\_optname #1{\_ifcsname _oz:#1\_endcsname - \_ea\_ea\_ea \_optnameA \_csname _oz:#1\_ea\_endcsname - \_else \_failedoptname{#1}\_fi -} -\_def\_failedoptname #1{optname-fails:(#1)} -\_def\_optnameA #1?#2 #3 <#4 {\_ifx*#4#1#3#2\_else - \_ifdim\_optsize<#4pt #1#3#2\_optnameC - \_else \_afterfifi \_optnameA #1?#2 \_fi\_fi -} -\_def\_optnameC #1* {\_fi\_fi} -\_def\_afterfifi #1\_fi\_fi{\_fi\_fi #1} -\_def\_optfontalias #1#2{\_slet{_oz:#1}{_oz:#2}} - - \_doc ----------------------------- \`\_fvars` `<rm-template> <bf-template> <it-template> <bi-template>` saves data for usage by the `\_currV` macro. If a template is only dot then previous template is used (it can be used if the font family doesn't @@ -199,10 +294,40 @@ \_public \moddef ; \_doc ----------------------------- - The \`\famvardef` `\<XX> {<data>}` + \`\fontdef` `<font-switch> {<data>}` does: + \begtt \catcode`\<=13 + \begingroup <data> \ea\endgroup \ea\let \ea<font-switch> \the\font + \endtt + It means that font modifiers used in <data> are applied in the group and the + resulting selected font (current at the end of the group) is set to the + <font-switch>. + We want to declare <font-switch> in its real name directly by `\font` primitive in + order to save this name for reporting later (in overfull messages, for + example). This is the reason why \^`\_loadf` is re-defined locally here. + The <variant selector> used in <data> expands to `\_tryload<XX> \_ten<XX>`. + The modified `\_tryload<XX>` + removes `\_ten<XX>` and does `\_resizefont{<XX>}<font-swith><font-switch>`, + i.e.\ a font is loaded using real `<font-switch>` 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` `\<XX> {<data>}` does, roughly speaking: + \begtt \catcode`\<=13 + \def \<XX> {\fontdef\_ten<XX> {<data>}\_ten<XX>} + \endtt + but the macro `\<XX>` is declared as family-dependent. + So, the real \^`\famvardef` `\<XX> {<data>}` uses analogical trick like \^`\moddef` with - the \^`\_famdepend` macro. The auxiliary - \`\_famvardefA` `\<XX> \_ten<XX> \_tryload<XX> {<data>}` is used. + the \^`\_famdepend` macro. The \^`\famvardef` loads + the auxiliary \`\_famvardefA` `\<XX> \_ten<XX> \_tryload<XX> {<data>}`. It does: \begitems * `\def \_tryload:<currfam>:<XX> {`\^`\fontdef`` \_ten<XX> {<data>}}` loads font `\_ten<XX>`, @@ -213,6 +338,9 @@ `\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}% @@ -339,25 +467,34 @@ \_doc ----------------------------- The font features are managed in the \`\_fontfeatures` macro. - They have their implicit values saved in the \`\_defaultfontfeatures` - and the \`\setff` `{<features>}` - can add next font features. If there is the same font feature as the newly - added one then the old value is removed from the `\_fontfeatures` list. + 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` `{<features>}` adds next font features to \^`\_ffadded`. + Usage \^`\setff{}` resets empty set of all \^`\_ffadded` features. + \_cod ----------------------------- + \_def \_setff #1{% - \_ifx^#1^\_let \_fontfeatures=\_defaultfontfeatures - \_else \_edef\_fontfeatures{\_fontfeatures #1;}\_fi + \_ifx^#1^\_def\_ffadded{}\_else \_edef\_ffadded{\_ffadded #1;}\_fi \_reloading } -\_setff {} % default font features: +tlig; -\_def\_removefeature #1{% - \_isinlist\_fontfeatures{#1}\_iftrue - \_def\_tmp ##1#1##2;##3\_relax{\_def\_fontfeatures{##1##3}}% - \_ea \_tmp \_fontfeatures \_relax - \_fi -} \_public \setff ; \_doc ----------------------------- @@ -370,22 +507,18 @@ `\fontdimen` registers). \_cod ----------------------------- -\_def\_savedfontcolor{} -\_def\_savedletterspace{} -\_def\_savedwsp{} - -\_def \_setfontcolor #1{\_removefeature{color=}% - \_edef\_tmp{\_calculatefontcolor{#1}}% - \_ifx\_tmp\_empty \_else \_edef\_fontfeatures{\_fontfeatures color=\_tmp;}\_fi - \_reloading +\_def \_setfontcolor #1{% + \_edef\_tmp{\_calculatefontcolor{#1}}% + \_ifx\_tmp\_empty \_def\_ffcolor{}\_else \_edef\_ffcolor{color=\_tmp;}\_fi + \_reloading } -\_def \_setletterspace #1{\_removefeature{letterspace=}% - \_if^#1^\_else \_edef\_fontfeatures{\_fontfeatures letterspace=#1;}\_fi - \_reloading +\_def \_setletterspace #1{% + \_if^#1^\_def\_ffletterspace{}\_else \_edef\_ffletterspace{letterspace=#1;}\_fi + \_reloading } \_def \_setwordspace #1{% - \_if^#1^\_def\_setwsp##1{}\_removefeature{+Ws}% - \_else \_def\_setwsp{\_setwspA#1/}\_setff{+Ws}\_fi + \_if^#1^\_def\_setwsp##1{}\_def\_ffwordspace{}% + \_else \_def\_setwsp{\_setwspA#1/}\_def\_ffwordspace{+Ws;}\_fi \_reloading } \_def\_setwsp #1{} @@ -402,6 +535,33 @@ \_public \setfontcolor \setletterspace \setwordspace ; + \_doc ----------------------------- + \`\_regoptsizes` `<internal-template> <left-output>?<right-output> <resizing-data>` + prepares data for using by the \`\_optname` `<internal-template>` macro. + The data are saved to the `\_oz:<internal-template>` macro. + When the `\_optname` is expanded then the data are scanned by the macro + \`\_optnameA` `<left-output>?<right-output> <mid-output> `\code{<}`<size>` + in the loop.\nl + \`\_optfontalias` `{<template A>}{<template B>}` is defined as + `\let\_oz:<templateA>=\_oz:<templateB>`. + \_cod ----------------------------- + +\_def\_regoptsizes #1 #2?#3 #4*{\_sdef{_oz:#1}{#2?#3 #4* }} +\_def\_optname #1{\_ifcsname _oz:#1\_endcsname + \_ea\_ea\_ea \_optnameA \_csname _oz:#1\_ea\_endcsname + \_else \_failedoptname{#1}\_fi +} +\_def\_failedoptname #1{optname-fails:(#1)} +\_def\_optnameA #1?#2 #3 <#4 {\_ifx*#4#1#3#2\_else + \_ifdim\_optsize<#4pt #1#3#2\_optnameC + \_else \_afterfifi \_optnameA #1?#2 \_fi\_fi +} +\_def\_optnameC #1* {\_fi\_fi} +\_def\_afterfifi #1\_fi\_fi{\_fi\_fi #1} +\_def\_optfontalias #1#2{\_slet{_oz:#1}{_oz:#2}} + +\_setfontsize {at10pt} % default font size + \_endcode %--------------------------------------------------- @@ -532,7 +692,7 @@ family selectors and defined font macros doing something with fonts. * Font switches can be decared by `\font` primitive (see section~\ref[fontprimitive]) or by \^`\fontlet` command (see section~\ref[fontlet]) or by \~`\fontdef` command (see - sections~\ref[fontdef2] and~\ref[fontdef]). + sections~\ref[fontdef2]). When the font switches are used then they select the given font independently of the current font context. They can be used in `\output` routine (for example) because we need to set fixed fonts @@ -566,14 +726,19 @@ All declaration commands mentioned here: `\font`, `\fontlet`, `\fontdef`, `\famv \secc[fontdef2] The `\fontdef` declarator in detail -The general format for \^`\fontdef` usage is +You can declare `\<font-switch>` by the \^`\fontdef` command. \begtt \catcode`\<=13 -\fontdef\<font switch> {\<family selector> <font modifiers> \<variant selector>} +\fontdef\<font-switch> {\<family selector> <font modifiers> \<variant selector>} \endtt % where `\<family selector>` and `<font modifiers>` are optional and `\<variant selector>` is mandatory. +The resulting `\<font-switch>` declared by \~`\fontdef` is \"fixed font switch" +independent of the font context. More exactly, it is +a fixed font switch when it is {\em used}. But it can depend on the current font +modifiers and font family and given font modifiers when it is {\em declared}. + The \^`\fontdef` does the following steps. It pushes the current font context to a stack, it does modifications of the font context by given `\<family selector>` and/or `<font modifiers>` and it @@ -582,9 +747,6 @@ it is assigned to the declared `\<font switch>` (like `\font` primitive does it). Finally, `\fontdef` pops the font context stack, so the current font context is the same as it was before `\fontdef` is used. -More about `\fontdef` command including examples is written in -section~\ref[fontdef]. - \secc[famvardef] The `\famvardef` declarator @@ -596,8 +758,8 @@ macro has similar syntax as \^`\fontdef`: % where `\<family selector>` and `<font modifiers>` are optional and `\<variant selector>` is mandatory. -The `\<new variant selector>` should be used in the same sense as `\rm`, -`\bf` etc. It can be used as the final command in next +The `\<new variant selector>` declared by `\famvardef` should be used in the same +sense as `\rm`, `\bf` etc. It can be used as the final command in next \^`\fontdef` or \^`\famvardef` declarators too. When the `\<new variant selector>` is used in the normal text then it does the following steps: pushes current font context to a stack, modifies font @@ -848,6 +1010,8 @@ Luaotfload documentation for more information. \endinput +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 |