%%^^A%%  fontspec-code-feat-opentype.dtx -- part of FONTSPEC <latex3.github.io/fontspec>

% \section{OpenType feature definitions}
%
% \iffalse
%    \begin{macrocode}
%<*fontspec>
%    \end{macrocode}
% \fi
%
%
%    \begin{macrocode}
\@@_feat_prop_add:nn {salt} { Alternate\,=\,$N$ }
\@@_feat_prop_add:nn {nalt} { Annotation\,=\,$N$ }
\@@_feat_prop_add:nn {ornm} { Ornament\,=\,$N$ }
\@@_feat_prop_add:nn {cvNN} { CharacterVariant\,=\,$N$:$M$ }
\@@_feat_prop_add:nn {ssNN} { StylisticSet\,=\,$N$ }
%    \end{macrocode}
%
% \section{Regular key=val / tag definitions}
%
% \subsection{Ligatures}
%    \begin{macrocode}
\@@_define_opentype_feature_group:n {Ligatures}
\@@_define_opentype_feature:nnnnn {Ligatures} {ResetAll} {} {}
  {
    +dlig,-dlig,+rlig,-rlig,+liga,-liga,+dlig,-dlig,+clig,-clig,+hlig,-hlig,
%<XE>  mapping = tex-text
%<LU>  +tlig,-tlig
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\@@_define_opentype_onoffreset:nnnnn {Ligatures} {Required}      {rlig} {rlig} {}
\@@_define_opentype_onoffreset:nnnnn {Ligatures} {Common}        {liga} {liga} {}
\@@_define_opentype_onoffreset:nnnnn {Ligatures} {Rare}          {dlig} {dlig} {}
\@@_define_opentype_onoffreset:nnnnn {Ligatures} {Discretionary} {dlig} {dlig} {}
\@@_define_opentype_onoffreset:nnnnn {Ligatures} {Contextual}    {clig} {clig} {}
\@@_define_opentype_onoffreset:nnnnn {Ligatures} {Historic}      {hlig} {hlig} {}
%    \end{macrocode}
% Emulate CM extra ligatures.
%    \begin{macrocode}
%<*XE>
\keys_define:nn {fontspec-opentype}
  {
    Ligatures / TeX .code:n = { \tl_set:Nn \l_@@_mapping_tl {tex-text} },
    Ligatures / TeXOff .code:n = { \tl_clear:N \l_@@_mapping_tl },
    Ligatures / TeXReset .code:n = { \tl_clear:N \l_@@_mapping_tl },
  }
%</XE>
%<LU>\@@_define_opentype_onoffreset:nnnnn {Ligatures} {TeX} {} {tlig} {}
%    \end{macrocode}
%
% \subsection{Letters}
%    \begin{macrocode}
\@@_define_opentype_feature_group:n {Letters}
\@@_define_opentype_feature:nnnnn   {Letters} {ResetAll} {} {}
  {
%<LU>  +lower,-lower,+upper,-upper,+case,+cpsp,
    +smcp,+pcap,+c2sc,+c2pc,+unic,+rand,
    -smcp,-pcap,-c2sc,-c2pc,-unic,-rand
  }
%    \end{macrocode}
%
%    \begin{macrocode}
%<*LU>
\keys_define:nn {fontspec-opentype}
  {
    Letters / Uppercase .code:n = {
      \@@_make_OT_feature:nnn {} {+upper} {+lower}
      \@@_make_OT_feature:nnn {} {+case} {}
      \@@_make_OT_feature:nnn {} {+cpsp} {}
    },
  }
\@@_define_opentype_feature:nnnnn {Letters} {UppercaseOff} {} {-upper} {+case,+cpsp}
\@@_define_opentype_feature:nnnnn {Letters} {UppercaseReset} {} {} {+upper,-upper}
\@@_define_opentype_onoffreset:nnnnn {Letters} {Lowercase} {} {lower} {+upper,+case,+cpsp}
%</LU>
\@@_define_opentype_onoffreset:nnnnn {Letters} {SmallCaps} {smcp} {smcp} {+pcap,+unic}
\@@_define_opentype_onoffreset:nnnnn {Letters} {PetiteCaps} {pcap} {pcap} {+smcp,+unic}
\@@_define_opentype_onoffreset:nnnnn {Letters} {UppercaseSmallCaps} {c2sc} {c2sc} {+c2pc,+unic}
\@@_define_opentype_onoffreset:nnnnn {Letters} {UppercasePetiteCaps} {c2pc} {c2pc} {+c2sc,+unic}
\@@_define_opentype_onoffreset:nnnnn {Letters} {Unicase} {unic} {unic} {}
\@@_define_opentype_onoffreset:nnnnn {Letters} {Random} {rand} {rand} {}
%    \end{macrocode}
%
% \subsection{Numbers}
%    \begin{macrocode}
\@@_define_opentype_feature_group:n {Numbers}
\@@_define_opentype_feature:nnnnn   {Numbers} {ResetAll} {} {}
  {
    +tnum,-tnum,
    +pnum,-pnum,
    +onum,-onum,
    +lnum,-lnum,
    +zero,-zero,
    +anum,-anum,
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\@@_define_opentype_onoffreset:nnnnn {Numbers} {Monospaced}   {tnum} {tnum} {+pnum,-pnum}
\@@_define_opentype_onoffreset:nnnnn {Numbers} {Proportional} {pnum} {pnum} {+tnum,-tnum}
\@@_define_opentype_onoffreset:nnnnn {Numbers} {Lowercase}    {onum} {onum} {+lnum,-lnum}
\@@_define_opentype_onoffreset:nnnnn {Numbers} {Uppercase}    {lnum} {lnum} {+onum,-onum}
\@@_define_opentype_onoffreset:nnnnn {Numbers} {SlashedZero}  {zero} {zero} {}
%    \end{macrocode}
%
%    \begin{macrocode}
\aliasfontfeatureoption {Numbers} {Monospaced} {Tabular}
\aliasfontfeatureoption {Numbers} {Lowercase}  {OldStyle}
\aliasfontfeatureoption {Numbers} {Uppercase}  {Lining}
%    \end{macrocode}
%
% |luaotload| provides a custom |anum| feature for replacing Latin
% (AKA Arabic) numbers with Arabic (AKA Indic-Arabic). The same feature
% maps to Farsi (Persian) numbers if font language is Farsi.
%    \begin{macrocode}
%<LU>  \@@_define_opentype_onoffreset:nnnnn {Numbers} {Arabic} {anum} {anum} {}
%    \end{macrocode}
%
% \subsection{Vertical position}
%    \begin{macrocode}
\@@_define_opentype_feature_group:n  {VerticalPosition}
\@@_define_opentype_feature:nnnnn    {VerticalPosition} {ResetAll} {} {}
  {
    +sups,-sups,
    +subs,-subs,
    +ordn,-ordn,
    +numr,-numr,
    +dnom,-dnom,
    +sinf,-sinf,
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\@@_define_opentype_onoffreset:nnnnn {VerticalPosition} {Superior}           {sups} {sups} {+subs,+ordn,+numr,+dnom,+sinf}
\@@_define_opentype_onoffreset:nnnnn {VerticalPosition} {Inferior}           {subs} {subs} {+sups,+ordn,+numr,+dnom,+sinf}
\@@_define_opentype_onoffreset:nnnnn {VerticalPosition} {Ordinal}            {ordn} {ordn} {+sups,+subs,+numr,+dnom,+sinf}
\@@_define_opentype_onoffreset:nnnnn {VerticalPosition} {Numerator}          {numr} {numr} {+sups,+subs,+ordn,+dnom,+sinf}
\@@_define_opentype_onoffreset:nnnnn {VerticalPosition} {Denominator}        {dnom} {dnom} {+sups,+subs,+ordn,+numr,+sinf}
\@@_define_opentype_onoffreset:nnnnn {VerticalPosition} {ScientificInferior} {sinf} {sinf} {+sups,+subs,+ordn,+numr,+dnom}
%    \end{macrocode}
%
% \subsection{Contextuals}
%    \begin{macrocode}
\@@_define_opentype_feature_group:n  {Contextuals}
\@@_define_opentype_feature:nnnnn    {Contextuals} {ResetAll} {} {}
  {
    +cswh,-cswh,
    +calt,-calt,
    +init,-init,
    +fina,-fina,
    +falt,-falt,
    +medi,-medi,
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\@@_define_opentype_onoffreset:nnnnn {Contextuals} {Swash}       {cswh} {cswh} {}
\@@_define_opentype_onoffreset:nnnnn {Contextuals} {Alternate}   {calt} {calt} {}
\@@_define_opentype_onoffreset:nnnnn {Contextuals} {WordInitial} {init} {init} {}
\@@_define_opentype_onoffreset:nnnnn {Contextuals} {WordFinal}   {fina} {fina} {}
\@@_define_opentype_onoffreset:nnnnn {Contextuals} {LineFinal}   {falt} {falt} {}
\@@_define_opentype_onoffreset:nnnnn {Contextuals} {Inner}       {medi} {medi} {}
%    \end{macrocode}
%
% \subsection{Diacritics}
%    \begin{macrocode}
\@@_define_opentype_feature_group:n  {Diacritics}
\@@_define_opentype_feature:nnnnn    {Diacritics} {ResetAll} {} {}
  {
    +mark,-mark,
    +mkmk,-mkmk,
    +abvm,-abvm,
    +blwm,-blwm,
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\@@_define_opentype_onoffreset:nnnnn {Diacritics} {MarkToBase} {mark} {mark} {}
\@@_define_opentype_onoffreset:nnnnn {Diacritics} {MarkToMark} {mkmk} {mkmk} {}
\@@_define_opentype_onoffreset:nnnnn {Diacritics} {AboveBase}  {abvm} {abvm} {}
\@@_define_opentype_onoffreset:nnnnn {Diacritics} {BelowBase}  {blwm} {blwm} {}
%    \end{macrocode}
%
% \subsection{Kerning}
%    \begin{macrocode}
\@@_define_opentype_feature_group:n  {Kerning}
\@@_define_opentype_feature:nnnnn    {Kerning} {ResetAll} {} {}
  {
    +cpsp,-cpsp,
    +kern,-kern,
  }
\@@_define_opentype_onoffreset:nnnnn {Kerning} {Uppercase} {cpsp} {cpsp} {}
\@@_define_opentype_feature:nnnnn    {Kerning} {On}        {kern} {+kern} {-kern}
\@@_define_opentype_feature:nnnnn    {Kerning} {Off}       {kern} {-kern} {+kern}
\@@_define_opentype_feature:nnnnn    {Kerning} {Reset}     {} {} {+kern,-kern}
%    \end{macrocode}
%
% \subsection{Fractions}
%    \begin{macrocode}
\@@_define_opentype_feature_group:n  {Fractions}
\@@_define_opentype_feature:nnnnn    {Fractions} {ResetAll} {} {}
  {
    +frac,-frac,
    +afrc,-afrc,
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\@@_define_opentype_feature:nnnnn    {Fractions} {On}    {frac} {+frac} {}
\@@_define_opentype_feature:nnnnn    {Fractions} {Off}   {frac} {-frac} {}
\@@_define_opentype_feature:nnnnn    {Fractions} {Reset} {} {} {+frac,-frac}
\@@_define_opentype_onoffreset:nnnnn {Fractions} {Alternate} {afrc} {afrc} {-frac}
%    \end{macrocode}
%
%    \begin{macrocode}
\@@_define_opentype_feature_group:n  {LocalForms}
\@@_define_opentype_feature:nnnnn    {LocalForms} {On}    {locl} {+locl} {}
\@@_define_opentype_feature:nnnnn    {LocalForms} {Off}   {locl} {-locl} {}
\@@_define_opentype_feature:nnnnn    {LocalForms} {Reset} {} {}  {+locl,-locl}
%    \end{macrocode}
%

% \subsection{Style}
%    \begin{macrocode}
\@@_define_opentype_feature_group:n  {Style}
\@@_define_opentype_feature:nnnnn    {Style} {ResetAll} {} {}
  {
    +salt,-salt,
    +ital,-ital,
    +ruby,-ruby,
    +swsh,-swsh,
    +hist,-hist,
    +titl,-titl,
    +hkna,-hkna,
    +vkna,-vkna,
    +ssty=0,-ssty=0,
    +ssty=1,-ssty=1,
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\@@_define_opentype_onoffreset:nnnnn {Style} {Alternate}        {salt} {salt} {}
\@@_define_opentype_onoffreset:nnnnn {Style} {Italic}           {ital} {ital} {}
\@@_define_opentype_onoffreset:nnnnn {Style} {Ruby}             {ruby} {ruby} {}
\@@_define_opentype_onoffreset:nnnnn {Style} {Swash}            {swsh} {swsh} {}
\@@_define_opentype_onoffreset:nnnnn {Style} {Cursive}          {swsh} {curs} {}
\@@_define_opentype_onoffreset:nnnnn {Style} {Historic}         {hist} {hist} {}
\@@_define_opentype_onoffreset:nnnnn {Style} {Titling}          {titl} {titl} {}
\@@_define_opentype_onoffreset:nnnnn {Style} {TitlingCaps}      {titl} {titl} {} % backwards compat
\@@_define_opentype_onoffreset:nnnnn {Style} {HorizontalKana}   {hkna} {hkna} {+vkna,+pkna}
\@@_define_opentype_onoffreset:nnnnn {Style} {VerticalKana}     {vkna} {vkna} {+hkna,+pkna}
\@@_define_opentype_onoffreset:nnnnn {Style} {ProportionalKana} {pkna} {pkna} {+vkna,+hkna}
\@@_define_opentype_feature:nnnnn    {Style} {MathScript}       {ssty} {+ssty=0} {+ssty=1}
\@@_define_opentype_feature:nnnnn    {Style} {MathScriptScript} {ssty} {+ssty=1} {+ssty=0}
\@@_define_opentype_onoffreset:nnnnn {Style} {Uppercase} {case} {case} {}
%    \end{macrocode}
%
% \subsection{CJK shape}
%    \begin{macrocode}
\@@_define_opentype_feature_group:n  {CJKShape}
\@@_define_opentype_feature:nnnnn    {CJKShape} {ResetAll} {} {}
  {
    +trad,-trad,
    +smpl,-smpl,
    +jp78,-jp78,
    +jp83,-jp83,
    +jp90,-jp90,
    +jp04,-jp04,
    +expt,-expt,
    +nlck,-nlck,
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\@@_define_opentype_onoffreset:nnnnn {CJKShape} {Traditional} {trad} {trad} {+smpl,+jp78,+jp83,+jp90,+jp04,+expt,+nlck}
\@@_define_opentype_onoffreset:nnnnn {CJKShape} {Simplified}  {smpl} {smpl} {+trad,+jp78,+jp83,+jp90,+jp04,+expt,+nlck}
\@@_define_opentype_onoffreset:nnnnn {CJKShape} {JIS1978}     {jp78} {jp78} {+trad,+smpl,+jp83,+jp90,+jp04,+expt,+nlck}
\@@_define_opentype_onoffreset:nnnnn {CJKShape} {JIS1983}     {jp83} {jp83} {+trad,+smpl,+jp78,+jp90,+jp04,+expt,+nlck}
\@@_define_opentype_onoffreset:nnnnn {CJKShape} {JIS1990}     {jp90} {jp90} {+trad,+smpl,+jp78,+jp83,+jp04,+expt,+nlck}
\@@_define_opentype_onoffreset:nnnnn {CJKShape} {JIS2004}     {jp04} {jp04} {+trad,+smpl,+jp78,+jp83,+jp90,+expt,+nlck}
\@@_define_opentype_onoffreset:nnnnn {CJKShape} {Expert}      {expt} {expt} {+trad,+smpl,+jp78,+jp83,+jp90,+jp04,+nlck}
\@@_define_opentype_onoffreset:nnnnn {CJKShape} {NLC}         {nlck} {nlck} {+trad,+smpl,+jp78,+jp83,+jp90,+jp04,+expt}
%    \end{macrocode}
%
% \subsection{Character width}
%    \begin{macrocode}
\@@_define_opentype_feature_group:n  {CharacterWidth}
\@@_define_opentype_feature:nnnnn    {CharacterWidth} {ResetAll} {} {}
  {
    +pwid,-pwid,
    +fwid,-fwid,
    +hwid,-hwid,
    +twid,-twid,
    +qwid,-qwid,
    +palt,-palt,
    +halt,-halt,
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\@@_define_opentype_onoffreset:nnnnn {CharacterWidth} {Proportional}          {pwid} {pwid} {+fwid,+hwid,+twid,+qwid,+palt,+halt}
\@@_define_opentype_onoffreset:nnnnn {CharacterWidth} {Full}                  {fwid} {fwid} {+pwid,+hwid,+twid,+qwid,+palt,+halt}
\@@_define_opentype_onoffreset:nnnnn {CharacterWidth} {Half}                  {hwid} {hwid} {+pwid,+fwid,+twid,+qwid,+palt,+halt}
\@@_define_opentype_onoffreset:nnnnn {CharacterWidth} {Third}                 {twid} {twid} {+pwid,+fwid,+hwid,+qwid,+palt,+halt}
\@@_define_opentype_onoffreset:nnnnn {CharacterWidth} {Quarter}               {qwid} {qwid} {+pwid,+fwid,+hwid,+twid,+palt,+halt}
\@@_define_opentype_onoffreset:nnnnn {CharacterWidth} {AlternateProportional} {palt} {palt} {+pwid,+fwid,+hwid,+twid,+qwid,+halt}
\@@_define_opentype_onoffreset:nnnnn {CharacterWidth} {AlternateHalf}         {halt} {halt} {+pwid,+fwid,+hwid,+twid,+qwid,+palt}
%    \end{macrocode}
%
% \subsection{Vertical}
% According to spec |vkrn| must also activate |vpal| if available but for simplicity we don't do that here (yet?).
%    \begin{macrocode}
\@@_define_opentype_feature_group:n {Vertical}
\@@_define_opentype_onoffreset:nnnnn {Vertical} {RotatedGlyphs}         {vrt2} {vrt2} {+vrtr,+vert}
\@@_define_opentype_onoffreset:nnnnn {Vertical} {AlternatesForRotation} {vrtr} {vrtr} {+vrt2}
\@@_define_opentype_onoffreset:nnnnn {Vertical} {Alternates}            {vert} {vert} {+vrt2}
\@@_define_opentype_onoffreset:nnnnn {Vertical} {KanaAlternates}        {vkna} {vkna} {+hkna}
\@@_define_opentype_onoffreset:nnnnn {Vertical} {Kerning}               {vkrn} {vkrn} {}
\@@_define_opentype_onoffreset:nnnnn {Vertical} {AlternateMetrics}      {valt} {valt} {+vhal,+vpal,+kern}
\@@_define_opentype_onoffreset:nnnnn {Vertical} {HalfMetrics}           {vhal} {vhal} {+valt,+vpal,+kern}
\@@_define_opentype_onoffreset:nnnnn {Vertical} {ProportionalMetrics}   {vpal} {vpal} {+valt,+vhal}
%    \end{macrocode}
%
%
%
%
% \section{OpenType features that need numbering}
%
% \subsection{Alternate}
%
%    \begin{macrocode}
\@@_define_opentype_feature_group:n  {Alternate}
\keys_define:nn {fontspec-opentype}
  {
    Alternate .default:n = {0} ,
    Alternate .groups:n = {opentype},
    Alternate / unknown .code:n =
      {
        \clist_map_inline:nn {#1}
          { \@@_make_OT_feature:nnn {salt}{ +salt = ##1 }{} }
      }
  }
%    \end{macrocode}
%
%    \begin{macrocode}
%<*LU>
\keys_define:nn {fontspec-opentype}
  {
    Alternate / Random  .code:n =
      { \@@_make_OT_feature:nnn {salt}{ +salt = random }{} } ,
  }
%</LU>
%    \end{macrocode}
%
%    \begin{macrocode}
\aliasfontfeature{Alternate}{StylisticAlternates}
%    \end{macrocode}
%
%
% \subsection{Variant / StylisticSet}
%
%    \begin{macrocode}
\@@_define_opentype_feature_group:n  {Variant}
\keys_define:nn {fontspec-opentype}
  {
    Variant .default:n = {0} ,
    Variant .groups:n = {opentype} ,
    Variant / unknown .code:n =
      {
        \clist_map_inline:nn {#1}
          {
            \@@_make_OT_feature:xxx { ss \two@digits {##1} } { +ss \two@digits {##1} } {}
          }
      }
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\aliasfontfeature{Variant}{StylisticSet}
%    \end{macrocode}
%
% \subsection{CharacterVariant}
%    \begin{macrocode}
\@@_define_opentype_feature_group:n  {CharacterVariant}
\use:x
  {
    \cs_new:Npn \exp_not:N \fontspec_parse_cv:w
        ##1 \c_colon_str ##2 \c_colon_str ##3 \exp_not:N \q_nil
      {
        \@@_make_OT_feature:xxx
          {  cv \exp_not:N \two@digits {##1} }
          { +cv \exp_not:N \two@digits {##1} = ##2 } {}
      }
    \keys_define:nn {fontspec-opentype}
      {
        CharacterVariant / unknown .code:n =
          {
            \clist_map_inline:nn {##1}
              {
                \exp_not:N \fontspec_parse_cv:w
                  ####1 \c_colon_str 0 \c_colon_str \exp_not:N \q_nil
              }
          }
      }
  }
%    \end{macrocode}
% Possibilities: \verb|a:0:\q_nil| or \verb|a:b:0:\q_nil|.
%
%
% \subsection{Annotation}
%    \begin{macrocode}
\@@_define_opentype_feature_group:n {Annotation}
\keys_define:nn {fontspec-opentype}
  {
    Annotation .default:n = {0} ,
    Annotation .groups:n = {opentype},
    Annotation / unknown .code:n =
      {
        \@@_make_OT_feature:nnn {nalt} {+nalt=#1} {}
      }
  }
%    \end{macrocode}
%
% \subsection{Ornament}
%
%    \begin{macrocode}
\@@_define_opentype_feature_group:n  {Ornament}
\keys_define:nn {fontspec-opentype}
  {
    Ornament .default:n = {0} ,
    Ornament .groups:n = {opentype},
    Ornament / unknown .code:n =
      {
        \@@_make_OT_feature:nnn {ornm} { +ornm=#1 } {}
      }
  }
%    \end{macrocode}
%
%
% \section{Script and Language}
%
%
% \subsection{Script}
%
%    \begin{macrocode}
\keys_define:nn {fontspec-opentype}
  {
    Script .choice: ,
    Script .groups:n = {opentype} ,
  }
\cs_new:Nn \fontspec_new_script:nn
  {
    \keys_define:nn {fontspec-opentype} { Script / #1 .code:n =
      {
%<debug>\typeout{Trying~[Script=#1]}
        \bool_set_false:N \l_@@_scriptlang_exist_bool
        \clist_map_inline:nn {#2}
          {
            \exp_args:No \@@_check_script:NnT \l_@@_fontface_cs_tl {####1}
              {
%<debug>\typeout{Script~tag~found:~####1}
                \tl_set:Nn \l_@@_script_name_tl {#1}
                \tl_set:Nn \l_@@_script_tl {####1}
                \int_set:Nn \l_@@_script_int {\l_@@_strnum_int}
                \bool_set_true:N \l_@@_scriptlang_exist_bool
                \tl_gset:Nx \g_@@_single_feat_tl { script=####1 }
                \clist_map_break:
              }
          }
%    \end{macrocode}
% If not found give a warning but load it anyway:
%    \begin{macrocode}
        \bool_if:NF \l_@@_scriptlang_exist_bool
          {
%<debug>\typeout{Script~not~found!}
            \@@_info:nxx {script-not-exist} {\l_fontspec_fontname_tl} {#1}
            \clist_set:Nn \l_tmpa_clist {#2}
            \clist_get:NN \l_tmpa_clist \l_@@_script_tl
            \exp_args:Noo \@@_check_script:NnF \l_@@_fontface_cs_tl \l_@@_script_tl
              {
                \tl_set:Nn \l_@@_script_name_tl {#1}
                \int_set:Nn \l_@@_script_int {\l_@@_strnum_int}
                \tl_gset:Nx \g_@@_single_feat_tl { script=\l_@@_script_tl }
              }
          }
      }
    }
  }
%    \end{macrocode}
% When script is not explicitly requested, use this list:
%    \begin{macrocode}
\clist_new:N \g_@@_default_scripts_clist
\cs_new:Nn \fontspec_default_script:n
  {
    \clist_gset:Nn \g_@@_default_scripts_clist {#1}
  }
\fontspec_default_script:n {latn,DFLT}
%    \end{macrocode}
%
%    \begin{macrocode}
\keys_define:nn {fontspec-opentype} { Script / CustomDefault .code:n =
  {
%<debug>\typeout{Trying~CustomDefault~Script}
    \bool_set_false:N \l_@@_scriptlang_exist_bool
    \clist_map_inline:Nn \g_@@_default_scripts_clist
      {
        \exp_args:No \@@_check_script:NnT \l_@@_fontface_cs_tl {##1}
          {
%<debug>\typeout{Script~tag~found:~##1}
            \tl_set:Nn \l_@@_script_name_tl {Default (##1)}
            \tl_set:Nn \l_@@_script_tl {##1}
            \int_set:Nn \l_@@_script_int {\l_@@_strnum_int}
            \bool_set_true:N \l_@@_scriptlang_exist_bool
            \tl_gset:Nx \g_@@_single_feat_tl { script=##1 }
            \clist_map_break:
          }
      }
    \bool_if:NF \l_@@_scriptlang_exist_bool
      {
%<debug>\typeout{Script~not~found!}
        \tl_clear:N \l_@@_script_name_tl
      }
  }
}
%    \end{macrocode}
%
%
% \subsection{Language}
%
%    \begin{macrocode}
\keys_define:nn {fontspec-opentype}
  {
    Language .choice: ,
    Language .groups:n = {opentype} ,
  }
\cs_new:Nn \fontspec_new_lang:nn
  {
    \keys_define:nn {fontspec-opentype} { Language / #1 .code:n =
      {
        \bool_set_false:N \l_@@_scriptlang_exist_bool
        \clist_map_inline:nn {#2}
          {
            \exp_args:No \@@_check_lang:NnTF \l_@@_fontface_cs_tl {####1}
              {
                \tl_set:Nn \l_@@_lang_tl {####1}
                \int_set:Nn \l_@@_language_int {\l_@@_strnum_int}
                \tl_gset:Nx \g_@@_single_feat_tl { language=####1 }
                \bool_set_true:N \l_@@_scriptlang_exist_bool
                \clist_map_break:
              }
          }
%    \end{macrocode}
% If not found give a warning but load it anyway:
%    \begin{macrocode}
        \bool_if:NF \l_@@_scriptlang_exist_bool
          {
%<debug>\typeout{Lang~not~found!}
            \@@_info:nx {language-not-exist} {#1}
            \clist_set:Nn \l_tmpa_clist {#2}
            \clist_get:NN \l_tmpa_clist \l_@@_lang_tl
            \exp_args:Noo \@@_check_lang:NnF \l_@@_fontface_cs_tl \l_@@_lang_tl
              {
                \tl_set:Nn \l_@@_lang_name_tl {#1}
                \int_set:Nn \l_@@_language_int {\l_@@_strnum_int}
                \tl_gset:Nx \g_@@_single_feat_tl { language=\l_@@_lang_tl }
              }
          }
      }
    }
  }
%    \end{macrocode}
%
% \paragraph{Language=Default}
% These are special-cased to avoid the additional logic above.
% From memory, the OpenType default
% language is hardcoded to have a zero value,
% although this might be some \XeTeX-specific thing.
%    \begin{macrocode}
\clist_new:N \g_@@_default_langs_clist
\cs_new:Nn \fontspec_default_lang:n
  {
    \clist_gset:Nn \g_@@_default_langs_clist {#1}
  }
\fontspec_default_lang:n {dflt}
\@@_keys_define_code:nnn {fontspec-opentype} { Language / Default }
  {
    \tl_set:Nn \l_@@_lang_tl {dflt}
    \int_zero:N \l_@@_language_int
    \tl_gset:Nn \g_@@_single_feat_tl { language=dflt }
  }
%    \end{macrocode}
%
%
% \section{Backwards compatibility}
%
%    \begin{macrocode}
\cs_new:Nn \@@_ot_compat:nn
  {
    \aliasfontfeatureoption {#1} {#2Off} {No#2}
  }
\@@_ot_compat:nn {Ligatures}   {Rare}
\@@_ot_compat:nn {Ligatures}   {Required}
\@@_ot_compat:nn {Ligatures}   {Common}
\@@_ot_compat:nn {Ligatures}   {Discretionary}
\@@_ot_compat:nn {Ligatures}   {Contextual}
\@@_ot_compat:nn {Ligatures}   {Historic}
\@@_ot_compat:nn {Numbers}     {SlashedZero}
\@@_ot_compat:nn {Contextuals} {Swash}
\@@_ot_compat:nn {Contextuals} {Alternate}
\@@_ot_compat:nn {Contextuals} {WordInitial}
\@@_ot_compat:nn {Contextuals} {WordFinal}
\@@_ot_compat:nn {Contextuals} {LineFinal}
\@@_ot_compat:nn {Contextuals} {Inner}
\@@_ot_compat:nn {Diacritics}  {MarkToBase}
\@@_ot_compat:nn {Diacritics}  {MarkToMark}
\@@_ot_compat:nn {Diacritics}  {AboveBase}
\@@_ot_compat:nn {Diacritics}  {BelowBase}
%    \end{macrocode}
%
% \iffalse
%    \begin{macrocode}
%</fontspec>
%    \end{macrocode}
% \fi


\endinput

% /©
% ------------------------------------------------
% The FONTSPEC package  <latex3.github.io/fontspec>
% ------------------------------------------------
% Copyright  2022-2025  The LaTeX project,  LPPL "maintainer"
% Copyright  2004-2022  Will Robertson
% 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/>.
% ------------------------------------------------
% ©/
