summaryrefslogtreecommitdiff
path: root/macros/unicodetex/latex/fontspec/fontspec-code-keyval.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/unicodetex/latex/fontspec/fontspec-code-keyval.dtx')
-rw-r--r--macros/unicodetex/latex/fontspec/fontspec-code-keyval.dtx905
1 files changed, 905 insertions, 0 deletions
diff --git a/macros/unicodetex/latex/fontspec/fontspec-code-keyval.dtx b/macros/unicodetex/latex/fontspec/fontspec-code-keyval.dtx
new file mode 100644
index 0000000000..87a93c176b
--- /dev/null
+++ b/macros/unicodetex/latex/fontspec/fontspec-code-keyval.dtx
@@ -0,0 +1,905 @@
+%%^^A%% fontspec-code-keyval.dtx -- part of FONTSPEC <wspr.io/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}
+ \@@_font_is_file:
+%<*XE>
+ \keys_set:nn {fontspec-renderer} {Renderer=OpenType}
+%</XE>
+ }
+\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{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} }
+ }
+%<debug>\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}
+ }
+ }
+ }
+%</XE>
+%<*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} }
+ }
+
+%<debug>\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}
+ } ,
+ }
+%</LU>
+% \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}
+ {
+%<XE> \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}
+ {
+%<XE> \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} }
+%<XE> \tl_set:Nn \l_@@_ttc_index_tl {:#1}
+%<LU> \tl_set:Nn \l_@@_ttc_index_tl {(#1)}
+ }
+\@@_keys_define_code:nnn {fontspec} {FontIndex}
+ {
+%<XE> \tl_set:Nn \l_@@_ttc_index_tl {:#1}
+%<LU> \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}
+%
+%
+% \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
+
+%<debug>\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}
+%
+% \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}
+ }
+% \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 }
+ {
+%<debug>\typeout{FontFace~ parsing:~ one~ clist~ item}
+ \tl_if_in:NnF \l_@@_arg_clist {=}
+ {
+%<debug>\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} does 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} }
+ }
+ { \tl_set:Nx \l_@@_scale_tl {#1} }
+ }
+% \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} }
+ }
+
+ \@@_info:n {set-scale}
+ \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} }
+ }
+ {
+%<LU> \@@_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}
+% Hooks into pkg{xcolor}, which names its colours \texttt{\char`\\color@<name>}.
+% \begin{macrocode}
+\@@_keys_define_code:nnn {fontspec} {Color}
+ {
+ \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 }
+ }
+%</XE>
+%<*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} }
+ }
+%</LU>
+% \end{macrocode}
+%
+%
+% \subsubsection{Continuous font axes}
+%
+% \begin{macrocode}
+\@@_keys_define_code:nnn {fontspec} {Weight}
+ {
+ \@@_update_featstr:n{weight=#1}
+ }
+\@@_keys_define_code:nnn {fontspec} {Width}
+ {
+ \@@_update_featstr:n{width=#1}
+ }
+\@@_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} }
+ }
+ }
+%</XE>
+%<*LU>
+ {
+ \tl_set:Nn \l_@@_optical_size_tl {/ S = #1}
+ }
+%</LU>
+% \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}
+%</fontspec>
+% \end{macrocode}
+% \fi
+
+
+\endinput
+
+% /©
+% ------------------------------------------------
+% The FONTSPEC package <wspr.io/fontspec>
+% ------------------------------------------------
+% Copyright 2004-2020 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): <http://www.latex-project.org/lppl/>.
+% ------------------------------------------------
+% ©/