%%^^A%% um-code-main.dtx -- part of UNICODE-MATH % \section{The main \cs{setmathfont} macro} % % \begin{macrocode} %<*package> % \end{macrocode} % % Using a |range| including large character sets such as \cmd\mathrel, % \cmd\mathalpha, \etc, is \emph{very slow}! % I hope to improve the performance somehow. % % \begin{macro}{\@@_setmathfont:nn} % \begin{macrocode} \cs_set:Nn \@@_setmathfont:nn { \tl_set:Nn \l_@@_fontname_tl {#2} % \end{macrocode} % Erase any conception \LaTeX\ has of previously defined math symbol fonts; % this allows \cmd\DeclareSymbolFont\ at any point in the document. % \begin{macrocode} \cs_set_eq:NN \glb@currsize \scan_stop: % \end{macrocode} % Initialise all local variabes: % \begin{macrocode} \@@_init: % \end{macrocode} % Grab the current size information: % (is this robust enough? Maybe it should be preceded by \cmd\normalsize). % The macro \cmd\S@\meta{size} % contains the definitions of the sizes used for maths letters, subscripts and subsubscripts in % \cmd\tf@size, \cmd\sf@size, and \cmd\ssf@size, respectively. % \begin{macrocode} \cs_if_exist:cF { S@ \f@size } { \calculate@math@sizes } \csname S@\f@size\endcsname % \end{macrocode} % Parse options and tell people what's going on: % \begin{macrocode} \keys_set_known:nnN {unicode-math} {#1} \l_@@_unknown_keys_clist \bool_if:NT \l_@@_init_bool { \@@_log:n {default-math-font} } % \end{macrocode} % Use \pkg{fontspec} to select a font to use. % After loading the font, we detect what sizes it recommends for scriptsize and scriptscriptsize, so after setting those values appropriately, we reload the font to take these into account. % \begin{macrocode} % \csname TIC\endcsname \@@_fontspec_select_font: % \csname TOC\endcsname \bool_if:nT { \l_@@_ot_math_bool && !\g_@@_mainfont_already_set_bool } { \@@_declare_math_sizes: \@@_fontspec_select_font: } % \end{macrocode} % Now define |\l_@@_symfont_label_tl| as the \LaTeX\ math font to access everything: % \begin{macrocode} \cs_if_exist:cF { sym \l_@@_symfont_label_tl } { \DeclareSymbolFont{\l_@@_symfont_label_tl} {\encodingdefault}{\l_@@_family_tl}{\mddefault}{\updefault} } \SetSymbolFont{\l_@@_symfont_label_tl}{\l_@@_mversion_tl} {\encodingdefault}{\l_@@_family_tl}{\mddefault}{\updefault} % \end{macrocode} % Set the bold math version. % \begin{macrocode} \str_if_eq_x:nnT {\l_@@_mversion_tl} {normal} { \SetSymbolFont{\l_@@_symfont_label_tl}{bold} {\encodingdefault}{\l_@@_family_tl}{\bfdefault}{\updefault} } % \end{macrocode} % Declare the math sizes (i.e., scaling of superscripts) for the specific % values for this font, % and set defaults for math fams two and three for legacy compatibility: % \begin{macrocode} \bool_if:nT { \l_@@_ot_math_bool && !\g_@@_mainfont_already_set_bool } { \bool_set_true:N \g_@@_mainfont_already_set_bool \@@_setup_legacy_fam_two: \@@_setup_legacy_fam_three: } % \end{macrocode} % And now we input every single maths char. % \begin{macrocode} % \csname TIC\endcsname \@@_input_math_symbol_table: % \csname TOC\endcsname % \end{macrocode} % Finally, % \begin{itemize} % \item remap symbols that don't take their natural mathcode; % \item activate any symbols that need to be math-active; % \item assign delimiter codes for symbols that need to grow; % \item setup the maths alphabets (\cs{symbf} etc.) --- % this is an extensive part of the code; see Section~\ref{sec:mathmap}; % \item setup negations, which are handled on an ad hoc basis; see Section~\ref{sec:negations}. % \end{itemize} % \begin{macrocode} \@@_remap_symbols: \@@_setup_mathactives: \@@_setup_delcodes: % \csname TIC\endcsname \@@_setup_alphabets: % \csname TOC\endcsname \@@_setup_negations: } % \end{macrocode} % \end{macro} % % \paragraph{Fall-back font} % % Want to load Latin Modern Math if nothing else. % This needs to happen early so that all of the font-loading machinery executes before % the other `AtBeginDocument' code. % \begin{macrocode} \AtBeginDocument { \@@_load_lm_if_necessary: } \cs_new:Nn \@@_load_lm_if_necessary: { \cs_if_exist:NF \l_@@_fontname_tl { % TODO: update this when lmmath-bold.otf is released \setmathfont{latinmodern-math.otf}[BoldFont={latinmodern-math.otf}] \bool_set_false:N \g_@@_mainfont_already_set_bool } } % \end{macrocode} % Note that here we reset the `font already loaded' boolean so that a new font being set % will do the right thing in terms of setting up defaults. % % TODO: need a better way to do this for the general case. (Maybe a `reset' command option?) % % \begin{macro}{\@@_init:} % \begin{macrocode} \cs_new:Nn \@@_init: { \bool_set_true:N \l_@@_ot_math_bool \tl_set:Nn \l_@@_mversion_tl {normal} \tl_set:Nn \l_@@_symfont_label_tl {operators} % \end{macrocode} % Defaults for the script and scriptscript font. % \begin{macrocode} \tl_set:Nn \l_@@_script_features_tl {Style=MathScript} \tl_set:Nn \l_@@_sscript_features_tl {Style=MathScriptScript} \tl_set_eq:NN \l_@@_script_font_tl \l_@@_fontname_tl \tl_set_eq:NN \l_@@_sscript_font_tl \l_@@_fontname_tl % \end{macrocode} % Default to defining the font for every math symbol character. % \begin{macrocode} \bool_set_true:N \l_@@_init_bool \seq_clear:N \l_@@_char_range_seq \clist_clear:N \l_@@_char_nrange_clist \seq_clear:N \l_@@_mathalph_seq \seq_clear:N \l_@@_missing_alph_seq % \end{macrocode} % Other range initialisations. % \begin{macrocode} \cs_set_eq:NN \_@@_sym:nnn \@@_process_symbol_noparse:nnn \cs_set_eq:NN \@@_set_mathalphabet_char:nnn \@@_mathmap_noparse:nnn \cs_set_eq:NN \@@_remap_symbol:nnn \@@_remap_symbol_noparse:nnn \cs_set_eq:NN \@@_maybe_init_alphabet:n \@@_init_alphabet:n \cs_set_eq:NN \@@_map_char_single:nn \@@_map_char_noparse:nn \cs_set_eq:NN \@@_assign_delcode:nn \@@_assign_delcode_noparse:nn \cs_set_eq:NN \@@_make_mathactive:nNN \@@_make_mathactive_noparse:nNN } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_declare_math_sizes:} % Set the math sizes according to the recommended font parameters. % TODO: this shouldn't need to be per-engine; check out why the wrappers aren't used. % \begin{macrocode} \cs_new:Nn \@@_declare_math_sizes: { %<*LU> \fp_compare:nF { \@@_script_style_size:n {ScriptPercentScaleDown} == 0 } { \DeclareMathSizes { \f@size } { \f@size } { \@@_script_style_size:n {ScriptPercentScaleDown} } { \@@_script_style_size:n {ScriptScriptPercentScaleDown} } } % %<*XE> \dim_compare:nF { \fontdimen 10 \l_@@_font == 0pt } { \DeclareMathSizes { \f@size } { \f@size } { \@@_fontdimen_to_scale:nn {10} {\l_@@_font} } { \@@_fontdimen_to_scale:nn {11} {\l_@@_font} } } % } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_script_style_size:n} % Determine script- and scriptscriptstyle sizes using luaotfload: % \begin{macrocode} %<*LU> \cs_new:Nn \@@_script_style_size:n { \fp_eval:n {\directlua{tex.sprint(luaotfload.aux.get_math_dimension("l_@@_font","#1"))} * \f@size / 100 } } % % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_setup_legacy_fam_two:} % \TeX\ won't load the same font twice at the same scale, so we need to magnify this one by an imperceptable amount. % \begin{macrocode} \cs_new:Nn \@@_setup_legacy_fam_two: { \fontspec_set_family:Nxn \l_@@_family_tl { \l_@@_font_keyval_tl, Scale=1.00001, FontAdjustment = { \@@_copy_fontparam:nnn { 8} {43} {FractionNumeratorDisplayStyleShiftUp}\relax \@@_copy_fontparam:nnn { 9} {42} {FractionNumeratorShiftUp}\relax \@@_copy_fontparam:nnn {10} {32} {StackTopShiftUp}\relax \@@_copy_fontparam:nnn {11} {45} {FractionDenominatorDisplayStyleShiftDown}\relax \@@_copy_fontparam:nnn {12} {44} {FractionDenominatorShiftDown}\relax \@@_copy_fontparam:nnn {13} {21} {SuperscriptShiftUp}\relax \@@_copy_fontparam:nnn {14} {21} {SuperscriptShiftUp}\relax \@@_copy_fontparam:nnn {15} {22} {SuperscriptShiftUpCramped}\relax \@@_copy_fontparam:nnn {16} {18} {SubscriptShiftDown}\relax \@@_copy_fontparam:nnn {17} {18} {SubscriptShiftDownWithSuperscript}\relax \@@_copy_fontparam:nnn {18} {24} {SuperscriptBaselineDropMax}\relax \@@_copy_fontparam:nnn {19} {20} {SubscriptBaselineDropMin}\relax \@@_zero_fontparam:n {20} % delim1 = FractionDelimiterDisplaySize \@@_zero_fontparam:n {21} % delim2 = FractionDelimiterSize \@@_copy_fontparam:nnn {22} {15} {AxisHeight}\relax } } {\l_@@_fontname_tl} \SetSymbolFont{symbols}{\l_@@_mversion_tl} {\encodingdefault}{\l_@@_family_tl}{\mddefault}{\updefault} \str_if_eq_x:nnT {\l_@@_mversion_tl} {normal} { \SetSymbolFont{symbols}{bold} {\encodingdefault}{\l_@@_family_tl}{\bfdefault}{\updefault} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_setup_legacy_fam_three:} % Similarly, this font is shrunk by an imperceptable amount for \TeX\ to load it again. % \begin{macrocode} \cs_new:Nn \@@_setup_legacy_fam_three: { \fontspec_set_family:Nxn \l_@@_family_tl { \l_@@_font_keyval_tl, Scale=0.99999, FontAdjustment = { \@@_copy_fontparam:nnn { 8} {48} {FractionRuleThickness}\relax \@@_copy_fontparam:nnn { 9} {28} {UpperLimitGapMin}\relax \@@_copy_fontparam:nnn {10} {30} {LowerLimitGapMin}\relax \@@_copy_fontparam:nnn {11} {29} {UpperLimitBaselineRiseMin}\relax \@@_copy_fontparam:nnn {12} {31} {LowerLimitBaselineDropMin}\relax \@@_zero_fontparam:n {13} } } {\l_@@_fontname_tl} \SetSymbolFont{largesymbols}{\l_@@_mversion_tl} {\encodingdefault}{\l_@@_family_tl}{\mddefault}{\updefault} \str_if_eq_x:nnT {\l_@@_mversion_tl} {normal} { \SetSymbolFont{largesymbols}{bold} {\encodingdefault}{\l_@@_family_tl}{\bfdefault}{\updefault} } } % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@_fontspec_select_font:} % Select the font with \cs{fontspec} and define \cs{l_@@_font} from it. % \begin{macrocode} \cs_new:Nn \@@_fontspec_select_font: { \tl_set:Nx \l_@@_font_keyval_tl { % Renderer = Basic, BoldItalicFont = {}, ItalicFont = {}, Script = Math, SizeFeatures = { { Size = \tf@size- } , { Size = \sf@size-\tf@size , Font = \l_@@_script_font_tl , \l_@@_script_features_tl } , { Size = -\sf@size , Font = \l_@@_sscript_font_tl , \l_@@_sscript_features_tl } } , \l_@@_unknown_keys_clist } \fontspec_set_fontface:NNxn \l_@@_font \l_@@_family_tl {\l_@@_font_keyval_tl} {\l_@@_fontname_tl} % \end{macrocode} % Check whether we're using a real maths font: % \begin{macrocode} \group_begin: \fontfamily{\l_@@_family_tl}\selectfont \fontspec_if_script:nF {math} {\bool_gset_false:N \l_@@_ot_math_bool} \group_end: } % \end{macrocode} % \end{macro} % % \subsection{Functions for setting up symbols with mathcodes} % \seclabel{mathsymbol} % % \begin{macro}{\@@_process_symbol_noparse:nnn} % \begin{macro}{\@@_process_symbol_parse:nnn} % If the \feat{range} font feature has been used, then only % a subset of the Unicode glyphs are to be defined. % See \secref{rangeproc} for the code that enables this. % \begin{macrocode} \cs_set:Nn \@@_process_symbol_noparse:nnn { \@@_set_mathsymbol:nNNn {\l_@@_symfont_label_tl} #2 #3 {#1} } % \end{macrocode} % \begin{macrocode} \cs_set:Nn \@@_process_symbol_parse:nnn { \@@_if_char_spec:nNNT {#1} {#2} {#3} { \@@_process_symbol_noparse:nnn {#1} {#2} {#3} } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@@_remap_symbols:} % \begin{macro}{\@@_remap_symbol_noparse:nnn} % \begin{macro}{\@@_remap_symbol_parse:nnn} % This function is used to define the mathcodes for those chars which should % be mapped to a different glyph than themselves. % \begin{macrocode} \cs_new:Npn \@@_remap_symbols: { \@@_remap_symbol:nnn{`\-}{\mathbin}{"02212}% hyphen to minus \@@_remap_symbol:nnn{`\*}{\mathbin}{"02217}% text asterisk to "centred asterisk" \bool_if:NF \g_@@_literal_colon_bool { \@@_remap_symbol:nnn{`\:}{\mathrel}{"02236}% colon to ratio (i.e., punct to rel) } } % \end{macrocode} % \end{macro} % Where |\@@_remap_symbol:nnn| is defined to be one of these two, depending % on the range setup: % \begin{macrocode} \cs_new:Nn \@@_remap_symbol_parse:nnn { \@@_if_char_spec:nNNT {#3} {\@nil} {#2} { \@@_remap_symbol_noparse:nnn {#1} {#2} {#3} } } \cs_new:Nn \@@_remap_symbol_noparse:nnn { \clist_map_inline:nn {#1} { \@@_set_mathcode:nnnn {##1} {#2} {\l_@@_symfont_label_tl} {#3} } } % \end{macrocode} % \end{macro} % \end{macro} % % \subsection{Active math characters} % % There are more math active chars later in the subscript/superscript section. % But they don't need to be able to be typeset directly. % % \begin{macro}{\@@_setup_mathactives:} % \begin{macrocode} \cs_new:Npn \@@_setup_mathactives: { \@@_make_mathactive:nNN {"2032} \@@_prime_single_mchar \mathord \@@_make_mathactive:nNN {"2033} \@@_prime_double_mchar \mathord \@@_make_mathactive:nNN {"2034} \@@_prime_triple_mchar \mathord \@@_make_mathactive:nNN {"2057} \@@_prime_quad_mchar \mathord \@@_make_mathactive:nNN {"2035} \@@_backprime_single_mchar \mathord \@@_make_mathactive:nNN {"2036} \@@_backprime_double_mchar \mathord \@@_make_mathactive:nNN {"2037} \@@_backprime_triple_mchar \mathord \@@_make_mathactive:nNN {`\'} \mathstraightquote \mathord \@@_make_mathactive:nNN {`\`} \mathbacktick \mathord } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_make_mathactive:nNN} % Makes |#1| a mathactive char, and gives cs |#2| the meaning of mathchar |#1| % with class |#3|. % You are responsible for giving active |#1| a particular meaning! % \begin{macrocode} \cs_new:Nn \@@_make_mathactive_parse:nNN { \@@_if_char_spec:nNNT {#1} #2 #3 { \@@_make_mathactive_noparse:nNN {#1} #2 #3 } } % \end{macrocode} % % \begin{macrocode} \cs_new:Nn \@@_make_mathactive_noparse:nNN { \@@_set_mathchar:NNnn #2 #3 {\l_@@_symfont_label_tl} {#1} \@@_char_gmake_mathactive:n {#1} } % \end{macrocode} % \end{macro} % % \subsection{Delimiter codes} % % \begin{macro}{\@@_assign_delcode:nn} % \begin{macrocode} \cs_new:Nn \@@_assign_delcode_noparse:nn { \@@_set_delcode:nnn \l_@@_symfont_label_tl {#1} {#2} } % \end{macrocode} % % \begin{macrocode} \cs_new:Nn \@@_assign_delcode_parse:nn { \@@_if_char_spec:nNNT {#2} {\@nil} {\@nil} { \@@_assign_delcode_noparse:nn {#1} {#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_assign_delcode:n} % Shorthand. % \begin{macrocode} \cs_new:Nn \@@_assign_delcode:n { \@@_assign_delcode:nn {#1} {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_setup_delcodes:} % Some symbols that aren't mathopen/mathclose still need to have delimiter codes assigned. % The list of vertical arrows may be incomplete. % On the other hand, many fonts won't support them all being stretchy. % And some of them are probably not meant to stretch, either. But adding them here doesn't hurt. % \begin{macrocode} \cs_new:Npn \@@_setup_delcodes: { % ensure \left. and \right. work: \@@_set_delcode:nnn \l_@@_symfont_label_tl {`\.} {\c_zero} % this is forcefully done to fix a bug -- indicates a larger problem! \@@_assign_delcode:nn {`\/} {\g_@@_slash_delimiter_usv} \@@_assign_delcode:nn {"2044} {\g_@@_slash_delimiter_usv} % fracslash \@@_assign_delcode:nn {"2215} {\g_@@_slash_delimiter_usv} % divslash \@@_assign_delcode:n {"005C} % backslash \@@_assign_delcode:nn {`\<} {"27E8} % angle brackets with ascii notation \@@_assign_delcode:nn {`\>} {"27E9} % angle brackets with ascii notation \@@_assign_delcode:n {"2191} % up arrow \@@_assign_delcode:n {"2193} % down arrow \@@_assign_delcode:n {"2195} % updown arrow \@@_assign_delcode:n {"219F} % up arrow twohead \@@_assign_delcode:n {"21A1} % down arrow twohead \@@_assign_delcode:n {"21A5} % up arrow from bar \@@_assign_delcode:n {"21A7} % down arrow from bar \@@_assign_delcode:n {"21A8} % updown arrow from bar \@@_assign_delcode:n {"21BE} % up harpoon right \@@_assign_delcode:n {"21BF} % up harpoon left \@@_assign_delcode:n {"21C2} % down harpoon right \@@_assign_delcode:n {"21C3} % down harpoon left \@@_assign_delcode:n {"21C5} % arrows up down \@@_assign_delcode:n {"21F5} % arrows down up \@@_assign_delcode:n {"21C8} % arrows up up \@@_assign_delcode:n {"21CA} % arrows down down \@@_assign_delcode:n {"21D1} % double up arrow \@@_assign_delcode:n {"21D3} % double down arrow \@@_assign_delcode:n {"21D5} % double updown arrow \@@_assign_delcode:n {"21DE} % up arrow double stroke \@@_assign_delcode:n {"21DF} % down arrow double stroke \@@_assign_delcode:n {"21E1} % up arrow dashed \@@_assign_delcode:n {"21E3} % down arrow dashed \@@_assign_delcode:n {"21E7} % up white arrow \@@_assign_delcode:n {"21E9} % down white arrow \@@_assign_delcode:n {"21EA} % up white arrow from bar \@@_assign_delcode:n {"21F3} % updown white arrow } % \end{macrocode} % \end{macro} % % \subsection{(Big) operators} % % The engine does what is necessary to deal with big operators for us % automatically with \cmd\Umathchardef. % However, the limits aren't set automatically; that is, we want to define, % a la Plain \TeX\ \etc, |\def\int{\intop\nolimits}|, so there needs to be a % transformation from \cmd\int\ to \cmd\intop\ during the expansion of % \cmd\_@@_sym:nnn\ in the appropriate contexts. % % \begin{macro}{\l_@@_nolimits_tl} % This macro is a sequence containing those maths operators that require a % \cmd\nolimits\ suffix. % This list is used when processing |unicode-math-table.tex| to define such % commands automatically (see the macro \cs{@@_set_mathsymbol:nNNn}). % I've chosen essentially just the operators that look like integrals; % hopefully a better mathematician can help me out here. % I've a feeling that it's more useful \emph{not} to include the multiple % integrals such as $\iiiint$, but that might be a matter of preference. % \begin{macrocode} \tl_set:Nn \l_@@_nolimits_tl { \int\iint\iiint\iiiint\oint\oiint\oiiint \intclockwise\varointclockwise\ointctrclockwise\sumint \intbar\intBar\fint\cirfnint\awint\rppolint \scpolint\npolint\pointint\sqint\intlarhk\intx \intcap\intcup\upint\lowint } % \end{macrocode} % \end{macro} % % \subsection{Radicals} % % \begin{macro}{\l_@@_radicals_tl} % The radicals are organised in \cs{@@_set_mathsymbol:nNNn}. % We organise radicals in the same way as nolimits-operators. % (\cs{cuberoot} and \cs{fourthroot}, don't seem to behave as proper radicals.) % \begin{macrocode} \tl_set:Nn \l_@@_radicals_tl {\sqrt \longdivision} % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} \endinput % /© % % ------------------------------------------------ % The UNICODE-MATH package % ------------------------------------------------ % This package is free software and may be redistributed and/or modified under % the conditions of the LaTeX Project Public License, version 1.3c or higher % (your choice): . % ------------------------------------------------ % Copyright 2006-2017 Will Robertson, LPPL "maintainer" % Copyright 2010-2017 Philipp Stephani % Copyright 2011-2017 Joseph Wright % Copyright 2012-2015 Khaled Hosny % ------------------------------------------------ % % ©/