% \section{User commands}\label{sec:codeuser} % % This section contains the definitions of the commands detailed in % the user documentation. Only the `top level' definitions of the % commands are contained herein; they all use or define macros which % are defined or used later on in \vref{sec:codeinternal}. % % \iffalse % \begin{macrocode} %<*fontspec&(xetexx|luatex)> % \end{macrocode} % \fi % % \subsubsection{Font selection} % \begin{macro}{\fontspec} % This is the main command of the package that % selects fonts with various features. It takes two arguments: the % font name and the optional requested features of that % font. Then this new font family is selected. % \begin{macrocode} \NewDocumentCommand \fontspec { O{} m O{} } { \@@_main_fontspec:nnn {#1} {#2} {#3} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_fontspec:nnn { \fontspec_set_family:Nnn \f@family {#1,#3} {#2} \fontencoding { \l_@@_nfss_enc_tl } \selectfont \ignorespaces } % \end{macrocode} % \end{macro} % % \begin{macro}{\setmainfont} % The following three macros perform equivalent operations setting % the default font for a % particular family: `roman', sans serif, or typewriter % (monospaced). I end them with |\normalfont| so that if they're % used in the document, the change registers immediately. % \begin{macrocode} \DeclareDocumentCommand \setmainfont { O{} m O{} } { \@@_main_setmainfont:nnn {#1} {#2} {#3} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_setmainfont:nnn { \fontspec_set_family:Nnn \g_@@_rmfamily_family {#1,#3} {#2} \tl_set_eq:NN \rmdefault \g_@@_rmfamily_family \use:x { \exp_not:n { \DeclareRobustCommand \rmfamily } { \exp_not:N \fontencoding { \l_@@_nfss_enc_tl } \exp_not:N \fontfamily { \g_@@_rmfamily_family } \exp_not:N \selectfont } } \str_if_eq_x:nnT {\familydefault} {\rmdefault} { \tl_set_eq:NN \encodingdefault \l_@@_nfss_enc_tl } \normalfont \ignorespaces } % \end{macrocode} % \end{macro} % % \begin{macro}{\setsansfont} % \begin{macrocode} \DeclareDocumentCommand \setsansfont { O{} m O{} } { \@@_main_setsansfont:nnn {#1} {#2} {#3} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_setsansfont:nnn { \fontspec_set_family:Nnn \g_@@_sffamily_family {#1,#3} {#2} \tl_set_eq:NN \sfdefault \g_@@_sffamily_family \use:x { \exp_not:n { \DeclareRobustCommand \sffamily } { \exp_not:N \fontencoding { \l_@@_nfss_enc_tl } \exp_not:N \fontfamily { \g_@@_sffamily_family } \exp_not:N \selectfont } } \str_if_eq_x:nnT {\familydefault} {\sfdefault} { \tl_set_eq:NN \encodingdefault \l_@@_nfss_enc_tl } \normalfont \ignorespaces } % \end{macrocode} % \end{macro} % % \begin{macro}{\setmonofont} % \begin{macrocode} \DeclareDocumentCommand \setmonofont { O{} m O{} } { \@@_main_setmonofont:nnn {#1} {#2} {#3} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_setmonofont:nnn { \fontspec_set_family:Nnn \g_@@_ttfamily_family {#1,#3} {#2} \tl_set_eq:NN \ttdefault \g_@@_ttfamily_family \use:x { \exp_not:n { \DeclareRobustCommand \ttfamily } { \exp_not:N \fontencoding { \l_@@_nfss_enc_tl } \exp_not:N \fontfamily { \g_@@_ttfamily_family } \exp_not:N \selectfont } } \str_if_eq_x:nnT {\familydefault} {\ttdefault} { \tl_set_eq:NN \encodingdefault \l_@@_nfss_enc_tl } \normalfont \ignorespaces } % \end{macrocode} % \end{macro} % % % \begin{macro}{\setromanfont} % This is the old name for \cs{setmainfont}, retained \emph{ad infinitum} % for backwards compatibility. It was deprecated in 2010. % \begin{macrocode} \DeclareDocumentCommand \setromanfont { O{} m O{} } { \@@_main_setmainfont:nnn {#1} {#2} {#3} } % \end{macrocode} % \end{macro} % % % \begin{macro}{\setmathrm} % \begin{macro}{\setmathsf} % \begin{macro}{\setboldmathrm} % \begin{macro}{\setmathtt} % These commands are analogous to \cmd\setmainfont\ and others, % but for selecting the font used for \cmd\mathrm, \etc. They % can only be used in the preamble of the % document. \cmd\setboldmathrm\ is used for specifying which % fonts should be used in \cmd\boldmath. % \begin{macrocode} \DeclareDocumentCommand \setmathrm { O{} m O{} } { \@@_main_setmathrm:nnn {#1} {#2} {#3} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_setmathrm:nnn { \fontspec_set_family:Nnn \g_@@_mathrm_tl {#1} {#2} } % \end{macrocode} % % \begin{macrocode} \DeclareDocumentCommand \setboldmathrm { O{} m O{} } { \@@_main_setboldmathrm:nnn {#1} {#2} {#3} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_setboldmathrm:nnn { \fontspec_set_family:Nnn \g_@@_bfmathrm_tl {#1} {#2} } % \end{macrocode} % % \begin{macrocode} \DeclareDocumentCommand \setmathsf { O{} m O{} } { \@@_main_setmathsf:nnn {#1} {#2} {#3} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_setmathsf:nnn { \fontspec_set_family:Nnn \g_@@_mathsf_tl {#1} {#2} } % \end{macrocode} % % \begin{macrocode} \DeclareDocumentCommand \setmathtt { O{} m O{} } { \@@_main_setmathtt:nnn {#1} {#2} {#3} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_setmathtt:nnn { \fontspec_set_family:Nnn \g_@@_mathtt_tl {#1} {#2} } % \end{macrocode} % % \begin{macrocode} \@onlypreamble\setmathrm \@onlypreamble\setboldmathrm \@onlypreamble\setmathsf \@onlypreamble\setmathtt % \end{macrocode} % If the commands above are not executed, then \cmd\rmdefault\ (\etc) % will be used. % \begin{macrocode} \tl_set:Nn \g_@@_mathrm_tl {\rmdefault} \tl_set:Nn \g_@@_mathsf_tl {\sfdefault} \tl_set:Nn \g_@@_mathtt_tl {\ttdefault} % \end{macrocode} % \end{macro} \end{macro} \end{macro} % \end{macro} % % \begin{macro}{\newfontfamily} % This macro takes the arguments of \cs{fontspec} with a prepended % \meta{instance cmd}. This command is used % when a specific font instance needs to be referred to repetitively % (\eg, in a section heading) since continuously calling % \cs{fontspec_select:nn} is inefficient because it must parse the % option arguments every time. % % \cs{fontspec_select:nn} defines a font family and saves its name in % \cs{l_fontspec_family_tl}. This family is then used in a typical NFSS \cmd\fontfamily\ % declaration, saved in the macro name specified. % \begin{macrocode} \DeclareDocumentCommand \newfontfamily { m O{} m O{} } { \@@_main_newfontfamily:nnnn {#1} {#2} {#3} {#4} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_newfontfamily:nnnn { \fontspec_set_family:cnn { g_@@_ \cs_to_str:N #1 _family } {#2,#4} {#3} \use:x { \exp_not:N \DeclareRobustCommand \exp_not:N #1 { \exp_not:N \fontfamily { \use:c {g_@@_ \cs_to_str:N #1 _family} } \exp_not:N \fontencoding { \l_@@_nfss_enc_tl } \exp_not:N \selectfont } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\newfontface} % \cmd\newfontface\ uses the fact that if the argument to \feat{BoldFont}, etc., is empty (\ie, |BoldFont={}|), then no bold font is searched for. % \begin{macrocode} \DeclareDocumentCommand \newfontface { m O{} m O{} } { \@@_main_newfontface:nnnn {#1} {#2} {#3} {#4} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_newfontface:nnnn { \newfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2,#4 ] {#3} } % \end{macrocode} % \end{macro} % % \subsubsection{Font feature selection} % % \begin{macro}{\defaultfontfeatures} % This macro takes one argument that consists of all of feature % options that will be applied by default to all subsequent % \cs{fontspec}, et al., commands. It stores its value in % \cs{g_fontspec_default_fontopts_tl} (initialised empty), which is % concatenated with the individual macro choices in the % [...] macro. % % \begin{macrocode} \DeclareDocumentCommand \defaultfontfeatures { t+ o m } { \IfNoValueTF {#2} { \@@_set_default_features:nn {#1} {#3} } { \@@_set_font_default_features:nnn {#1} {#2} {#3} } \ignorespaces } \cs_new:Nn \@@_set_default_features:nn { \IfBooleanTF {#1} \clist_put_right:Nn \clist_set:Nn \g_@@_default_fontopts_clist {#2} } % \end{macrocode} % The optional argument specifies a font identifier. % Branch for either (a)~single token input such as \verb|\rmdefault|, or (b)~otherwise assume its a fontname. % In that case, strip spaces and file extensions and lower-case to ensure consistency. % \begin{macrocode} \cs_new:Nn \@@_set_font_default_features:nnn { \clist_map_inline:nn {#2} { \tl_if_single:nTF {##1} { \tl_set:No \l_@@_tmp_tl { \cs:w g_@@_ \cs_to_str:N ##1 _family\cs_end: } } { \@@_sanitise_fontname:Nn \l_@@_tmp_tl {##1} } \IfBooleanTF {#1} { \prop_get:NVNF \g_@@_fontopts_prop \l_@@_tmp_tl \l_@@_tmpb_tl { \tl_clear:N \l_@@_tmpb_tl } \tl_put_right:Nn \l_@@_tmpb_tl {#3,} \prop_gput:NVV \g_@@_fontopts_prop \l_@@_tmp_tl \l_@@_tmpb_tl } { \tl_if_empty:nTF {#3} { \prop_gremove:NV \g_@@_fontopts_prop \l_@@_tmp_tl } { \prop_put:NVn \g_@@_fontopts_prop \l_@@_tmp_tl {#3,} } } } } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\addfontfeatures} % In order to be able to extend the feature selection of % a given font, two things need to be known: the currently selected % features, and the currently selected font. Every time a font % family is created, this information is saved inside a control % sequence with the name of the font family itself. % % This macro extracts this information, then appends the requested % font features to add to the already existing ones, and calls the % font again with the top level \cs{fontspec} command. % % The default options are \emph{not} applied (which is why % \cs{g_fontspec_default_fontopts_tl} is emptied inside the group; this is allowed % as \cmd\l_fontspec_family_tl\ is globally defined in \cmd\@@_select_font_family:nn), so this % means that the only added features to the font are strictly those % specified by this command. % % \cs{addfontfeature} is defined as an alias, as I found that I % often typed this instead when adding only a single font feature. % \begin{macrocode} \DeclareDocumentCommand \addfontfeatures {m} { \@@_main_addfontfeatures:n {#1} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_addfontfeatures:n { % \typeout{^^J::::::::::::::::::::::::::::::::::^^J: addfontfeatures} \fontspec_if_fontspec_font:TF { \group_begin: \keys_set_known:nnN {fontspec-addfeatures} {#1} \l_@@_tmp_tl \prop_get:cnN {g_@@_ \f@family _prop} {options} \l_@@_options_tl \prop_get:cnN {g_@@_ \f@family _prop} {fontname} \l_@@_fontname_tl \bool_set_true:N \l_@@_disable_defaults_bool % \typeout{ \@@_select_font_family:nn { \l_@@_options_tl , #1 } {\l_@@_fontname_tl} } \use:x { \@@_select_font_family:nn { \l_@@_options_tl , #1 } {\l_@@_fontname_tl} } \group_end: \fontfamily\l_fontspec_family_tl\selectfont } { \@@_warning:nx {addfontfeatures-ignored} {#1} } \ignorespaces } \cs_set_eq:NN \addfontfeature \addfontfeatures % \end{macrocode} % \end{macro} % % \subsubsection{Defining new font features} % % \begin{macro}{\newfontfeature} % \cs{newfontfeature} takes two arguments: the name of the feature % tag by which to reference it, and the string that is used to % select the font feature. % \begin{macrocode} \DeclareDocumentCommand \newfontfeature {mm} { \@@_main_newfontfeature:nn {#1} {#2} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_newfontfeature:nn { \keys_define:nn { fontspec } { #1 .code:n = { \@@_update_featstr:n {#2} } } } % \end{macrocode} % \end{macro} % % % \begin{macro}{\newAATfeature} % This command assigns a new AAT feature by its code (|#2|,|#3|) to a new name (|#1|). % Better than \cmd\newfontfeature\ because it checks if the feature exists in the % font it's being used for. % \begin{macrocode} \DeclareDocumentCommand \newAATfeature {mmmm} { \@@_main_newAATfeature:nnnn {#1} {#2} {#3} {#4} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_newAATfeature:nnnn { \keys_if_exist:nnF { fontspec } {#1} { \@@_define_aat_feature_group:n {#1} } \keys_if_choice_exist:nnnT {fontspec} {#1} {#2} { \@@_warning:nxx {feature-option-overwrite} {#1} {#2} } \@@_define_aat_feature:nnnn {#1}{#2}{#3}{#4} } % \end{macrocode} % \end{macro} % % \begin{macro}{\newopentypefeature} % This command assigns a new OpenType feature by its abbreviation (|#2|) to a new name (|#1|). % Better than \cmd\newfontfeature\ because it checks if the feature exists in the % font it's being used for. % \begin{macrocode} \DeclareDocumentCommand \newopentypefeature {mmm} { \@@_main_newopentypefeature:nnn {#1} {#2} {#3} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_newopentypefeature:nnn { \keys_if_exist:nnF { fontspec / options } {#1} { \@@_define_opentype_feature_group:n {#1} } \keys_if_choice_exist:nnnT {fontspec} {#1} {#2} { \@@_warning:nxx {feature-option-overwrite} {#1} {#2} } \exp_args:Nnnx \@@_define_opentype_feature:nnnnn {#1} {#2} { \@@_strip_plus_minus:n {#3} } {#3} {} } % \end{macrocode} % % \begin{macrocode} \cs_new:Nn \@@_strip_plus_minus:n { \@@_strip_plus_minus_aux:Nq #1 \q_nil } \cs_new:Npn \@@_strip_plus_minus_aux:Nq #1#2 \q_nil { \str_case:nnF {#1} { {+} {#2} {-} {#2} } {#1#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{\newICUfeature} % Deprecated. % \begin{macrocode} \DeclareDocumentCommand \newICUfeature {mmm} { \@@_main_newopentypefeature:nnn {#1} {#2} {#3} } % \end{macrocode} % \end{macro} % % % \begin{macro}{\aliasfontfeature} % User commands for renaming font features and font feature options. % \begin{macrocode} \DeclareDocumentCommand \aliasfontfeature {mm} { \@@_main_aliasfontfeature:nn {#1} {#2} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_aliasfontfeature:nn { % \typeout{::::::::::::::::::::^^J:: aliasfontfeature{#1}{#2}} \bool_set_false:N \l_@@_alias_bool \clist_map_inline:Nn \g_@@_all_keyval_modules_clist { \keys_if_exist:nnT {##1} {#1} { % \typeout{:::: Key~exists~##1~/~#1} \bool_set_true:N \l_@@_alias_bool \keys_define:nn {##1} { #2 .code:n = { \keys_set:nn {##1} { #1 = {####1} } } } } } \bool_if:NF \l_@@_alias_bool { \@@_warning:nx {rename-feature-not-exist} {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\aliasfontfeatureoption} % \begin{macrocode} \DeclareDocumentCommand \aliasfontfeatureoption {mmm} { \@@_main_aliasfontfeatureoption:nnn {#1} {#2} {#3} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_aliasfontfeatureoption:nnn { \bool_set_false:N \l_@@_alias_bool \clist_map_inline:Nn \g_@@_all_keyval_modules_clist { \keys_if_exist:nnT { ##1 / #1 } {#2} { % \typeout{:::: Keyval~exists~##1~/~#1~=~#2} \bool_set_true:N \l_@@_alias_bool \keys_define:nn { ##1 / #1 } { #3 .code:n = { \keys_set:nn {##1} { #1 = {#2} } } } } \keys_if_exist:nnT { ##1 / #1 } {#2Reset} { % \typeout{:::: Keyval~exists~##1~/~#1~=~#2Reset} \keys_define:nn { ##1 / #1 } { #3Reset .code:n = { \keys_set:nn {##1} { #1 = {#2Reset} } } } } \keys_if_exist:nnT { ##1 / #1 } {#2Off} { % \typeout{:::: Keyval~exists~##1~/~#1~=~#2Off} \keys_define:nn { ##1 / #1 } { #3Off .code:n = { \keys_set:nn {##1} { #1 = {#2Off} } } } } } \bool_if:NF \l_@@_alias_bool { \@@_warning:nx {rename-feature-not-exist} {#1/#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\newfontscript} % Mostly used internally, but also possibly useful for users, to define new OpenType % `scripts', mapping logical names to OpenType script tags. % \begin{macrocode} \DeclareDocumentCommand \newfontscript {mm} { \fontspec_new_script:nn {#1} {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{\newfontlanguage} % Mostly used internally, but also possibly useful for users, to define new OpenType % `languages', mapping logical names to OpenType language tags. % \begin{macrocode} \DeclareDocumentCommand \newfontlanguage {mm} { \fontspec_new_lang:nn {#1} {#2} } % \end{macrocode} % \end{macro} % % % \begin{macro}{\DeclareFontsExtensions} % \texttt{dfont} would never be uppercase, right? % \begin{macrocode} \DeclareDocumentCommand \DeclareFontsExtensions {m} { \@@_main_DeclareFontsExtensions:n {#1} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_DeclareFontsExtensions:n { \clist_set:Nn \l_@@_extensions_clist { #1 } \tl_remove_all:Nn \l_@@_extensions_clist {~} } \DeclareFontsExtensions{.otf,.ttf,.OTF,.TTF,.ttc,.TTC,.dfont} % \end{macrocode} % \end{macro} % \begin{macro}{\IfFontFeatureActiveTF} % \begin{macrocode} \DeclareDocumentCommand \IfFontFeatureActiveTF {mmm} { \@@_main_IfFontFeatureActiveTF:nnn {#1} {#2} {#3} } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_main_IfFontFeatureActiveTF:nnn { % \typeout{^^J:::::::::::::::::::::::::::::::::::::::::::::::} % \typeout{:IfFontFeatureActiveTF \exp_not:n{{#1}{#2}{#3}}} \@@_if_font_feature:nTF {#1} {#2} {#3} } % \end{macrocode} % % \begin{macrocode} \prg_new_conditional:Nnn \@@_if_font_feature:n {TF} { \tl_gclear:N \g_@@_single_feat_tl \group_begin: \@@_font_suppress_not_found_error: \@@_init: \bool_set_true:N \l_@@_ot_bool \bool_set_true:N \l_@@_never_check_bool \bool_set_false:N \l_@@_firsttime_bool \clist_clear:N \l_@@_fontfeat_clist \@@_get_features:Nn \l_@@_rawfeatures_sclist {#1} \group_end: % \typeout{:::> \exp_not:N\l_@@_rawfeatures_sclist->~{\l_@@_rawfeatures_sclist}} % \typeout{:::> \exp_not:N\g_@@_single_feat_tl->~{\g_@@_single_feat_tl}} \tl_if_empty:NTF \g_@@_single_feat_tl { \prg_return_false: } { \exp_args:NV \fontspec_if_current_feature:nTF \g_@@_single_feat_tl { \prg_return_true: } { \prg_return_false: } } } % \end{macrocode} % \end{macro} % % \iffalse % \begin{macrocode} % % \end{macrocode} % \fi