%%^^A%% fontspec-code-keyval.dtx -- part of FONTSPEC % \section{Font loading (\pkg{keyval}) definitions} % % \iffalse % \begin{macrocode} %<*fontspec> % \end{macrocode} % \fi % % This package uses a large number of keyval modules which operate sequentially on keyval % input to ensure priority. % \begin{macrocode} \clist_gset:Nn \g_@@_all_keyval_modules_clist { fontspec, fontspec-opentype, fontspec-aat, fontspec-preparse, fontspec-preparse-cfg, fontspec-preparse-external, fontspec-preparse-nested, fontspec-renderer } % \end{macrocode} % % Wrapper function to save some characters in the source: % \begin{macrocode} \cs_new:Nn \@@_keys_define_code:nnn { \keys_define:nn {#1} { #2 .code:n = {#3} } } % \end{macrocode} % % For catching features that cannot be used in |\addfontfeatures|: % \begin{macrocode} \cs_new:Nn \@@_aff_error:n { \@@_keys_define_code:nnn {fontspec-addfeatures} {#1} { \@@_error:nx {not-in-addfontfeatures} {#1} } } % \end{macrocode} % % \subsection{Pre-pre-parsing stages} % % These features are extracted from the font feature list before all others. % % \paragraph{Don't load font config file} % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse-cfg} {IgnoreFontspecFile} { \bool_set_false:N \l_@@_fontcfg_bool } \@@_keys_define_code:nnn {fontspec-preparse-external} {IgnoreFontspecFile} { \bool_set_false:N \l_@@_fontcfg_bool } % \end{macrocode} % % \begin{macro}{Path} % For fonts that aren't installed in the system. If no argument is given, the font is located % with |kpsewhich|; it's either in the current directory or the \TeX\ tree. Otherwise, the % argument given defines the file path of the font. % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse-external} {Path} { \bool_set_true:N \l_@@_nobf_bool \bool_set_true:N \l_@@_noit_bool \bool_set_true:N \l_@@_external_bool \tl_set:Nn \l_@@_font_path_tl {#1} \bool_lazy_and:nnTF { \l_@@_external_kpse_bool } { \tl_if_empty_p:N \l_@@_font_path_tl } { \@@_font_is_kpse: } { \@@_font_is_file: } %<*XE> \keys_set:nn {fontspec-renderer} {Renderer=OpenType} % } \aliasfontfeature{Path}{ExternalLocation} \@@_keys_define_code:nnn {fontspec} {Path} {} % \end{macrocode} % \end{macro} % % \paragraph{\feat{Extension}} % For fonts that aren't installed in the system. Specifies the font extension % to use. % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse-external} {Extension} { \tl_set:Nn \l_@@_extension_tl {#1} \bool_if:NF \l_@@_external_bool { \keys_set:nn {fontspec-preparse-external} {Path} } } \tl_clear:N \l_@@_extension_tl \@@_keys_define_code:nnn {fontspec} {Extension} {} % \end{macrocode} % % \paragraph{\feat{KpseOnly}} % If the font is specified by filename, only search for it through kpse. % \XeTeX\ does not support finding system fonts by filename so this is always implicitly set % there. % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse-external} {KpseOnly} { \bool_set_true:N \l_@@_external_kpse_bool \bool_if:NT \l_@@_external_bool { \@@_font_is_kpse: } } \@@_keys_define_code:nnn {fontspec} {KpseOnly} {} % \end{macrocode} % % % \paragraph{\feat{Renderer}} % This feature must be processed before all others (the other font shape and features % options are also pre-parsed for convenience) because the renderer determines the format % of the features and whether certain features are available. % \begin{macrocode} %<*XE> \keys_define:nn {fontspec-renderer} { Renderer .choices:nn = {AAT,ICU,OpenType,Graphite,Full,Basic,Node,Base,HarfBuzz,Harfbuzz} { \int_compare:nTF {\l_keys_choice_int <= 4} { \tl_set:Nx \l_@@_renderer_tl { \int_case:nn \l_keys_choice_int { 1 {/AAT} 2 {/OT} 3 {/OT} 4 {/GR} } } %\typeout{Renderer:~ \l_@@_renderer_tl} \tl_gset:Nx \g_@@_single_feat_tl { \l_@@_renderer_tl } } { \@@_warning:nx {only-luatex-feature} {Renderer=Full/Basic/Node/Base/HarfBuzz} } } } % %<*LU> \keys_define:nn {fontspec-renderer} { Renderer .choices:nn = {Full,Node,Basic,Base,HarfBuzz,Harfbuzz,OpenType,AAT,Graphite} { \int_compare:nT {\l_keys_choice_int >= 5} { \bool_set_true:N \l_@@_harfbuzz_bool } \tl_set:Nx \l_@@_mode_tl { \int_case:nn \l_keys_choice_int { 1 {node} 2 {node} 3 {base} 4 {base} 5 {harf} 6 {harf} 7 {harf} 8 {harf} 9 {harf}} } \tl_set:Nx \l_@@_shaper_tl { \int_case:nn \l_keys_choice_int { 1 {} 2 {} 3 {} 4 {} 5 {} 6 {} 7 {ot} 8 {coretext_aat} 9 {graphite2} } } %\typeout{Mode:~"\l_@@_mode_tl"~/~Shaper:~"\l_@@_shaper_tl"} \tl_gset:Nx \g_@@_single_feat_tl { mode=\l_@@_mode_tl ; \tl_if_empty:NF \l_@@_shaper_tl { shaper=\l_@@_shaper_tl} } } , Renderer unknown .code:n = { \bool_set_true:N \l_@@_harfbuzz_bool \@@_warning:nx {unknown-renderer} {#1} \tl_set:Nn \l_@@_mode_tl {harf} \tl_set:Nn \l_@@_shaper_tl {#1} } , } % % \end{macrocode} % % \subsection{Pre-parsed features} % % \paragraph{OpenType script/language} % See later for the resolutions from \pkg{fontspec} features to OpenType definitions. % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse} {Script} { % \keys_set:nn {fontspec-renderer} {Renderer=OpenType} \tl_set:Nn \l_@@_script_name_tl {#1} } % \end{macrocode} % Exactly the same: % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse} {Language} { % \keys_set:nn {fontspec-renderer} {Renderer=OpenType} \tl_set:Nn \l_@@_lang_name_tl {#1} } % \end{macrocode} % % % \paragraph{TTC font index} % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse} {FontIndex} { \str_if_eq:eeF { \str_lowercase:f {\l_@@_extension_tl} } {.ttc} { \@@_warning:n {font-index-needs-ttc} } % \tl_set:Nn \l_@@_ttc_index_tl {:#1} % \tl_set:Nn \l_@@_ttc_index_tl {(#1)} } \@@_keys_define_code:nnn {fontspec} {FontIndex} { % \tl_set:Nn \l_@@_ttc_index_tl {:#1} % \tl_set:Nn \l_@@_ttc_index_tl {(#1)} } % \end{macrocode} % % \subsection{Font faces} % % \paragraph{Upright} % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse-external} {UprightFont} { \fontspec_complete_fontname:Nn \l_@@_fontname_up_tl {#1} } % \end{macrocode} % % \paragraph{Italic and slanted} % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse-external} {ItalicFont} { \tl_if_empty:nTF {#1} { \bool_set_true:N \l_@@_noit_bool } { \bool_set_false:N \l_@@_noit_bool \fontspec_complete_fontname:Nn \l_@@_fontname_it_tl {#1} } } % \end{macrocode} % % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse-external} {SlantedFont} { \fontspec_complete_fontname:Nn \l_@@_fontname_sl_tl {#1} } % \end{macrocode} % % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse-external} {SwashFont} { \fontspec_complete_fontname:Nn \l_@@_fontname_sw_tl {#1} } % \end{macrocode} % % % \paragraph{Bold (NFSS) Series} % By default, \pkg{fontspec} uses the default bold series, \cs{bfdefault}. % We want to be able to make this extensible. This code is not yet functional! % \begin{macrocode} %\@@_keys_define_code:nnn {fontspec-preparse-external} {BoldSeries} % { % \tl_gset:Nx \g_@@_curr_series_tl { #1 } % \seq_put_right:Nx \l_@@_bf_series_seq { #1 } % } % \end{macrocode} % % \paragraph{Bold} % This contains some stubb code to allow more than one bold font to be loaded. % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse-external} {BoldFont} { \tl_if_empty:nTF {#1} { \bool_set_true:N \l_@@_nobf_bool } { \bool_set_false:N \l_@@_nobf_bool \fontspec_complete_fontname:Nn \l_@@_curr_bfname_tl {#1} \seq_if_empty:NT \l_@@_bf_series_seq { \tl_gset:Nx \g_@@_curr_series_tl {\bfdefault} \seq_put_right:Nx \l_@@_bf_series_seq {\bfdefault} } \tl_if_eq:oxT \g_@@_curr_series_tl {\bfdefault} { \tl_set_eq:NN \l_@@_fontname_bf_tl \l_@@_curr_bfname_tl } \prop_put:NxV \l_@@_nfss_prop {BoldFont-\g_@@_curr_series_tl} \l_@@_curr_bfname_tl %\typeout{Setting~bold~font~"\l_@@_curr_bfname_tl"~with~series~"\g_@@_curr_series_tl"} } } % \end{macrocode} % % \paragraph{Bold italic/slanted} % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse-external} {BoldItalicFont} { \fontspec_complete_fontname:Nn \l_@@_fontname_bfit_tl {#1} } % \end{macrocode} % % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse-external} {BoldSlantedFont} { \fontspec_complete_fontname:Nn \l_@@_fontname_bfsl_tl {#1} } % \end{macrocode} % % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse-external} {BoldSwashFont} { \fontspec_complete_fontname:Nn \l_@@_fontname_bfsw_tl {#1} } % \end{macrocode} % % \paragraph{Small caps} % Small caps isn't pre-parsed because it can vary with others above: % \begin{macrocode} \@@_keys_define_code:nnn {fontspec} {SmallCapsFont} { \tl_if_empty:nTF {#1} { \bool_set_true:N \l_@@_nosc_bool } { \bool_set_false:N \l_@@_nosc_bool \fontspec_complete_fontname:Nn \l_@@_fontname_sc_tl {#1} } } % \end{macrocode} % % % \subsubsection{Preparsed font features} % % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse} {UprightFeatures} { \clist_put_right:Nn \l_@@_fontfeat_up_clist {#1} } \@@_keys_define_code:nnn {fontspec-preparse} {BoldFeatures} { \clist_put_right:Nn \l_@@_fontfeat_bf_clist {#1} % \prop_put:NxV \l_@@_nfss_prop % {BoldFont-\g_@@_curr_series_tl} \l_@@_curr_bfname_tl } \@@_keys_define_code:nnn {fontspec-preparse} {ItalicFeatures} { \clist_put_right:Nn \l_@@_fontfeat_it_clist {#1} } \@@_keys_define_code:nnn {fontspec-preparse} {BoldItalicFeatures} { \clist_put_right:Nn \l_@@_fontfeat_bfit_clist {#1} } \@@_keys_define_code:nnn {fontspec-preparse} {SlantedFeatures} { \clist_put_right:Nn \l_@@_fontfeat_sl_clist {#1} } \@@_keys_define_code:nnn {fontspec-preparse} {BoldSlantedFeatures} { \clist_put_right:Nn \l_@@_fontfeat_bfsl_clist {#1} } \@@_keys_define_code:nnn {fontspec-preparse} {SwashFeatures} { \clist_put_right:Nn \l_@@_fontfeat_sw_clist {#1} } \@@_keys_define_code:nnn {fontspec-preparse} {BoldSwashFeatures} { \clist_put_right:Nn \l_@@_fontfeat_bfsw_clist {#1} } % \end{macrocode} % Note that small caps features can vary by shape, so these in fact \emph{aren't} pre-parsed. % \begin{macrocode} \@@_keys_define_code:nnn {fontspec} {SmallCapsFeatures} { \bool_if:NF \l_@@_firsttime_bool { \clist_put_right:Nn \l_@@_fontfeat_sc_clist {#1} } } % \end{macrocode} % % \paragraph{Features varying by size} % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse} {SizeFeatures} { \clist_set:Nn \l_@@_sizefeat_clist {#1} \clist_put_right:Nn \l_@@_fontfeat_up_clist { SizeFeatures = {#1} } } \@@_keys_define_code:nnn {fontspec-preparse-nested} {SizeFeatures} { \clist_set:Nn \l_@@_sizefeat_clist {#1} \tl_if_empty:NT \l_@@_this_font_tl { \tl_set:Nn \l_@@_this_font_tl { -- } } % needs to be non-empty as a flag } \@@_keys_define_code:nnn {fontspec-preparse-nested} {Font} { \tl_set:Nn \l_@@_this_font_tl {#1} } \@@_keys_define_code:nnn {fontspec} {SizeFeatures} { % dummy } \@@_keys_define_code:nnn {fontspec} {Font} { % dummy } % \end{macrocode} % % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-sizing} {Size} { \tl_set:Nn \l_@@_size_tl {#1} } \@@_keys_define_code:nnn {fontspec-sizing} {Font} { \fontspec_complete_fontname:Nn \l_@@_sizedfont_tl {#1} } % \end{macrocode} % % A hack to fix a test, needs to be investigated why necessary! % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-opentype} {UprightFont} {} \@@_keys_define_code:nnn {fontspec-opentype} {ItalicFont} {} \@@_keys_define_code:nnn {fontspec-opentype} {SlantedFont} {} \@@_keys_define_code:nnn {fontspec-opentype} {BoldFont} {} \@@_keys_define_code:nnn {fontspec-opentype} {BoldItalicFont} {} \@@_keys_define_code:nnn {fontspec-opentype} {BoldSlantedFont} {} % \end{macrocode} % % % % \subsection{General font-independent features} % % These features can be applied to any font. % % \paragraph{NFSS encoding} % For the very brave. % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse} {NFSSEncoding} { \tl_gset:Nx \g_@@_nfss_enc_tl { #1 } } % \end{macrocode} % % \paragraph{NFSS family} % Interactions with other packages will sometimes require setting the NFSS family explicitly. % (By default \pkg{fontspec} auto-generates one based on the font name.) % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse} {NFSSFamily} { \tl_set:Nx \l_@@_nfss_fam_tl { #1 } } % \end{macrocode} % % \paragraph{NFSS series/shape} % This option looks similar in name but has a very different function. % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-preparse} {FontFace} { \tl_clear:N \l_@@_this_font_tl \clist_set:No \l_@@_arg_clist { \use_iii:nnn #1 } \clist_set_eq:NN \l_@@_this_feat_clist \l_@@_arg_clist \int_compare:nT { \clist_count:N \l_@@_arg_clist = 1 } { %\typeout{FontFace~ parsing:~ one~ clist~ item} \tl_if_in:NnF \l_@@_arg_clist {=} { %\typeout{FontFace~ parsing:~ no~ equals~ =>~ font~ name~ only} \tl_set_eq:NN \l_@@_this_font_tl \l_@@_arg_clist \tl_clear:N \l_@@_this_feat_clist } } \@@_add_nfssfont:nnnn {\use_i:nnn #1} {\use_ii:nnn #1} {\l_@@_this_font_tl} {\l_@@_this_feat_clist} } % \end{macrocode} % % % % \paragraph{Scale} % If the input isn't one of the pre-defined string options, then % it's gotta be numerical. \cs{fontspec_calc_scale:n} and \cs{fontspec_calc_scale:nn} % do all the work in the auto-scaling cases. % \begin{macrocode} \@@_keys_define_code:nnn {fontspec} {Scale} { \str_case:nnF {#1} { {MatchLowercase} { \@@_calc_scale:n {5} } {MatchUppercase} { \@@_calc_scale:n {8} } {MatchAveragecase} { \@@_calc_scale:nn {5} {8} } } { \tl_set:Nx \l_@@_scale_tl {#1} } \@@_info:n {set-scale} } % \end{macrocode} % % \paragraph{ScaleAgain} % \begin{macrocode} \@@_keys_define_code:nnn {fontspec} {ScaleAgain} { \tl_if_empty:NT \l_@@_scale_tl { \tl_set:Nn \l_@@_scale_tl {1} } \tl_set:Nx \l_@@_scale_tl { \fp_eval:n { #1 * \l_@@_scale_tl } } \@@_info:n {set-scale} } % \end{macrocode} % % \begin{macro}{\@@_calc_scale:n} % This macro calculates the amount of scaling between the default % roman font and the (default shape of) the font being selected such % that the font dimension that is input is equal for both. The only % font dimensions that justify this are 5 (lowercase height) % and 8 (uppercase height in \XeTeX). % % This script is executed for every extra shape, which seems wasteful, % but allows alternate italic shapes from a separate font, say, to % be loaded and to be auto-scaled correctly. Even if this would be ugly. % % To begin, change to \cs{rmfamily} but use internal commands in case cs{rmfamily} % has been overwritten. % (Note that changing \cs{rmfamily} with fontspec resets \cs{encodingdefault} % appropriately.) % \begin{macrocode} \cs_new:Nn \@@_calc_scale:n { \group_begin: \fontencoding { \encodingdefault } \fontfamily { \familydefault } \selectfont \@@_set_font_dimen:NnN \l_@@_tmpa_dim {#1} \font \@@_set_font_dimen:NnN \l_@@_tmpb_dim {#1} \l_@@_fontface_cs_tl \tl_set:Nx \l_@@_scale_tl { \fp_eval:n { \dim_to_fp:n {\l_@@_tmpa_dim} / \dim_to_fp:n {\l_@@_tmpb_dim} } } \exp_args:NNNx \group_end: \tl_set:Nx \l_@@_scale_tl { \l_@@_scale_tl } } % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@_calc_scale:nn} % This macro calls \cs{fontspec_calc_scale:n} twice % and then sets the scale to the average of the two results. % \begin{macrocode} \cs_new:Nn \@@_calc_scale:nn { \group_begin: \__fontspec_calc_scale:n {#1} \tl_set_eq:NN \l_@@_tmp_tl \l_@@_scale_tl \__fontspec_calc_scale:n {#2} \tl_set:Nx \l_@@_scale_tl { \fp_eval:n { (\l_@@_tmp_tl + \l_@@_scale_tl)/2 } } \exp_args:NNNx \group_end: \tl_set:Nx \l_@@_scale_tl { \l_@@_scale_tl } } % \end{macrocode} % \end{macro} % \begin{macro}{\@@_set_font_dimen:NnN} % This function sets the dimension |#1| (for font |#3|) to `fontdimen' |#2| % for either font dimension 5 (x-height) or 8 (cap-height). If, for some % reason, these return an incorrect `zero' value (as \cs{fontdimen8} might % for a \texttt{.tfm} font), then we cheat and measure the height of a glyph. % We assume in this case that the font contains either an `X' or an `x'. % \begin{macrocode} \cs_new:Nn \@@_set_font_dimen:NnN { \dim_set:Nn #1 { \fontdimen #2 #3 } \dim_compare:nNnT #1 = {0pt} { \settoheight #1 { \str_if_eq:nnTF {#3} {\font} \rmfamily #3 \int_case:nnF #2 { {5} {x} % x-height {8} {X} % cap-height } {?} % "else" clause; never reached. } } } % \end{macrocode} % \end{macro} % % % \paragraph{Inter-word space} % These options set the relevant \cmd\fontdimen s for the % font being loaded. % \begin{macrocode} \@@_keys_define_code:nnn {fontspec} {WordSpace} { \bool_if:NF \l_@@_firsttime_bool { \_fontspec_parse_wordspace:w #1,,,\q_stop } } \@@_aff_error:n {WordSpace} % \end{macrocode} % % \begin{macro}{\_fontspec_parse_wordspace:w} % This macro determines if the input to \feat{WordSpace} is % of the form |{X}| or |{X,Y,Z}| and executes the font scaling. % If the former input, it executes |{X,X,X}|. % \begin{macrocode} \cs_set:Npn \_fontspec_parse_wordspace:w #1,#2,#3,#4 \q_stop { \tl_if_empty:nTF {#4} { \tl_set:Nn \l_@@_wordspace_adjust_tl { \fontdimen 2 \font = #1 \fontdimen 2 \font \fontdimen 3 \font = #1 \fontdimen 3 \font \fontdimen 4 \font = #1 \fontdimen 4 \font } } { \tl_set:Nn \l_@@_wordspace_adjust_tl { \fontdimen 2 \font = #1 \fontdimen 2 \font \fontdimen 3 \font = #2 \fontdimen 3 \font \fontdimen 4 \font = #3 \fontdimen 4 \font } } } % \end{macrocode} % \end{macro} % % \paragraph{Punctuation space} % Scaling factor for the nominal \cmd\fontdimen \#7. % \begin{macrocode} \@@_keys_define_code:nnn {fontspec} {PunctuationSpace} { \str_case_e:nnF {#1} { {WordSpace} { \tl_set:Nn \l_@@_punctspace_adjust_tl { \fontdimen 7 \font = 0 \fontdimen 2 \font } } {TwiceWordSpace} { \tl_set:Nn \l_@@_punctspace_adjust_tl { \fontdimen 7 \font = 1 \fontdimen 2 \font } } } { \tl_set:Nn \l_@@_punctspace_adjust_tl { \fontdimen 7 \font = #1 \fontdimen 7 \font } } } \@@_aff_error:n {PunctuationSpace} % \end{macrocode} % % \paragraph{Secret hook into the font-adjustment code} % % \begin{macrocode} \@@_keys_define_code:nnn {fontspec} {FontAdjustment} { \tl_put_right:Nx \l_@@_postadjust_tl {#1} } % \end{macrocode} % % \paragraph{Letterspacing} % \begin{macrocode} \@@_keys_define_code:nnn {fontspec} {LetterSpace} { \@@_update_featstr:n {letterspace=#1} } % \end{macrocode} % % \paragraph{Hyphenation character} % This feature takes one of three arguments: `\opt{None}', % \meta{glyph}, or \meta{slot}. If the input isn't the first, % and it's one character, then it's the second; otherwise, it's % the third. % % LuaTeX decouples hyphenation from font settings, so only \verb|HyphenChar=None| works % for that engine. % \begin{macrocode} \@@_keys_define_code:nnn {fontspec} {HyphenChar} { \str_if_eq:nnTF {#1} {None} { \tl_put_right:Nn \l_@@_postadjust_tl { \@@_primitive_font_set_hyphenchar:Nn \font {-1} } } { % \@@_warning:nx {only-xetex-feature} {HyphenChar} \tl_if_single:nTF {#1} { \tl_set:Nn \l_@@_hyphenchar_tl {`#1} } { \tl_set:Nn \l_@@_hyphenchar_tl { #1} } \exp_args:No \@@_primitive_font_glyph_if_exist:NnTF \l_@@_fontface_cs_tl {\l_@@_hyphenchar_tl} { \tl_put_right:Nn \l_@@_postadjust_tl { \@@_primitive_font_set_hyphenchar:Nn \font { \l_@@_hyphenchar_tl } } } { \@@_error:nxx {no-glyph}{\l_fontspec_fontname_tl}{#1} } } } \@@_aff_error:n {HyphenChar} % \end{macrocode} % % \paragraph{Color} % Test first if the color is a named l3color, then if it is a color from % \pkg{xcolor}, which names its colours \texttt{\char`\\color@}. % If this fails the argument is assumed to be a hex color. % % \begin{macrocode} \@@_keys_define_code:nnn {fontspec} {Color} { %<*XE> \color_if_exist:nTF {#1} { \color_export:nnN {#1} {HTML}\l_@@_hexcol_tl } { \cs_if_exist:cTF { \token_to_str:N \color@ #1 } { \convertcolorspec{named}{#1}{HTML}\l_@@_hexcol_tl } { \int_compare:nTF { \tl_count:n {#1} == 6 } { \tl_set:Nn \l_@@_hexcol_tl {#1} } { \int_compare:nTF { \tl_count:n {#1} == 8 } { \fontspec_parse_colour:viii #1 } { \bool_if:NF \l_@@_firsttime_bool { \@@_warning:nx {bad-colour} {#1} } } } } } % %<*LU> \color_if_exist:nTF {#1} { \tl_set:Nn \l_@@_hexcol_tl {#1} } { \cs_if_exist:cTF { \token_to_str:N \color@ #1 } { \convertcolorspec{named}{#1}{HTML}\l_@@_hexcol_tl } { \int_compare:nTF { \tl_count:n {#1} == 6 } { \tl_set:Nn \l_@@_hexcol_tl {#1} } { \int_compare:nTF { \tl_count:n {#1} == 8 } { \fontspec_parse_colour:viii #1 } { \bool_if:NF \l_@@_firsttime_bool { \@@_warning:nx {bad-colour} {#1} } } } } } % } % \end{macrocode} % % \begin{macrocode} \cs_set:Npn \fontspec_parse_colour:viii #1#2#3#4#5#6#7#8 { \tl_set:Nn \l_@@_hexcol_tl {#1#2#3#4#5#6} \tl_if_eq:NNF \l_@@_opacity_tl \c_@@_opacity_tl { \bool_if:NF \l_@@_firsttime_bool { \@@_warning:nx {opa-twice-col} {#7#8} } } \tl_set:Nn \l_@@_opacity_tl {#7#8} } \aliasfontfeature{Color}{Colour} % \end{macrocode} % \begin{macrocode} \@@_keys_define_code:nnn {fontspec} {Opacity} { \int_set:Nn \l_@@_tmp_int {255} \@@_int_mult_truncate:Nn \l_@@_tmp_int { #1 } \tl_if_eq:NNF \l_@@_opacity_tl \c_@@_opacity_tl { \bool_if:NF \l_@@_firsttime_bool { \@@_warning:nx {opa-twice} {#1} } } \tl_set:Nx \l_@@_opacity_tl { % , \int_compare:nT { \l_@@_tmp_int <= "F } {0} % zero pad \int_to_hex:n { \l_@@_tmp_int } } } % \end{macrocode} % % % \paragraph{Mapping} % \begin{macrocode} %<*XE> \@@_keys_define_code:nnn {fontspec-aat} {Mapping} { \tl_set:Nn \l_@@_mapping_tl { #1 } } \@@_keys_define_code:nnn {fontspec-opentype} {Mapping} { \tl_set:Nn \l_@@_mapping_tl { #1 } } % %<*LU> \@@_keys_define_code:nnn {fontspec-opentype} {Mapping} { \str_if_eq:nnTF {#1} {tex-text} { \@@_warning:n {no-mapping-ligtex} \msg_redirect_name:nnn {fontspec} {no-mapping-ligtex} {none} \keys_set:nn {fontspec-opentype} { Ligatures=TeX } } { \@@_warning:n {no-mapping} } } % % \end{macrocode} % % % \subsubsection{Continuous font axes} % % \begin{macrocode} %<*XE> \@@_keys_define_code:nnn {fontspec} {Weight} { \@@_update_featstr:n{weight=#1} } % %\@@_define_opentype_variation_axis:nn {Weight} {wght} %<*XE> \@@_keys_define_code:nnn {fontspec} {Width} { \@@_update_featstr:n{width=#1} } % %\@@_define_opentype_variation_axis:nn {Width} {wdth} \@@_define_opentype_variation_axis:nn {Slant} {slnt} \@@_keys_define_code:nnn {fontspec} {OpticalSize} %<*XE> { \bool_if:NTF \l_@@_ot_bool { \tl_set:Nn \l_@@_optical_size_tl {/ S = #1} } { \bool_if:NT \l_@@_mm_bool { \@@_update_featstr:n { optical size = #1 } } } \bool_if:nT { !\l_@@_ot_bool && !\l_@@_mm_bool } { \bool_if:NT \l_@@_firsttime_bool { \@@_warning:nx {no-opticals} {\l_fontspec_fontname_tl} } } } % %<*LU> { \tl_set:Nn \l_@@_optical_size_tl {/ S = #1} } % % \end{macrocode} % % For other potentially font specific variation axes, there is a raw setter available: % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-opentype} {RawAxis} { \prop_gput_from_keyval:Nn \g_@@_rawvariations_prop {#1} } % \end{macrocode} % % \subsubsection{Variation instances} % % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-opentype} {Instance} { \tl_gset:Nn \g_@@_instance_tl {#1} } % \end{macrocode} % % \subsubsection{Font transformations} % These are to be specified to apply directly to a font shape: % \begin{macrocode} \keys_define:nn {fontspec} { FakeSlant .code:n = { \@@_update_featstr:n {slant=#1} }, FakeSlant .default:n = {0.2} } \keys_define:nn {fontspec} { FakeStretch .code:n = { \@@_update_featstr:n {extend=#1} }, FakeStretch .default:n = {1.2} } \keys_define:nn {fontspec} { FakeBold .code:n = { \@@_update_featstr:n {embolden=#1} }, FakeBold .default:n = {1.5} } % \end{macrocode} % These are to be given to a shape that has no real bold/italic % to signal that \pkg{fontspec} should automatically create `fake' shapes. % % The behaviour is currently that only if both \opt{AutoFakeSlant} \emph{and} % \opt{AutoFakeBold} are specified, the bold italic is also faked. % % These features presently \emph{override} real shapes found in the font; % in the future I'd like these features to be ignored in this case, instead. % (This is just a bit harder to program in the current design of % \pkg{fontspec}.) % \begin{macrocode} \keys_define:nn {fontspec} { AutoFakeSlant .code:n = { \bool_if:NT \l_@@_firsttime_bool { \tl_set:Nn \l_@@_fake_slant_tl {#1} \clist_put_right:Nn \l_@@_fontfeat_it_clist {FakeSlant=#1} \tl_set_eq:NN \l_@@_fontname_it_tl \l_fontspec_fontname_tl \bool_set_false:N \l_@@_noit_bool \tl_if_empty:NF \l_@@_fake_embolden_tl { \clist_put_right:Nx \l_@@_fontfeat_bfit_clist {FakeBold=\l_@@_fake_embolden_tl} \clist_put_right:Nx \l_@@_fontfeat_bfit_clist {FakeSlant=#1} \tl_set_eq:NN \l_@@_fontname_bfit_tl \l_fontspec_fontname_tl } } }, AutoFakeSlant .default:n = {0.2} } % \end{macrocode} % Same but reversed: % \begin{macrocode} \keys_define:nn {fontspec} { AutoFakeBold .code:n = { \bool_if:NT \l_@@_firsttime_bool { \tl_set:Nn \l_@@_fake_embolden_tl {#1} \clist_put_right:Nn \l_@@_fontfeat_bf_clist {FakeBold=#1} \tl_set_eq:NN \l_@@_fontname_bf_tl \l_fontspec_fontname_tl \bool_set_false:N \l_@@_nobf_bool \tl_if_empty:NF \l_@@_fake_slant_tl { \clist_put_right:Nx \l_@@_fontfeat_bfit_clist {FakeSlant=\l_@@_fake_slant_tl} \clist_put_right:Nx \l_@@_fontfeat_bfit_clist {FakeBold=#1} \tl_set_eq:NN \l_@@_fontname_bfit_tl \l_fontspec_fontname_tl } } }, AutoFakeBold .default:n = {1.5} } % \end{macrocode} % % % \subsubsection{Raw feature string} % This allows savvy \XeTeX-ers to input font features manually if they have % already memorised the OpenType abbreviations and don't mind not having error checking. % \begin{macrocode} \@@_keys_define_code:nnn {fontspec-opentype} {RawFeature} { \@@_update_featstr:n {#1} } \@@_keys_define_code:nnn {fontspec-aat} {RawFeature} { \@@_update_featstr:n {#1} } % \end{macrocode} % % % % % \iffalse % \begin{macrocode} % % \end{macrocode} % \fi \endinput % /© % ------------------------------------------------ % The FONTSPEC package % ------------------------------------------------ % Copyright 2022-2023 The LaTeX project % Copyright 2004-2022 Will Robertson, LPPL "maintainer" % Copyright 2009-2015 Khaled Hosny % Copyright 2013 Philipp Gesang % Copyright 2013-2016 Joseph Wright % ------------------------------------------------ % 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): . % ------------------------------------------------ % ©/