%% This is part of the OpTeX project, see http://petr.olsak.net/optex \_codedecl \setfontsize {Font resizing macros <2022-11-08>} % preloaded in format \_doc ----------------------------- \`\initunifonts` macro extends \LuaTeX's font capabilities, in order to be able to load Unicode fonts. Unfortunately, this part of \OpTeX/ depends on the `luaotfload` package, which adapts \ConTeXt's generic font loader for plain \TeX/ and \LaTeX. `luaotfload` uses Lua functions from \LaTeX's `luatexbase` namespace, we provide our own replacements. \^`\initunifonts` sets itself to relax because we don't want to do this work twice. \`\ufont` is a shortcut of \^`\initunifonts`~`\font`. \_cod ----------------------------- \_protected\_def \_initunifonts {% \_directlua{% require('luaotfload-main') luaotfload.main() optex.hook_into_luaotfload() }% \_glet \_fmodtt=\_unifmodtt % use \_ttunifont for \tt \_glet \_initunifonts=\_relax % we need not to do this work twice \_glet \initunifonts=\_relax } \_protected\_def \_ufont {\_initunifonts \_font} \_public \initunifonts \ufont ; \_doc ----------------------------- The \`\setfontsize` `{}` saves the `` to the \`\_sizespec` macro. The \`\_optsize` value is calculated from the ``. If the is in the format `scaled` then `\_optsize` is set from \`\defaultoptsize`. If the `` is in the `mag` format then the contents of the `\_sizespec` macro is re-calculated to the `at` format using previous `\_optsize` value. \par \goodbreak \_cod ----------------------------- \_newdimen \_optsize \_optsize=10pt \_newdimen \_defaultoptsize \_defaultoptsize=10pt \_newdimen\_lastmagsize \_def\_setfontsize #1{% \_edef\_sizespec{#1}% \_ea \_setoptsize \_sizespec\_relax } \_def\_setoptsize {\_isnextchar a{\_setoptsizeA} {\_isnextchar m{\_setoptsizeC}{\_setoptsizeB}}} \_def\_setoptsizeA at#1\_relax{\_optsize=#1\_relax\_lastmagsize=\_optsize} % at \_def\_setoptsizeB scaled#1\_relax{\_optsize=\_defaultoptsize\_relax} % scaled \_def\_setoptsizeC mag#1\_relax{% \_ifdim\_lastmagsize>\_zo \_optsize=\_lastmagsize \_else \_optsize=\_pdffontsize\_font \_fi \_optsize=#1\_optsize \_lastmagsize=\_optsize \_edef\_sizespec{at\_the\_optsize}% } \_public \setfontsize \defaultoptsize ; \_doc ----------------------------- The `\fontname` primitive returns the optionally followed by . The \`\xfontname` macro expands to without . We need to remove the part `at` from `\fontname` output. The letters `at` have category 12 in the \`\_stringat` macro. \_cod ----------------------------- \_edef\_stringat{\_string a\_string t} \_edef\_xfontname#1{\_unexpanded{\_ea\_xfontnameA\_fontname}#1 \_stringat\_relax} \_expanded{\_def\_noexpand\_xfontnameA#1 \_stringat#2\_relax}{#1} \_doc ----------------------------- \`\fontlet` ` ` does \begtt \catcode`\<=13 \font = {} \endtt Note, that the `\_xfontname` output is converted due to optical size data using `\_optfn`. \_cod ----------------------------- \_protected\_def \_fontlet #1#2{\_ifx #2=\_ea\_fontlet \_ea#1\_else \_ea\_font \_ea#1\_expanded{{\_optfn{\_xfontname#2}}}\_fi} \_public \xfontname \fontlet ; \_doc ----------------------------- \`\newcurrfontsize` `` does \^`\fontlet` `=\font \_relax `. It changes the current font at the given . \nl \`\resizethefont` is implemented by \^`\newcurrfontsize` using data from the \^`\_sizespec` macro.\nl \`\sfont` has the same syntax like `\font` primitive, but declares a macro which selects the font and sets its size properly dependent on the current size. \_cod ----------------------------- % \newcurrfontsize{at25pt} \_def \_newcurrfontsize {\_ea\_newcurrfontsizeA \_csname \_ea\_csstring \_the\_font \_endcsname} \_def \_newcurrfontsizeA #1#2{\_fontlet #1\_font #2\_relax \_fontloaded#1#1} \_protected\_def \_resizethefont {\_newcurrfontsize\_sizespec} \_protected\_def \_sfont #1{% \_protected\_edef #1{\_csname _sfont:\_csstring#1\_endcsname \_resizethefont}% \_initunifonts \_ea\_font \_csname _sfont:\_csstring#1\_endcsname } \_public \newcurrfontsize \resizethefont \sfont ; \_doc ----------------------------- The \`\_regtfm` ` ` registers optical sizes data directly by the font file names. This can be used for `tfm` files or OpenType files without various font features. See also \^`\_regoptsizes` in section~\ref[optsizes]. The `\_regtfm` command saves the concerned to the ``. The `` is in the form as shown below in the code where `\_regtfm` is used. \nl The \`\_optfn` `` expands to the `` or to the corrected `` read from the `` registered by `\_regtfm`. It is used in the \^`\fontlet` macro. The implementation detail: The `\_reg:` is defined as the `` and all control sequences `\_reg:` from this data line have the same meaning because of the \`\_reversetfm` macro. The `\_optfn` expands this data line and apply \`\_runoptfn`. This macro selects the right result from the data line by testing with the current `\_optsize` value. \_cod ----------------------------- \_def\_regtfm #1 0 #2 *{\_ea\_def \_csname _reg:#1\_endcsname{#2 16380 \_relax}% \_def\_tmpa{#1}\_reversetfm #2 * % } \_def\_reversetfm #1 #2 {% we need this data for \_setmathfamily \_ea\_let\_csname _reg:#1\_ea\_endcsname \_csname _reg:\_tmpa\_endcsname \_if*#2\_else \_ea\_reversetfm \_fi } \_def\_optfn #1{% \_ifcsname _reg:#1\_endcsname \_ea\_ea\_ea \_runoptfn \_csname _reg:#1\_ea\_endcsname \_else #1% \_fi } \_def\_runoptfn #1 #2 {% \_ifdim\_optsize<#2pt #1\_ea\_ignoretfm\_else \_ea\_runoptfn \_fi } \_def\_ignoretfm #1\_relax{} \_doc ----------------------------- Optical sizes data for preloaded 8bit Latin Modern fonts: \_cod ----------------------------- \_regtfm lmr 0 ec-lmr5 5.5 ec-lmr6 6.5 ec-lmr7 7.5 ec-lmr8 8.5 ec-lmr9 9.5 ec-lmr10 11.1 ec-lmr12 15 ec-lmr17 * \_regtfm lmbx 0 ec-lmbx5 5.5 ec-lmbx6 6.5 ec-lmbx7 7.5 ec-lmbx8 8.5 ec-lmbx9 9.5 ec-lmbx10 11.1 ec-lmbx12 * \_regtfm lmri 0 ec-lmri7 7.5 ec-lmri8 8.5 ec-lmri9 9.5 ec-lmri10 11.1 ec-lmri12 * \_regtfm lmtt 0 ec-lmtt8 8.5 ec-lmtt9 9.5 ec-lmtt10 11.1 ec-lmtt12 * \_endcode %--------------------------------------------------- \sec[fontprimitive] Using `\font` primitive directly %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% You can declare a new {\em font switch} by `\font` primitive: \begtt \catcode`\<=13 \font \ = % for example: \font \tipa = tipa10 at12pt % the font tipa10 at 12pt is loaded % usage: {\tipa TEXT} % the TEXT is printed in the loaded font. \endtt The can be empty or `at` or `scaled`. The must be terminated by space or surrounded in the braces. \OpTeX/ starts with `\font` primitive which is able to read only `tfm` files. i.e.\ the `.tfm` (and additional data for glyphs) must be correctly installed in your system. If you want to load OpenType `otf` or `ttf` font files, use the declarator \^`\initunifonts` before first `\font` primitive. This command adds additional features to the `\font` primitive which gives the extended syntax: \begtt \catcode`\<=13 \font \ = {[]:} % or \font \ = {:} \endtt where is name of the OpenType font file with the extension `.otf` or `.ttf` or without it. The braces in the syntax are optional, use them when the or includes spaces. The original syntax for `tfm` files is also available. Example: \begtt \initunifonts \font\crimson=[Crimson-Roman] at11pt % the font Crimson-Regular.otf is loaded \font\crimsonff=[Crimson-Roman]:+smcp;+onum at11pt % The same font is re-loaded % with font features {\crimson Text 12345} % normal text in Crimson-Regular {\crimsonff Text 12345} % Crimson-Regular with small capitals and old digits \endtt \^`\initunifonts` loads the implementation of the `\font` primitive from `luaotfload` package. More information is available in the `luaotfload-latex.pdf` file. You can use \^`\ufont` macro which runs \^`\initunifonts` followed by `\font` primitive. And \^`\fontfam` does (among other things) \^`\initunifonts` too. You need not to specify \^`\initunifonts` if \^`\fontfam` or \^`\ufont` is used. When \^`\initunifonts` is declared then the `\font` primitive is ready to read Type1 fonts too. If you have `file.afm` and `file.pfb` then you can declare `\font\f=file.afm` and use `\f`. It means that you needn't to create `tfm` files nor `vf` files, you can use Type1 fonts directly. They behave as Unicode fonts if the `afm` metrics are implemented correctly (with correct names of all included glyphs). But we must to say that Type1 font format is old technology, the loading of Type1 fonts is not optimized. Use OpenType fonts (`otf` of `ttf`) if it is possible. Let's sum it up. Suppose that \^`\initunifonts` was used. The `\font` primitive is able to load OpenType fonts (`otf` or `ttf`), Type1 fonts (`afm` and `pfb`) or classical `tfm` fonts. We strongly recommend to prefer OpenType format over Type1 format over `tfm` format. The last one doesn't support Unicode. If there is nothing else left and you must to use `tfm`, then you must to implement re-encoding from Unicode to the `tfm` encoding at macro level, see the \ulink[http://petr.olsak.net/optex/optex-tricks.html\#nonunicode]{\OpTeX/ trick 0018} for example. \secc[setfontsize] The `\setfontsize` macro It seems that you must decide about final size of the font before it is loaded by the `\font` primitive. It is not exactly true; \OpTeX/ offers powerful possibility to resize the font already loaded on demand. The \^`\setfontsize` `{}` saves the information about ``. This information is taken into account when a variant selector (for example `\rm`, `\bf`, `\it`, `\bi`) or `\resizethefont` is used. The `` can be: \begitems * `at`, for example `\setfontsize{at12pt}`. It gives the desired font size directly. * `scaled`, for example `\setfontsize{scaled1200}`. The font is scaled in respect to its native size (which is typically 10\,pt). It behaves like `\font\... scaled`. * `mag`, for example `\setfontsize{mag1.2}`. The font is scaled in respect to the current size of the fonts given by the previous \^`\setfontsize` command. \enditems The initial value in \OpTeX/ is given by `\setfontsize{at10pt}`. The \^`\resizethefont` resizes the currently selected font to the size given by previous \^`\setfontsize`. For example \begtt The 10 pt text is here, \setfontsize{at12pt} the 10 pt text is here unchanged... \resizethefont and the 12 pt text is here. \endtt % The \^`\setfontsize` command acts like {\em font modifier}. It means that it saves information about fonts but does not change the font actually until variant selector or \^`\resizethefont` is used. The following example demonstrates the `mag` format of \^`\setfontsize` parameter. It is only a curious example probably not used in practical typography. \begtt \def\smaller{\setfontsize{mag.9}\resizethefont} Text \smaller text \smaller text \smaller text. \endtt The \^`\resizethefont` works with arbitrary current font, for example with the font loaded directly by `\font` primitive. For example: \begtt \ufont\tencrimson=[Crimson-Roman]:+onum % font Crimson-Regular at 10 pt is loaded \def\crimson{\tencrimson\resizethefont} % \crimson uses the font size on demand \crimson The 10 pt text is here. \setfontsize{at12pt} \crimson The 12 pt text is here. \endtt This is not only an academical example. The `\csrimson` command defined here behaves like variant selector in the Font Selection System (section~\ref[fontsystem]). It takes only information about size from the font context, but it is sufficient. You can use it in titles, footnotes, etc. The font size depending on surrounding size is automatically selected. There is a shortcut \^`\sfont` with the same syntax like `\font` primitive, it declares a macro which selects the font and does resizing depending on the current size. So, the example above can be realized by `\sfont\crimson=[Crimson-Roman]:+onum`. \secc The `\font`-like commands summary \begitems * `\font` is \TeX/ primitive. When \OpTeX/ starts, then it accepts only classical \TeX/ syntax and doesn't allow to load Unicode fonts. Once \^`\initunifonts` (or \^`\fontfam`) is used, the `\font` primitive is re-initialized: now it accepts extended syntax and it is able to load Unicode OpenType fonts. * \^`\ufont` is a shortcut of `\initunifonts \font`. I.e.\ it behaves like `\font` and accepts extended syntax immediately. * \^`\sfont` has syntax like extended `\font`. It declares a macro which selects the given font and resizes it to the current size (given by \^`\setfontsize`). In various part of document (text, footnotes, titles), the size of this font is selected by the declared macro properly. \enditems \secc[fontlet] The \code{\\fontlet} declarator We have another command for scaling: \^`\fontlet` which can resize arbitrary font given by its font switch. \begtt \catcode`\<=13 \fontlet \ = \ example: \fontlet \bigfont = \_tenbf at15pt \endtt The `\` must be declared previously by `\font` or \^`\fontlet` or \~`\fontdef`. The `\` is declared as the same font at given . The equal sign in the syntax is optional. You can declare `\` as the scaled current font by \begtt \catcode`\<=13 \fontlet \ = \font \endtt \secc Optical sizes There are font families with more font files where almost the same font is implemented in various design sizes: `cmr5`, `cmr6`, `cmr7`, `cmr8`, `cmr9`, `cmr10`, `cmr12`, `cmr17` for example. This feature is called \"optical sizes". Each design size is implemented in its individual font file and \OpTeX/ is able to choose right file if various optical sizes and corresponding file names are declared for the font by \^`\_regtfm` or \^`\_regoptsizes` command. The command \^`\setfontsize` sets the internal requirements for optical size if the parameter is in the format `at` or `mag`. Then the command \^`\resizethefont` or \^`\fontlet` or variant selectors try to choose the font suitable for the required optical size. For example \begtt \fontfam[lm] The text is printed in font [lmroman10-regular] at 10 pt. \setfontsize{at13pt}\rm Now, the text is printed in [lmroman12-regular] at 13 pt. \endtt See also section~\ref[optsizes]. \secc Font rendering If \^`\initunifonts` isn't declared then \OpTeX/ uses classical font renderer (like in `pdftex`). The extended font renderer implemented in the Luaotfload package is started after \^`\initunifonts`. The \OpTeX/ format uses `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 2022-11-08 \sfont introduced, \protected: \initunifont, \ufont, \fontlet 2022-11-07 \fontlet \a\a: bug fixed 2022-10-14 \ufont introduced 2022-02-22 Font Selection System reimplemented, \fontsel introduced 2021-05-02 better concept of doc, moving parts to fonts-select 2021-04-17 \_fontloaded, \_newfontloaded introduced 2020-04-17 \resizethefont introduced 2020-03-17 released