summaryrefslogtreecommitdiff
path: root/macros/optex/base/fonts-select.opm
diff options
context:
space:
mode:
Diffstat (limited to 'macros/optex/base/fonts-select.opm')
-rw-r--r--macros/optex/base/fonts-select.opm314
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