diff options
Diffstat (limited to 'macros/luatex/optex/fonts-select.opm')
-rw-r--r-- | macros/luatex/optex/fonts-select.opm | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/macros/luatex/optex/fonts-select.opm b/macros/luatex/optex/fonts-select.opm new file mode 100644 index 0000000000..f9d6355639 --- /dev/null +++ b/macros/luatex/optex/fonts-select.opm @@ -0,0 +1,460 @@ +%% This is part of OpTeX project, see http://petr.olsak.net/optex + +\_codedecl \fontfam {Fonts selection system <2020-01-23>} + +\_def\_initunifonts {% + \_ea\_newcount \_csname e@alloc@attribute@count\_endcsname + \_global \_csname e@alloc@attribute@count\_endcsname=-1 + \_directlua{% + require("ltluatex") + require('luaotfload-main') local _void = luaotfload.main () + }% + \_gdef\_rfskipatX ##1" ##2\_relax{"##1"}% + \_gdef\_doresizefont ##1{\_logfont{##1}% + \_font##1=\_fontnamegen\_space \_sizespec \_relax}% + \_def \_fontnamegen{lmr10}% + \_global\_let\_initunifonts=\_relax % we need not to do this work twice +} +\_def\_fontdecl [#1]#2#3#4#5#6#7"#8"{% + \_initunifonts \_uniaccents + \_ifx #2\_undefined + \_isfont"#8"\_iffalse + \_opwarning{Family [#1] skipped, font "#7" not found}\_ea\_ea\_ea\_endinput \_else + \_def\_textfamily{#1}% + \_edef\_currfamily {\_xstring #2}% + \_def\_mainfamcommand{#2}% + \_wterm {FONT: [#1] -- \string#2 \_detokenize{(#3)^^J mods:{#4} vars:{#5} math:{#6}}}% + \_fi + \_else \_ea \_endinput \_fi +} +\_def\_regoptsizes #1 #2?#3 #4*{\_sdef{_optsizes:#1}{#2?#3 #4* }} +\_def\_optfontalias #1#2{\_slet{_optsizes:#1}{_optsizes:#2}} +\_def\_optname #1{\_ifcsname _optsizes:#1\_endcsname + \_ea\_ea\_ea \_optnameA \_csname _optsizes:#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} + +\_newifi \_ifexistfam +\_def\_isfont"#1"#2{% + \_begingroup + \_suppressfontnotfounderror=1 + \_font\_testfont="#1"\_relax + \_ifx\_testfont\_nullfont \_def\_tmp{\_existfamfalse \_unless} + \else \_def\_tmp{\_existfamtrue}\_fi + \_ea \_endgroup \_tmp #2% +} + +\_def\_fontfeatures{+tlig;} +\_def\_fvars #1 #2 #3 #4 {% + \_sdef{_fvar:rm}{#1}% + \_sdef{_fvar:bf}{#2}% + \_ifx.#2\_slet{_fvar:bf}{_fvar:rm}\_fi + \_sdef{_fvar:it}{#3}% + \_ifx.#3\_slet{_fvar:it}{_fvar:rm}\_fi + \_sdef{_fvar:bi}{#4}% + \_ifx.#4\_slet{_fvar:bi}{_fvar:it}\_fi +} +\_def\_currV{\_cs{_fvar:\_whatresize}} +\_def\_V{ } +\_def \_fsetV #1 {\_fsetVa #1,=,} +\_def \_fsetVa #1=#2,{\_isempty{#1}\_iffalse + \_ifx,#1\_else\_sdef{_#1V}{#2}\_ea\_ea\_ea\_fsetVa\_fi\_fi +} +\_def \_onlyif #1=#2:#3{% + \_edef\_act{\_noexpand\_isinlist{,#2,}{,\_cs{_#1V},}}\_act + \_iftrue #3\_fi +} +\_def \_moddef #1#2{\_edef\_tmp{\_xstring#1}\_remfirstunderscore\_tmp + \_sdef{_f:\_currfamily:\_tmp}{#2\_reloading}% + \_protected \_edef #1{\noexpand\_famdepend\noexpand#1{_f:\noexpand\_currfamily:\_tmp}}% + \_ea \_ifx \_csname\_tmp\_endcsname #1\_else + \_ea \_public \_csname\_tmp\_endcsname ;\_fi +} +\_protected \_def\_resetmod {\_cs{_f:\_currfamily:resetmod}} % private variant of \resetmod + +\_def\_famdepend#1#2{\_ifcsname#2\_endcsname \_csname#2\_ea\_endcsname \_else + \_opwarning{\string#1 is undeclared in current family "\_currfamily", ignored}\_fi +} +\_def\_famvardef#1{\_edef\_tmp{\_xstring#1}\_remfirstunderscore\_tmp + \_ea\_famvardefA \_ea#1\_csname _ten\_tmp\_ea\_endcsname + \_csname _tryload\_tmp\_ea\_endcsname \_csname \_tmp\_endcsname +} +\_def\_famvardefA #1#2#3#4#5{% #1=\_XX #2=\_tenXX #3=\_tryloadXX #4=\XX #5=data + \_isinlist{.\rm\bf\it\bi\currvar}#4\iftrue + \_opwarning{\string\famvardef: + You cannot re-declare standard variant selector \string#4}% + \_else + \_protected\_edef #1{\noexpand\_famdepend\noexpand#1{_f:\noexpand\_currfamily:\_tmp}}% + \_sdef{_f:\_currfamily:\_tmp}{#3#2}% + \_def#3{\_fontdef#2{\_reloading#5}}% + \_ifx#1\tt \addto#1{\_fam\_ttfam}\fi + \_sdef{_currvar:\xstring#2}{#1}% + \_ifx#1#4\_else \_public#4;\_fi + \_fi +} +\_def\_initfontfamily{% + \_mainfamcommand \_reloading \_rm +} +\def\_fontfam[#1]{% + \_lowercase{\_edef\_famname{\_ea\_removespaces #1 {} }}% + \_ifcsname _famf:\_famname\_endcsname \_edef\_famfile{\_cs{_famf:\_famname}}% + \_else \_edef\_famfile{f-\_famname}\_fi + \_ifx \_famfile\_empty \_listfamnames \_fi + \_isfile {f-\_famname.opm}\_iftrue + \_input "f-\_famname.opm"% + \_else \_isfile {fams-user.opm}\_iftrue \_input fams-user.opm \_fi + \_ifcsname _famf:\_famname\_endcsname \_edef\_famfile{\_cs{_famf:\_famname}}% + \_else \_edef\_famfile{f-\_famname}\_fi + \_isfile {\_famfile.opm}\_iftrue \_input "\_famfile.opm"% + \_else \_opwarning{Family [#1] undeclared, "\_famfile.opm" not found}% + \_fi \_fi \_relax +} +\_sdef{_famf:?}{} \_sdef{_famf:{} }{} +\_def\_listfamnames #1\_fi\_relax{\_fi + \_wterm{===== List of font families ======} + \_begingroup + \_let\_famtext=\_wterm + \_def\_faminfo [##1]##2##3##4{% + \_wterm{ \_space\_noexpand\_fontfam [##1] -- ##2}% + \_let\_famalias=\_famaliasA}% + \_input fams-ini.opm + \_isfile {fams-declared.opm}\_iftrue \_input fams-declared.opm \_fi + \_message{^^J}% + \_endgroup +} +\_def\_famaliasA{\_message{ \_space\_space\_space\_space -- alias:} + \_def\_famalias[##1]{\_message{[##1]}}\_famalias} + +\_def\_famtext #1{} +\_def\_faminfo [#1]#2#3#4{% + \_lowercase{\_edef\_famname{\_ea\_removespaces #1 {} }}% + \_sdef{_famf:\_famname}{#3}% + \_def\_famfile{#3}% +} +\_def\_famalias [#1]{% + \_lowercase{\_edef\_famname{\_ea\_removespaces #1 {} }}% + \_sdef{_famf:\_famname\_ea}\_ea{\_famfile}% +} +\_input fams-ini.opm +\_newtoks \_catalogsample +\_newtoks \_catalogonly +\_newtoks \_catalogexclude +\_catalogsample={ABCDabcd Qsty fi fl áéíóúüů řžč ÁÉÍÓÚ ŘŽČ 0123456789} + +\_public + \fontfam \isfont \famvardef \moddef \catalogonly \catalogexclude \catalogsample ; + +\_endcode %--------------------------------------------------- + + +\sec Usage of font selection system +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +Try to write `\fontfam[?]`. All font families registered in \OpTeX/ +font selection system are listed on the terminal and in the log file. +You can choose one of them and use for example `\fontfam[Termes]` or +`\fontfam[LM Fonts]`. Then you can use four basic variant selectors `\rm` or +or `\bf` or `\it` or `\bi` and desired fonts are printed. + +You can write `\fontfam[Catalog]` and all fonts registered in \OpTeX/ are +printed with their templates. + +The fonts registered in \OpTeX/ have their macros in "font files", each family +in one font file with the name `f-famname.opm`. All families are collected +in `fams-ini.opm`. You can read the documentation in the file `fams-ini.opm` +and in the files `f-heros.opm`, `f-lmfonts.opm` for more information how +to install and to register your own font family. Note that all families +registered in such files are Unicode fonts. Non-Unicode fonts are not +preferred in \OpTeX/ but you can use them using classical `\font` primitive, +of course. + +Each font family is connected with a preferred unicode-math font. This +unicode-math is activated when font family is loaded. If you don't prefer +this and you are satisfied with 8bit math CM+AMS fonts preloaded in the +\OpTeX/ format then you can use command `\noloadmath` before you load a first +font family. + +There are two equal possibilities how to load a font family: `\fontfam[Family]` +or `\input f-fontfamily.opm`. + +There are "main family command", "font modifiers" and "variant selectors" in +each family. Each family provides four variant selectors mentioned above +(may be, in few cases a missing variant is substituded by `\rm` or +`\it`). A few families provides more than these four variant selectors. + +Mostly all families provides "font modifiers" like `\caps`, `\light`, +`\cond`. Which font modifiers are provided is listed in terminal or in the +catalogue. A font modifier does nothing with current font, but the next +variant selectors select a modified font. You can combine more than one +font modifiers followed by a variant selector. The font is reloaded at the +moment when variant selector is in its process. The following example +supposes that we are working with a font family where `\caps` and `\cond` +font modifiers are provided. + +\begtt +\rm normal font, \bf bold, \it italic. +\cond\currvar now condensed italics is active, +\rm condensed normal, \bf condensed bold. +\caps\rm condensed caps and small caps variant is used in regular variant +\bi condensed caps and small caps variant is used in bold-italic variant. +\resetmod\rm using the `\resetmod` font modifier we can return to +the normal state when no font modifier is active. +\endtt + +Of course, all font settings respect groups. The font modifiers keeps their +context until the group is closed or until another font modifier (which +negates previous setting) is used. In our example these two selectors are +independent, so there are four variants: normal, condensed, caps and +caps-condensed, all these variants are present in four standard +variants: regular, bold, italics, bold-italics. + +There is one special command `\currvar` which respects the current +variant and the font of such variant is reloaded with respect to previously +given font modifiers. + +You can use the `\setfontsize{<sizespec>}` command in the same sense as +other font modifiers. It means that the command itself does nothing with the +fonts but following variant selectors reload fonts to desired size. For +example: + +\begtt +\rm standard size \setfontsize{at14pt}\rm here is 14pt size \it italic is +in 14pt size too \bf bold too. +\endtt + +Note that much more comfortable is to resize fonts using OPmac-like command +`\typosize`, `\typoscale`. These commands prepare the right sizes for math +fonts too and re-calculates many internal parameters like `\baselineskip`. See +`opmac-fonts.opm` file for more information. + + +\secc More than one font families loaded +%--------------------------------------- + +You can load more font families. Then you must to know the context (what +family is currently in use) and you can switch between families using main +family comand. For example, when Heros and Termes are loaded then: + +\begtt +\rm here is Termes because it is loaded last, \it italics in Termes but +\Heros \rm here is Heros font \it italics is in Heros too. +\endtt + +Summary: To select a font you can use (in this order): + +\begtt +\<main-family-command> \<font-modifiers> \<variant-selector-or-currvar> +\endtt + +You can use zero or more font modifiers, the `\setfontsize` command is a +font modifier too. Finally, the variant selector or `\currvar` loads +the desired font. + +The font modifiers (with an exception `\setfontsize`) are declared localy in +their font family as "family dependent". If you use it in the context of +another font family where it is not declared then warning is printed on the +terminal and nothing else happens. It is possible (and it is typical) that a +modifier with the same name is declared in more font families. Then such +modifiers are working in context of current used family. For example +`\LMfonts\caps\rm` or `\Termes\caps\rm` both loads small caps in specified +font family using different internal definitions. + +Maybe, one needs a context switching between `\rm`<-->`\bf` and +`\it`<-->`\bi`. This is done by `\em` macro, see opmac-fonts.ofm. + + +\secc Defining a font commands +%----------------------------- + +You can define your own font selectors as a combination of font modifiers +followed by a font selector or by `\currvar` command. + +You can declare a "font switch" like `\font` primitive does it, +but you need not to know nothing about names of font files: + +\begtt +\fontdef \newswitch {<font-modifiers> <variant-selector>} +for example +\fontdef \titlefont {\setfontsize{at14pt}\bf} +\endtt + +This example declares \title as a font switch: it selects the bold font at +14pt and other not mentioned parameters (font family and font modifiers) are +taken from outside context when `\fontdef` is in process. +The result is a "definitive" font switch (internaly declared by `\font` primitive) +which does not respect any other current context when it is used. It means: + +\begtt +\sizespec{at8pt}\rm small roman font \titlefont bold big font \it italics +small font. +\endtt + +Such font switches sould be used in `\output` routine (headers, footers) for +example. But it should be less usable in common text. For example when +`\titlefont` defined above is used for titles, you cannot change a font +variant (to `\it`, for example). So, better idea to declare a "title font" +is to use normal `\def` instead `\fontdef` + +\begtt +\def\titlefont{\setfontsize{at14pt}\bf \let\it\bi} % Let it be (John Lennon) +... +{\titlefont here we have bold 14pt font and {\it here} was bold 14pt italics} +\endtt + +There are four standard variant selectors, but you can declare new variant +selector by `\famvardef` command: + +\begtt +\famvardef \selector {<font-modifiers> <variant-selector>} +\endtt + +If such `\selector` is used, then it takes the current context of font family and +font modifiers, opens a group, locally adds the defined font modifiers, +applies variant selector (loads the font now), closes the group but keeps +the selected font and use it. Moreover, such `\selector` is declared as +family-dependent in the same sense as font modifiers. + +You can use `\isfont "<fontname>"\iftrue` or `\isfont "<fontname>"\iffalse` +to test if the specified font is present in your system. + + +\secc Example of modifying font features +%--------------------------------------- + +Each OTF fionts 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 +fonrm. + +If you need to activate or deactivate a font feature then you must to +re-load the font with new collection of features. Actual collection of +features are stored in `\_fontfeatures` macro. The features are separated by +semicolon and prefixed by `+` (to activate it) or `-` (to deactivate it). +If you want to print fractions in LinLibertine create a font modifier using +`\moddef` of variant selector using `\famvardef`: + +\begtt + \fontfam[LinLibertine] + \moddef \fracmod {\addto\_fontfeatures{+frac;}} + {Compare 1/2 or 1/10 \fracmod\currvar to 1/2 or 1/10.} + or: + \famvardef \fraclig {\addto\_fontfeatures{+frac;}\currvar} + {Compare 1/2 or 1/10 \fraclig to 1/2 or 1/10.} +\endtt + +The `onum` font feature (old style digits) is connected to `\caps` macro for +Caps+SmallCaps variant in \OpTeX/ font-definition-files. So you need not to +create a new modifier, just use `{\caps\currvar 012345}`. + + +\secc Example of usage more vaiants +%---------------------------------- + +Suppose we have load Heros family where \cond font modifier is declared. +Then you can define: + +\begtt + \famvardef \rmcond {\cond\rm} + \famvardef \bfcond {\cond\bf} + \famvardef \itcond {\cond\it} + \famvardef \bicond {\cond\bi} +\endtt + +Now, you can select between eight variants. But the context between similar +variants like `\bf`--`\bfcond` is lost. Maybe you will find more usefull to +create only a two cond--nocond swithers which respect the current variant. +And use only four standard variant selectors: + +\begtt + \def\useCond {\cond\currvar} \def\useNormal {\nocond\currvar} + \Heros\rm + here is rm-normal \bf here is bold-normal \useCond here is bold-condensed + \it here is italics-condensed \useNormal here is italics-normal. +\endtt + + +\secc Example of usage more than one family +%------------------------------------------ + +Supose we have load Termes and Heros families. Then you can define + +\begtt + \def\useTermes {\Termes\currvar} % switch to Termes with respect current variant + \def\useHeros {\Heros\currvar} % switch to Heros with respect curent variant +\endtt + +Or you can declare fonts-like macros: + +\begtt + \fontdef \titlefont {\setfontsize{at14pt}\Heros\bf} + \times\rm ..... normal text in Times + \titlefont .... Titles in Heros. +\endtt + +If you are mixing fonts from various font families then the ex height can +be different and optical unfit. You can compensate exheight of such fonts +for example by: + +\begtt + \Termes + \famvardef \sansfont {\setfontsize{mag.9}\Heros\currvar} + \rm here is text in Termes \sansfont and text in Heros with compatible ex-height. +\endtt + + +\secc Fontfam processing in detail +%-----------------------/--------- + +The `\fontfam` macro lists all declared families if parameter is empty or +`?`. If not, then `\fontfam` transforms the given parameter to lowercase and +without spaces. If exists the file `f-<parameter>.opm` then it is read. If +does not exists such file then `\fontfam` internally lists the families +declared by `\_faminfo` and `\_famalias`, firstly from `fams-ini.opm` file +and secondly from `fams-user.opm` (if such file exists). The last +declaration from this internal list (which mathes the given <parameter>) +wins. If the parameter does not match then font-macro-file is not found and +the warning is printed and no new family is loaded. + +When the font-macro-file is found, then `\fontfam` tries an existence of fonts in the +system. If they does not exist, a warning on the terminal is printed and no +family is loaded. + +Note, that `fams-user.opm` has higher precedence that internal +`fams-ini.file`. You can declare families with the same name as internal +names and your declaration wins. + + +\secc Implementation notes +%------------------------- + +TODO ... + +The family-dependend macros are declared by \moddef and \famvardef. The +following trick is used: + +\begtt + \protected\def\macro{\_famdepend\macro{_f:\_currfamily:macro}}% + \sdef{_f:currfamily:macro}{... definition body ...}% +\endtt + +The `\_famdepend\macro{csname}` runs `\csname` if it is defined else it writes +a warning. + +If you want to declare macros wit the same feature but wit a parameter, for +example, you have to do: + +\begtt + \protected\def\macro{\famdepend\macro{_f:\_currfamily:macro}}% + \sdef{_f:currfamily:macro}#1{... definition body ...}% +\endtt + +Of course, you must to do some `\edef...\noexpand` tricks but this is an +implementation detail. + |