%D \module %D [ file=font-mat, %D version=2011.01.13, % (copied fron font-ini) %D title=\CONTEXT\ Font Macros, %D subtitle=Math, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \writestatus{loading}{ConTeXt Font Macros / Math} \unprotect %D The original (\MKIV) approach to bidi is that we have two extra families for %D regular, bold and pseudobold: %D %D regular normal=0 l2r=1 r2l=2 %D bold normal=3 l2r=4 r2l=5 %D pseudobold normal=6 l2r=7 r2l=8 %D %D where l2r is just an alias. Because we're now using the mirror lookup (like %D we do a smaller lookup) in the engine we not just have: %D %D regular normal=0 %D bold normal=3 %D pseudobold normal=6 %D %D And when one can wonder if pseudobold is needed (just bolden); we can then %D actually go down to only two families. It is one of these cases when it hurts %D to throw away a nice old mechanism that worked quite well so here we keep it %D commented. For what it's worth: this variant switches a bit faster too and %D produces less logging but I doubt if anyone will notice that. %D We now have bidi handled via a tweak in the goodie file which means that we %D could simplify the implementation and get rid of the (four) extra families %D needed. For now we retain the zero/three designation for mr/mb but that might %D go away. Actually we could drop the number of families in the engine to sixteen %D again or even four if we need the space for more classes or something else. %D Be nice: \ifdefined\??fontinstanceready \else \installcorenamespace{fontinstanceready} \fi \ifdefined\??fontinstancebasic \else \installcorenamespace{fontinstancebasic} \fi \ifdefined\??fontinstanceclass \else \installcorenamespace{fontinstanceclass} \fi %D The order 3 2 1 of size matters is historic and was needed for math-fbk relative %D size storage! It is no longer relevant. %D \macros %D {textonly} %D %D Traditionally math has a big impact on font definitions, mainly because we need %D to define alphabet variants using families and fonts. This means that one can %D easily get 10 fonts loaded per math size. In \MKIV\ we use a different approach: %D one family which has either a virtual font made of traditional fonts, or an %D \OPENTYPE\ font that has it all. %D %D We currently use only one math family but in the future we might consider using a %D second one for bold math. For the moment we keep the \MKII\ method of using a %D token register for definitions but we already dropped the text and symbols ones %D since they now live in the same family. When we go always compact we can simplify %D the code even more. For previous implementations see the \MKIV\ code and the %D repository pre October 2022. \newtoks \t_font_math_strategies \newconditional\c_font_synchronize_math_fonts \settrue\c_font_synchronize_math_fonts \protected\def\font_helpers_synchronize_math % math stuff in mmode {\ifconditional\c_font_synchronize_math_fonts\the\t_font_math_strategies\fi} \permanent\protected\def\textonly{\setfalse\c_font_synchronize_math_fonts} % document this %D The main math font definer. We have removed some optimized code simply because we %D now always have a fontclass. We could check for fontclass being default or empty %D and save a few tests but it does not help us when no math is defined. %D %D Because we want to keep mr=.. and mb=... settings (read: not break downward %D compatibility by enforcing mrlr etc) we need a bit more code that optimal. \aliased\let\c_font_fam_mr\zerocount % math regular \aliased\let\c_font_fam_mb\plusthree % math bold \definesystemattribute[mathfamily][public] % when we are always true we can as well remove this test: \newconditional\c_font_complete_bold_mathstrategy \settrue\c_font_complete_bold_mathstrategy \immutable\def\mathtextsuffix {-text} \immutable\def\mathscriptsuffix {-script} \immutable\def\mathscriptscriptsuffix{-scriptscript} %D Beware: truefontname also does a fallback on defaultfontclass so there can be %D some interference here, which is why we use a different method for bold. \def\font_helpers_set_math_family_a {\ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size \lastnamedcs \orelse \ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size \lastnamedcs \else \font_helpers_set_math_family_b \fi} \def\font_helpers_set_math_family_b {\ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size \lastnamedcs \orelse \ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size \lastnamedcs \else \font_helpers_set_math_family_c \fi} \def\font_helpers_set_math_family_c {\ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size \lastnamedcs \orelse \ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size \lastnamedcs \else \settrue \c_font_auto_size \fi} \mutable\lettonothing\mathsizesuffix \mutable\let\fontfamily\relax % for now public but it is a helper \newcount \c_math_last_family_used \def\font_helpers_set_math_family_indeed_normal#mrtag#family% \fontface etc are also used later on {\let\savedfontbody\fontbody \let\fontfamily#family% \c_math_last_family_used\zerocount % the order is important as we depend on known id's when completing fonts % enabling is needed when we have fallbacks which spoils the families; per % mid 2022 this is no longer true as we do fallbacks differently \let\mathsizesuffix\mathscriptscriptsuffix \let\fontface\!!plusthree \font_helpers_set_math_family_a\scriptscriptfont#mrtag\font % defines \font_helpers_set_math_family_a\scriptscriptfont#mrtag\font % enables / still needed ? \let\mathsizesuffix\mathscriptsuffix \let\fontface\!!plustwo \font_helpers_set_math_family_a\scriptfont #mrtag\font % defines \font_helpers_set_math_family_a\scriptfont #mrtag\font % enables / still needed ? \let\mathsizesuffix\mathtextsuffix \let\fontface\!!plusone \font_helpers_set_math_family_a\textfont #mrtag\font % defines \font_helpers_set_math_family_a\textfont #mrtag\font % enables / still needed ? \lettonothing\mathsizesuffix \let\fontface\!!zerocount \let\fontbody\savedfontbody \setfalse\c_font_auto_size} \def\font_helpers_set_math_family_set_scales_compact {% these are used when no font setting is there, the settings come before setting the parameters % and are stored with the family ... this is not really needed because the size is used otherwise \glyphtextscale \plusthousand \glyphscriptscale \numexpr\plusthousand*\dimexpr\scriptface \relax/\dimexpr\textface\relax\relax \glyphscriptscriptscale \numexpr\plusthousand*\dimexpr\scriptscriptface\relax/\dimexpr\textface\relax\relax} \def\font_helpers_set_math_family_set_scales_normal {\glyphtextscale \plusthousand \glyphscriptscale \plusthousand \glyphscriptscriptscale\plusthousand} \def\font_helpers_set_math_family_indeed_compact#mrtag#family% \fontface etc are also used later on {\let\savedfontbody\fontbody \let\fontfamily#family% \c_math_last_family_used\zerocount \font_helpers_set_math_family_set_scales_compact % the order is important as we depend on known id's when completing fonts % enabling is needed when we have fallbacks which spoils the families \let\mathsizesuffix\mathtextsuffix \let\fontface\!!plusone \font_helpers_set_math_family_a\textfont #mrtag\font % defines \font_helpers_set_math_family_a\textfont #mrtag\font % enables / still needed ? \scriptfont #mrtag\font % reuses \scriptscriptfont#mrtag\font % reuses \lettonothing\mathsizesuffix \let\fontface\!!zerocount \let\fontbody\savedfontbody \setfalse\c_font_auto_size} \def\font_helpers_set_math_family_indeed {\ifconditional\c_font_compact \expandafter\font_helpers_set_math_family_indeed_compact \else \expandafter\font_helpers_set_math_family_indeed_normal \fi} \def\font_helpers_set_math_family_bold_indeed_normal#mbfam#familytag#mrfam% \c_font_fam_mb \s!mb \c_font_fam_mr {\let\savedfontclass\defaultfontclass \let\defaultfontclass\fontclass % else truefontname falls back on the wrong one \let\savedfontbody\fontbody \let\fontfamily#familytag% \c_math_last_family_used\zerocount \font_helpers_set_math_family_set_scales_normal \let\mathsizesuffix\mathscriptscriptsuffix \let\fontface\!!plusthree \font_helpers_set_math_family_bold_a\scriptscriptfont#mbfam#mrfam% defines \font_helpers_set_math_family_bold_a\scriptscriptfont#mbfam#mrfam% enables / still needed ? \let\mathsizesuffix\mathscriptsuffix \let\fontface\!!plustwo \font_helpers_set_math_family_bold_a\scriptfont #mbfam#mrfam% defines \font_helpers_set_math_family_bold_a\scriptfont #mbfam#mrfam% enables / still needed ? \let\mathsizesuffix\mathtextsuffix \let\fontface\!!plusone \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam% defines \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam% enables / still needed ? \lettonothing\mathsizesuffix \let\fontface\!!zerocount \let\fontbody\savedfontbody \let\defaultfontclass\savedfontclass \setfalse\c_font_auto_size} \def\font_helpers_set_math_family_bold_indeed_compact#mbfam#familytag#mrfam% \c_font_fam_mb \s!mb \c_font_fam_mr {\let\savedfontclass\defaultfontclass \let\defaultfontclass\fontclass % else truefontname falls back on the wrong one \let\savedfontbody\fontbody \let\fontfamily#familytag% \c_math_last_family_used\zerocount \let\mathsizesuffix\mathtextsuffix \let\fontface\!!plusone \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam% defines \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam% enables / still needed ? \scriptfont #mbfam\textfont#mbfam% reuses \scriptscriptfont#mbfam\textfont#mbfam% reuses \lettonothing\mathsizesuffix \let\fontface\!!zerocount \let\fontbody\savedfontbody \let\defaultfontclass\savedfontclass \setfalse\c_font_auto_size} \def\font_helpers_set_math_family_bold_indeed {\ifconditional\c_font_compact \expandafter\font_helpers_set_math_family_bold_indeed_compact \else \expandafter\font_helpers_set_math_family_bold_indeed_normal \fi} \def\font_helpers_set_math_family_bold_a#font#mbfam#mrfam% {\ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size \lastnamedcs #font#mbfam\font \orelse \ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size \lastnamedcs #font#mbfam\font \else #font#mbfam#font#mrfam% \fi} % optimized: math fonts are never changed (10K \bfa $x$: 3.2 => 2.5 (baseline 1.0)) % % sort of tricky: we cannot reset in \everybeforedefinetypeface as we don't know % all sizes so we postpone the optimization to the first starttext % % pitfall: we should reset 'm when a fontclass name is reused \newconditional\optimizemathfontdefinitions \settrue\optimizemathfontdefinitions \def\font_helpers_set_math_family#mrfam#familytag% {\ifconditional\optimizemathfontdefinitions \ifcsname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-1\endcsname % \writestatus{fonts}{math: reusing \fontclass\fontbody\s!mm#familytag\fontsize1}% \font_helpers_preset_math_family_indeed#mrfam#familytag% \else % \writestatus{fonts}{math: defining \fontclass\fontbody\s!mm#familytag\fontsize1}% \font_helpers_set_math_family_indeed#mrfam#familytag% \fi \else \font_helpers_set_math_family_indeed#mrfam#familytag% \fi} \def\font_helpers_set_math_family_bold#mbfam#familytag#mrfam% {\ifconditional\optimizemathfontdefinitions %\ifcsname\??fontinstanceclass\fontclass-\textface-\s!mm-#familytag-\fontsize-1\endcsname \ifcsname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-1\endcsname \font_helpers_preset_math_family_indeed#mbfam#familytag% \else \font_helpers_set_math_family_bold_indeed#mbfam#familytag#mrfam% \fi \else \font_helpers_set_math_family_bold_indeed#mbfam#familytag#mrfam% \fi} %D It can happen that we use a bodyfont with no math in which case we have a problem %D with setting the global bodyfont size in the page builder. For instance in: %D %D \starttext %D \definetypeface[test][rm][serif][pagella][default] %D \setupbodyfont[test] %D test %D \stoptext %D %D This is why we need the check. At the cost of some extra checking we gain a %D little in restoring global states and, what's more important, we get rid of large %D math parameter push/pop in tracingall when not needed. \def\font_helpers_preset_math_family_indeed_normal#fam#familytag% {\expandafter\let\expandafter\font_math_last_font\csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-1\endcsname \font_math_last_font \ifnum\fontid\textfont#fam=\fontid\font\else \font_helpers_preset_math_family_indeed_changed_normal#fam#familytag% \fi} \def\font_helpers_preset_math_family_indeed_changed_normal#fam#familytag% {\font_helpers_set_math_family_set_scales_normal \csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-3\endcsname\scriptscriptfont#fam\font \csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-2\endcsname\scriptfont #fam\font % \csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-1\endcsname\textfont #fam\font} \font_math_last_font \textfont #fam\font} \def\font_helpers_preset_math_family_indeed_compact#fam#familytag% {\csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-1\endcsname \ifnum\fontid\textfont#fam=\fontid\font\else \font_helpers_preset_math_family_indeed_changed_compact#fam% \fi} \def\font_helpers_preset_math_family_indeed_changed_compact#fam% {\font_helpers_set_math_family_set_scales_compact \scriptscriptfont#fam\font \scriptfont #fam\font \textfont #fam\font} \def\font_helpers_preset_math_family_indeed {\ifconditional\c_font_compact \expandafter\font_helpers_preset_math_family_indeed_compact \else \expandafter\font_helpers_preset_math_family_indeed_normal \fi} \let\font_helpers_reset_fontclass_math_families\gobbleoneargument %D It would be nice if characters could be defined in a neutral way (say fam 255) %D and be mapped to a real family during noad list construction. However, this %D changes tex in critical places so for the moment we simulate this using %D manipulation. %D %D For tracing purposes we use three families but in l2r mode 1 and 2 are copies of %D 0 while in rl mode 0 is a copy of 1. There is no real overhead involved in this. %D This also permits different font definitions for normal and mixed. \lettonothing\m_font_class_direction \lettonothing\m_font_class_features \lettonothing\m_font_class_fallbacks \lettonothing\m_font_class_goodies \lettonothing\m_font_direction \lettonothing\m_font_features \lettonothing\m_font_fallbacks \lettonothing\m_font_goodies \appendtoks \font_helpers_set_math_family\c_font_fam_mr\s!mr \to \t_font_math_strategies \def\font_helpers_complete_bold_mathstrategy_yes {\font_helpers_set_math_family_bold\c_font_fam_mb\s!mb\c_font_fam_mr\relax} \def\font_helpers_complete_bold_mathstrategy_nop {\ifnum\fontid\textfont\c_font_fam_mb=\fontid\textfont\c_font_fam_mr\else \font_helpers_complete_bold_mathstrategy_nop_changed \fi} \def\font_helpers_complete_bold_mathstrategy_nop_changed {\textfont \c_font_fam_mb\textfont \c_font_fam_mr \scriptfont \c_font_fam_mb\scriptfont \c_font_fam_mr \scriptscriptfont\c_font_fam_mb\scriptscriptfont\c_font_fam_mr} \def\font_helpers_apply_complete_bold_mathstrategy {\ifconditional\c_font_complete_bold_mathstrategy \font_helpers_complete_bold_mathstrategy_yes \else \font_helpers_complete_bold_mathstrategy_nop \fi} \appendtoks \font_helpers_apply_complete_bold_mathstrategy \to \t_font_math_strategies \ifdefined\defaultmathfamily \else \setnewconstant\defaultmathfamily\zerocount % no longer used, always zero \fi \appendtoks \fam\zerocount % all characters and symbols are in this family \to \everymathematics \protected\def\font_helpers_synchronize_math_family_mr {\c_attr_mathfamily\zerocount} \protected\def\font_helpers_synchronize_math_family_mb {\c_attr_mathfamily\ifconditional\c_font_pseudo_bold_math_state\plussix\else\plusthree\fi} \installcorenamespace{fontmathsynchronizer} \installcorenamespace{fontmathstoredstrategy} \letcsname\??fontmathsynchronizer\s!tf \endcsname\font_helpers_synchronize_math_family_mr \letcsname\??fontmathsynchronizer\s!sl \endcsname\font_helpers_synchronize_math_family_mr \letcsname\??fontmathsynchronizer\s!it \endcsname\font_helpers_synchronize_math_family_mr \letcsname\??fontmathsynchronizer\s!bf \endcsname\font_helpers_synchronize_math_family_mb \letcsname\??fontmathsynchronizer\s!bs \endcsname\font_helpers_synchronize_math_family_mb \letcsname\??fontmathsynchronizer\s!bi \endcsname\font_helpers_synchronize_math_family_mb \letcsname\??fontmathsynchronizer\empty\endcsname\font_helpers_synchronize_math_family_mr \def\font_helpers_synchronize_math_family {\ifcsname\??fontmathsynchronizer\fontalternative\endcsname \lastnamedcs \else \font_helpers_synchronize_math_family_mr \fi} \appendtoks \ifnum\fontid\textfont\zerocount=\fontid\textfont\plusthree \letcsname\??fontmathstoredstrategy\fontclass\endcsname\font_helpers_set_math_partial_bold_strategy \else \letcsname\??fontmathstoredstrategy\fontclass\endcsname\font_helpers_set_math_full_bold_strategy \fi \to \t_font_math_strategies \def\font_helpers_synchronize_math_bold_strategy{\begincsname\??fontmathstoredstrategy\fontclass\endcsname} \newconditional\c_font_pseudo_bold_math_state \def\font_helpers_set_math_partial_bold_strategy{\settrue \c_font_pseudo_bold_math_state} \def\font_helpers_set_math_full_bold_strategy {\setfalse\c_font_pseudo_bold_math_state} \appendtoks \font_helpers_synchronize_math_bold_strategy \to \everymathematics %D Bold is somewhat special as we might want both full-bold-math mixed regular-math, %D as well as automatic adaption to outer bold (in titles and inline text bold) so %D we will need explicit switches as well as an automatic one. (We will use lucida %D as an example.) \ifdefined\mathdefault \else \let\mathdefault\relax \fi \newconditional\c_math_bold \permanent\protected\def\mr % math regular {\ifmmode \font_helpers_synchronize_math_family_mr \else \font_helpers_set_current_font_alternative\s!mr \fi \mathdefault \setfalse\c_math_bold} \permanent\protected\def\mb % math bold {\ifmmode \font_helpers_synchronize_math_family_mb \else \font_helpers_set_current_font_alternative\s!mb \fi \mathdefault \settrue\c_math_bold} \appendtoks \font_helpers_synchronize_math_family % auto bold \to \everymathematics \appendtoks \ifconditional\c_math_bold\mb\fi \to \everymathematics %D \macros %D {bigmath,nobigmath} %D %D We can inhibit this slow||downer with: % these can best be combined % 0=never 1=everymath 2=always \setnewconstant\synchronizebigmathflag\plusone \appendtoks \ifcase\synchronizebigmathflag % never \or \synchronizebigmath \or % always \fi \to \everymathematics \permanent\protected\def\nobigmath {\synchronizebigmathflag\zerocount} \permanent\protected\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath} \permanent\protected\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath} \mutable\lettonothing\bigmathfontsize \permanent\protected\def\synchronizebigmath {\ifconditional\c_font_compact % no need \orelse\ifx\bigmathfontsize\fontsize % already in sync \else \let\bigmathfontsize\fontsize \font_helpers_synchronize_math \fi} \protected\def\font_helpers_check_big_math_synchronization {\ifcase\synchronizebigmathflag % never \or \ifmmode \synchronizebigmath \fi \or \synchronizebigmath \fi} %D This is an experiment! \permanent\protected\def\mx {\ifmmode\scaledmathstyle\dimexpression\plusthousand*(\xtextface /\textface)\relax\fi} \permanent\protected\def\mxx{\ifmmode\scaledmathstyle\dimexpression\plusthousand*(\xxtextface/\textface)\relax\fi} \permanent\protected\def\setmscale#1{\ifmmode\scaledmathstyle\numericscale#1\relax\fi} %D This is nasty, as the engine only stores the last set family parameters (per style) which %D in our case can be bold. \def\font_helpers_synchronize_math_parameters {\c_math_last_family_used\mathstylefontid\textstyle\zerocount \textfont \zerocount\textfont \zerocount \scriptfont \zerocount\scriptfont \zerocount \scriptscriptfont\zerocount\scriptscriptfont\zerocount} \appendtoks \ifnum\c_math_last_family_used=\mathstylefontid\textstyle\zerocount\else \font_helpers_synchronize_math_parameters \fi \to\everybodyfont \protect \endinput