diff options
Diffstat (limited to 'macros/latex/contrib/unicode-math/um-code-mathmap.dtx')
-rw-r--r-- | macros/latex/contrib/unicode-math/um-code-mathmap.dtx | 595 |
1 files changed, 595 insertions, 0 deletions
diff --git a/macros/latex/contrib/unicode-math/um-code-mathmap.dtx b/macros/latex/contrib/unicode-math/um-code-mathmap.dtx new file mode 100644 index 0000000000..e55fe07c2c --- /dev/null +++ b/macros/latex/contrib/unicode-math/um-code-mathmap.dtx @@ -0,0 +1,595 @@ +%%^^A%% um-code-mathmap.dtx -- part of UNICODE-MATH <wspr.io/unicode-math> +%%^^A%% Setup of symbol alphabets. + +% \section{Defining the math alphabets per style} +% \label{sec:mathmap} +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \begin{macro}{\@@_setup_alphabets:} +% This function is called within \cs{setmathfont} to configure the +% mapping between characters inside math styles. Three modes: +% \begin{description} +% \item[IMPLICIT] No ranges specified, set up everything +% \item[EXPLICIT] Some ranges specified, set up what is requested only +% \item[INHERIT] Of the slots in the ranges specified, compare against +% slots in each styled alphabet and only set up those needed +% \end{description} +% The INHERIT mode saves less time than I was hoping for but is still beneficial +% in simple cases. +% \begin{macrocode} +\@@_cs_new:Nn \@@_setup_alphabets: + { + \bool_if:NTF \g_@@_init_bool { \@@_setup_alphabets_implicit: } + { + \seq_if_empty:NF \g_@@_mathalph_seq { \@@_setup_alphabets_explicit: } + \clist_if_empty:NF \l_@@_mathmap_charints_clist { \@@_setup_alphabets_inherit: } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_setup_alphabets_implicit:} +% \begin{macrocode} +\@@_cs_new:Nn \@@_setup_alphabets_implicit: + { + \@@_log:n {setup-implicit} + \seq_gset_eq:NN \g_@@_mathalph_seq \g_@@_default_mathalph_seq + \bool_set_true:N \l_@@_implicit_alph_bool + \@@_maybe_init_alphabet:n {sf} + \@@_maybe_init_alphabet:n {bf} + \@@_maybe_init_alphabet:n {bfsf} + \cs_set_eq:NN \@@_set_mathalphabet_char:nnn \@@_mathmap_noparse:nnn + \cs_set_eq:NN \@@_map_char_single:nn \@@_map_char_noparse:nn + \@@_mathalph_map: + \seq_if_empty:NF \l_@@_missing_alph_seq { \@@_log:n { missing-alphabets } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_setup_alphabets_explicit:} +% \begin{macrocode} +\@@_cs_new:Nn \@@_setup_alphabets_explicit: + { + \@@_log:n {setup-explicit} + \bool_set_false:N \l_@@_implicit_alph_bool + \cs_set_eq:NN \@@_set_mathalphabet_char:nnn \@@_mathmap_noparse:nnn + \cs_set_eq:NN \@@_map_char_single:nn \@@_map_char_noparse:nn + \@@_mathalph_map: + \seq_if_empty:NF \l_@@_missing_alph_seq { \@@_log:n { missing-alphabets } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_setup_alphabets_inherit:} +% \begin{macrocode} +\@@_cs_new:Nn \@@_setup_alphabets_inherit: + { + \seq_gclear:N \g_@@_mathalph_seq + \seq_map_inline:Nn \g_@@_default_mathalph_seq + { + \tl_set:No \l_@@_style_tl { \use_i:nnn ##1 } + \clist_set:No \l_@@_alphabet_clist { \use_ii:nnn ##1 } + + \clist_map_inline:Nn \l_@@_alphabet_clist + { + \clist_if_exist:cT {g_@@_named_slots_ \l_@@_style_tl _ ####1 _clist} + { + \clist_map_inline:cn {g_@@_named_slots_ \l_@@_style_tl _ ####1 _clist} + { + \clist_map_inline:Nn \l_@@_mathmap_charints_clist + { + \@@_int_if_slot_in_range:nnT {################1} {########1} + { + \seq_gput_right:Nn \g_@@_mathalph_seq {##1} + \clist_map_break:n { \clist_map_break:n { \clist_map_break: } } + } + } + } + } + } + } + + \cs_set_eq:NN \@@_set_mathalphabet_char:nnn \@@_mathmap_parse:nnn + \cs_set_eq:NN \@@_map_char_single:nn \@@_map_char_parse:nn + \@@_mathalph_map: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_mathalph_map:} +% \begin{macrocode} +\cs_set:Nn \@@_mathalph_map: + { + \seq_map_inline:Nn \g_@@_mathalph_seq + { + \tl_set:No \l_@@_style_tl { \use_i:nnn ##1 } + \clist_set:No \l_@@_alphabet_clist { \use_ii:nnn ##1 } + \tl_set:No \l_@@_remap_style_tl { \use_iii:nnn ##1 } + + % If no set of alphabets is defined: + \clist_if_empty:NT \l_@@_alphabet_clist + { + \cs_set_eq:NN \@@_maybe_init_alphabet:n \@@_init_alphabet:n + \prop_get:cnN { g_@@_named_range_ \l_@@_style_tl _prop } + { default-alpha } \l_@@_alphabet_clist + } + + \@@_check_math_alphabet: + \@@_setup_math_alphabet: + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_check_math_alphabet:} +% First check that at least one of the alphabets for the font shape is defined +% (this process is fast) \dots +% \begin{macrocode} +\cs_new:Nn \@@_check_math_alphabet: + { + \clist_map_inline:Nn \l_@@_alphabet_clist + { + \tl_set:Nn \l_@@_alphabet_tl {##1} + \@@_if_alphabet_exists:nnTF \l_@@_style_tl \l_@@_alphabet_tl + { + \str_if_eq:eeTF {\l_@@_alphabet_tl} {misc} + { + \@@_maybe_init_alphabet:n \l_@@_style_tl + \clist_map_break: + } + { + \@@_glyph_if_exist:NnT \g_@@_curr_font_cmd_tl + { \@@_to_usv:nn {\l_@@_style_tl} {\l_@@_alphabet_tl} } + { + \@@_maybe_init_alphabet:n \l_@@_style_tl + \clist_map_break: + } + } + } + { + \msg_warning:nnx {unicode-math} {no-alphabet} + { \l_@@_style_tl / \l_@@_alphabet_tl } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_setup_math_alphabet:} +% \dots and then loop through them defining the individual ranges: +% (currently this process is slow) +% \begin{macrocode} +\@@_cs_new:Nn \@@_setup_math_alphabet: + { + \clist_map_inline:Nn \l_@@_alphabet_clist + { + \tl_set:Nx \l_@@_alphabet_tl { \tl_trim_spaces:n {##1} } + +%<debug>\@@_debug:n {_setup_math_alphabet:~\l_@@_style_tl/\l_@@_alphabet_tl} + + \@@_if_alphabet_exists:nnT {\l_@@_style_tl} {\l_@@_alphabet_tl} + { + \exp_args:No \tl_if_eq:nnTF \l_@@_alphabet_tl {misc} + { + \@@_log:nx {setup-alph} {sym \l_@@_style_tl~(\l_@@_alphabet_tl)} + \@@_alphabet_config:nnn {\l_@@_style_tl} {\l_@@_alphabet_tl} {\l_@@_remap_style_tl} + } + { + \@@_glyph_if_exist:NnTF \g_@@_curr_font_cmd_tl { \@@_to_usv:nn {\l_@@_remap_style_tl} {\l_@@_alphabet_tl} } + { + \@@_log:nx {setup-alph} {sym \l_@@_style_tl~(\l_@@_alphabet_tl)} + \@@_alphabet_config:nnn {\l_@@_style_tl} {\l_@@_alphabet_tl} {\l_@@_remap_style_tl} + } + { + \bool_if:NTF \l_@@_implicit_alph_bool + { + \seq_put_right:Nx \l_@@_missing_alph_seq + { + \@backslashchar sym \l_@@_style_tl \space + (\tl_use:c{c_@@_math_alphabet_name_ \l_@@_alphabet_tl _tl}) + } + } + { + \@@_alphabet_config:nnn {\l_@@_style_tl} {\l_@@_alphabet_tl} {up} + } + } + } + } + } + } +% \end{macrocode} +% \end{macro} +% +% Each alphabet style needs to be configured. +% This happens in Section~\ref{sec:setupalphabets}. +% \begin{macrocode} +\cs_new:Nn \@@_new_alphabet_config:nnn + { + \prop_if_exist:cF {g_@@_named_range_#1_prop} + { \@@_warning:nnn {no-named-range} {#1} {#2} } + + + \prop_gput:cnn {g_@@_named_range_#1_prop} { alpha_tl } + { + \prop_item:cn {g_@@_named_range_#1_prop} { alpha_tl } {#2} + } + % Q: do I need to bother removing duplicates? + +% \end{macrocode} +% Create list of all chars defined in this named range: +% \begin{macrocode} + \cs_new:cn { @@_config_#1_#2:n } + { + \clist_gclear_new:c {g_@@_named_slots_#1_#2_clist} + \tl_set:Nn \l_@@_curr_named_slot { g_@@_named_slots_#1_#2_clist } + #3 + \clist_gremove_duplicates:c {g_@@_named_slots_#1_#2_clist} + } + + } +% \end{macrocode} +% \begin{macrocode} +\cs_new:Nn \@@_alphabet_config:nnn + { + \use:c {@@_config_#1_#2:n} {#3} + } +% \end{macrocode} +% \begin{macrocode} +\prg_new_conditional:Nnn \@@_if_alphabet_exists:nn {T,TF} + { + \cs_if_exist:cTF {@@_config_#1_#2:n} + \prg_return_true: \prg_return_false: + } +% \end{macrocode} +% +% \subsection{Mapping `naked’ math characters} +% +% Before we show the definitions of the alphabet mappings using the functions +% |\@@_alphabet_config:nnn \l_@@_style_tl {##1} {...}|, we first want to define some functions +% to be used inside them to actually perform the character mapping. +% +% \subsubsection{Functions} +% +% \begin{macro}{\@@_map_char_single:nn} +% Wrapper for |\@@_map_char_noparse:nn| or |\@@_map_char_parse:nn| +% depending on the context. +% +% \begin{macro}{\@@_map_char_noparse:nn} +% \begin{macro}{\@@_map_char_parse:nn} +% \begin{macrocode} +\cs_new:Nn \@@_map_char_noparse:nn + { + \@@_set_mathcode:nnnn {#1} {\mathalpha} {\l_@@_symfont_label_tl} {#2} + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Nn \@@_map_char_parse:nn + { + \@@_if_char_spec:nNT {#1} {\mathalpha} + { \@@_map_char_noparse:nn {#1}{#2} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_map_char_single:nnn} +% \darg{char name (`dotlessi’)} +% \darg{from alphabet(s)} +% \darg{to alphabet} +% Logical interface to \cs{@@_map_char_single:nn}. +% \begin{macrocode} +\cs_new:Nn \@@_map_char_single:nnn + { + \@@_map_char_single:nn { \@@_to_usv:nn {#1} {#3} } + { \@@_to_usv:nn {#2} {#3} } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_map_chars_range:nnnn} +% \darg{Number of chars (26)} +% \darg{From style, one or more (it)} +% \darg{To style (up)} +% \darg{Alphabet name (Latin)} +% First the function with numbers: +% \begin{macrocode} +\cs_set:Nn \@@_map_chars_range:nnn + { + \int_step_inline:nnnn {0} {1} {#1-1} + { \@@_map_char_single:nn {#2+##1} {#3+##1} } + + \clist_gput_right:cx { \l_@@_curr_named_slot } + { \int_eval:n { #3 } - \int_eval:n { #3 + #1-1 } } + } +% \end{macrocode} +% And the wrapper with names: +% \begin{macrocode} +\cs_new:Nn \@@_map_chars_range:nnnn + { + \@@_map_chars_range:nnn {#1} { \@@_to_usv:nn {#2} {#4} } + { \@@_to_usv:nn {#3} {#4} } + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Functions for `normal’ alphabet symbols} +% +% \begin{macro}{\@@_set_normal_char:nnn} +% \begin{macrocode} +\cs_set:Nn \@@_set_normal_char:nnn + { + \@@_usv_if_exist:nnT {#3} {#1} + { + \clist_map_inline:nn {#2} + { + \@@_set_mathalphabet_pos:nnnn {normal} {#1} {##1} {#3} + \@@_map_char_single:nnn {##1} {#3} {#1} + + \clist_gput_right:cx {\l_@@_curr_named_slot} + { \int_eval:n { \@@_to_usv:nn {#3} {#1} } } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\cs_new:Nn \@@_set_normal_Latin:nn + { + \clist_map_inline:nn {#1} + { + \@@_set_mathalphabet_Latin:nnn {normal} {##1} {#2} + \@@_map_chars_range:nnnn {26} {##1} {#2} {Latin} + } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Nn \@@_set_normal_latin:nn + { + \clist_map_inline:nn {#1} + { + \@@_set_mathalphabet_latin:nnn {normal} {##1} {#2} + \@@_map_chars_range:nnnn {26} {##1} {#2} {latin} + } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Nn \@@_set_normal_greek:nn + { + \clist_map_inline:nn {#1} + { + \@@_set_mathalphabet_greek:nnn {normal} {##1} {#2} + \@@_map_chars_range:nnnn {25} {##1} {#2} {greek} + \@@_map_char_single:nnn {##1} {#2} {epsilon} + \@@_map_char_single:nnn {##1} {#2} {vartheta} + \@@_map_char_single:nnn {##1} {#2} {varkappa} + \@@_map_char_single:nnn {##1} {#2} {phi} + \@@_map_char_single:nnn {##1} {#2} {varrho} + \@@_map_char_single:nnn {##1} {#2} {varpi} + \@@_set_mathalphabet_pos:nnnn {normal} {epsilon} {##1} {#2} + \@@_set_mathalphabet_pos:nnnn {normal} {vartheta} {##1} {#2} + \@@_set_mathalphabet_pos:nnnn {normal} {varkappa} {##1} {#2} + \@@_set_mathalphabet_pos:nnnn {normal} {phi} {##1} {#2} + \@@_set_mathalphabet_pos:nnnn {normal} {varrho} {##1} {#2} + \@@_set_mathalphabet_pos:nnnn {normal} {varpi} {##1} {#2} + } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Nn \@@_set_normal_Greek:nn + { + \clist_map_inline:nn {#1} + { + \@@_set_mathalphabet_Greek:nnn {normal} {##1} {#2} + \@@_map_chars_range:nnnn {25} {##1} {#2} {Greek} + \@@_map_char_single:nnn {##1} {#2} {varTheta} + \@@_set_mathalphabet_pos:nnnn {normal} {varTheta} {##1} {#2} + } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Nn \@@_set_normal_numbers:nn + { + \@@_set_mathalphabet_numbers:nnn {normal} {#1} {#2} + \@@_map_chars_range:nnnn {10} {#1} {#2} {num} + } +% \end{macrocode} +% +% +% \subsection{Mapping chars inside a math style} +% +% \subsubsection{Functions for setting up the maths alphabets} +% +% \begin{macro}{\@@_set_mathalphabet_char:nnn} +% \darg{Maths alphabet, \eg, `bb’} +% \darg{Input slot, \eg, the slot for `A’ (comma separated)} +% \darg{Output slot, \eg, the slot for `$\mathbb{A}$’} +% This is a wrapper for either |\@@_mathmap_noparse:nnn| or +% |\@@_mathmap_parse:nnn|, depending on the context. +% \end{macro} +% +% \begin{macro}{\@@_mathmap_noparse:nnn} +% \darg{Maths alphabet, \eg, `bb’} +% \darg{Input slot, \eg, the slot for `A’ (comma separated)} +% \darg{Output slot, \eg, the slot for `$\mathbb{A}$’} +% Adds \cs{@@_set_mathcode:nnnn} declarations to the specified maths alphabet’s definition. +% \begin{macrocode} +\cs_new:Nn \@@_mathmap_noparse:nnn + { + \tl_gput_right:cx { g_@@_switchto_#1_tl } + { + \@@_set_mathcode:nnnn {#2} {\mathalpha} {\l_@@_symfont_label_tl} {#3} + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_mathmap_parse:nnn} +% \darg{Maths alphabet, \eg, `bb’} +% \darg{Input slot, \eg, the slot for `A’ (comma separated)} +% \darg{Output slot, \eg, the slot for `$\mathbb{A}$’} +% When \cmd\@@_if_char_spec:nNT\ is executed, it populates the \cmd\l_@@_mathmap_charints_clist\ +% macro with slot numbers corresponding to the specified range. This range is used to +% conditionally add \cs{@@_set_mathcode:nnnn} declaractions to the maths alphabet definition. +% \begin{macrocode} +\cs_new:Nn \@@_mathmap_parse:nnn + { + \exp_args:NNx \clist_if_in:NnT \l_@@_mathmap_charints_clist { \int_eval:n {#3} } + { + \@@_mathmap_noparse:nnn {#1} {#2} {#3} + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_set_mathalphabet_char:nnnn} +% \darg{math style command} +% \darg{input math alphabet name} +% \darg{output math alphabet name} +% \darg{char name to map} +% \begin{macrocode} +\cs_new:Nn \@@_set_mathalphabet_char:nnnn + { + \@@_set_mathalphabet_char:nnn {#1} { \@@_to_usv:nn {#2} {#4} } + { \@@_to_usv:nn {#3} {#4} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_set_mathalph_range:nnnn} +% \darg{Number of iterations} +% \darg{Sym command suffix} +% \darg{Starting input char} +% \darg{Starting output char} +% Loops through character ranges setting \cmd\mathcode. +% First the version that uses numbers: +% \begin{macrocode} +\cs_new:Nn \@@_set_mathalph_range:nnnn + { + \int_step_inline:nnnn {0} {1} {#1-1} + { \@@_set_mathalphabet_char:nnn {#2} { ##1 + #3 } { ##1 + #4 } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_set_mathalph_range:nnnn} +% \darg{Number of iterations} +% \darg{Sym command suffix} +% \darg{input style} +% \darg{output style} +% \darg{alphabet} +% Then the wrapper version that uses names: +% \begin{macrocode} +\cs_new:Nn \@@_set_mathalph_range:nnnnn + { + \clist_gput_right:cx { \l_@@_curr_named_slot } + { \int_eval:n { \@@_to_usv:nn {#4} {#5} } - \int_eval:n { (#1-1)+\@@_to_usv:nn {#4} {#5} } } + + \@@_set_mathalph_range:nnnn {#1} {#2} { \@@_to_usv:nn {#3} {#5} } + { \@@_to_usv:nn {#4} {#5} } + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Individual mapping functions for different alphabets} +% +% \begin{macrocode} +\cs_new:Nn \@@_set_mathalphabet_pos:nnnn + { + \@@_usv_if_exist:nnT {#4} {#2} + { + \clist_map_inline:nn {#3} + { \@@_set_mathalphabet_char:nnnn {#1} {##1} {#4} {#2} } + + \clist_gput_right:cx {\l_@@_curr_named_slot} + { \int_eval:n { \@@_to_usv:nn {#4} {#2} } } + } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Nn \@@_set_mathalphabet_numbers:nnn + { + \clist_map_inline:nn {#2} + { \@@_set_mathalph_range:nnnnn {10} {#1} {##1} {#3} {num} } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Nn \@@_set_mathalphabet_Latin:nnn + { + \clist_map_inline:nn {#2} + { \@@_set_mathalph_range:nnnnn {26} {#1} {##1} {#3} {Latin} } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Nn \@@_set_mathalphabet_latin:nnn + { + \clist_map_inline:nn {#2} + { + \@@_set_mathalph_range:nnnnn {26} {#1} {##1} {#3} {latin} + \@@_set_mathalphabet_char:nnnn {#1} {##1} {#3} {h} + } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Nn \@@_set_mathalphabet_Greek:nnn + { + \clist_map_inline:nn {#2} + { + \@@_set_mathalph_range:nnnnn {25} {#1} {##1} {#3} {Greek} + \@@_set_mathalphabet_char:nnnn {#1} {##1} {#3} {varTheta} + } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Nn \@@_set_mathalphabet_greek:nnn + { + \clist_map_inline:nn {#2} + { + \@@_set_mathalph_range:nnnnn {25} {#1} {##1} {#3} {greek} + \@@_set_mathalphabet_char:nnnn {#1} {##1} {#3} {epsilon} + \@@_set_mathalphabet_char:nnnn {#1} {##1} {#3} {vartheta} + \@@_set_mathalphabet_char:nnnn {#1} {##1} {#3} {varkappa} + \@@_set_mathalphabet_char:nnnn {#1} {##1} {#3} {phi} + \@@_set_mathalphabet_char:nnnn {#1} {##1} {#3} {varrho} + \@@_set_mathalphabet_char:nnnn {#1} {##1} {#3} {varpi} + } + } +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} + +\endinput + +% /© +% +% ------------------------------------------------ +% The UNICODE-MATH package <wspr.io/unicode-math> +% ------------------------------------------------ +% 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): <http://www.latex-project.org/lppl/>. +% ------------------------------------------------ +% Copyright 2006-2019 Will Robertson, LPPL "maintainer" +% Copyright 2010-2017 Philipp Stephani +% Copyright 2011-2017 Joseph Wright +% Copyright 2012-2015 Khaled Hosny +% ------------------------------------------------ +% +% ©/ |