From 8c65eb5b73f80e0fcaa70910c1011adfa024d106 Mon Sep 17 00:00:00 2001
From: Karl Berry <karl@freefriends.org>
Date: Mon, 27 Sep 2010 00:42:03 +0000
Subject: fontspec 2.1a (26sep10)

git-svn-id: svn://tug.org/texlive/trunk@19908 c570f23f-e606-0410-a88d-b1316a301751
---
 Master/texmf-dist/tex/latex/fontspec/fontspec.sty | 1315 +++++++++++----------
 1 file changed, 681 insertions(+), 634 deletions(-)

(limited to 'Master/texmf-dist/tex/latex/fontspec/fontspec.sty')

diff --git a/Master/texmf-dist/tex/latex/fontspec/fontspec.sty b/Master/texmf-dist/tex/latex/fontspec/fontspec.sty
index 2820cfd99a2..7a1e55d7530 100644
--- a/Master/texmf-dist/tex/latex/fontspec/fontspec.sty
+++ b/Master/texmf-dist/tex/latex/fontspec/fontspec.sty
@@ -14,7 +14,7 @@
 %% 
 %% 
 \ProvidesPackage{fontspec}
-  [2010/09/19 v2.1 Advanced font selection for XeLaTeX/LuaLaTeX]
+  [2010/09/27 v2.1a Advanced font selection for XeLaTeX/LuaLaTeX]
 
 
 \RequirePackage{expl3,xparse}
@@ -57,21 +57,26 @@
 \newif\ifzf@package@euler@loaded
 \newif\if@zf@configfile
 \newif\if@zf@math
-\newcount\c@zf@newff
-\newcount\c@zf@index
-\newcount\c@zf@script
-\newcount\c@zf@language
+\int_new:N \l_fontspec_script_int
+\int_new:N \l_fontspec_language_int
 \int_new:N \l_fontspec_strnum_int
 \cs_set:Npn \use:x #1 { \edef\@tempa{#1}\@tempa }
+
+\cs_if_exist:NF \str_if_eq:xxTF {
+  \cs_set_eq:NN \str_if_eq_p:xx \tl_if_eq_p:xx
+  \cs_set_eq:NN \str_if_eq:xxTF \tl_if_eq:xxTF
+  \cs_set_eq:NN \str_if_eq:xxT  \tl_if_eq:xxT
+  \cs_set_eq:NN \str_if_eq:xxF  \tl_if_eq:xxF
+  \cs_set_eq:NN \str_if_eq_p:nn \tl_if_eq_p:nn
+  \cs_set_eq:NN \str_if_eq:nnTF \tl_if_eq:nnTF
+  \cs_set_eq:NN \str_if_eq:nnT \tl_if_eq:nnT
+  \cs_set_eq:NN \str_if_eq:nnF \tl_if_eq:nnF
+}
 \cs_set:Npn \use_v:nnnnn #1#2#3#4#5 {#5}
 \cs_set:Npn \use_iv:nnnnn #1#2#3#4#5 {#4}
-\prg_new_conditional:Nnn \fontspec_glyph_if_exist:Nn {p,TF,T,F} {
-  \etex_iffontchar:D #1 #2 \scan_stop:
-    \prg_return_true:
-  \else:
-    \prg_return_false:
-  \fi:
-}
+\cs_generate_variant:Nn \str_if_eq:nnTF {nv}
+\cs_generate_variant:Nn \int_set:Nn {Nv}
+\cs_generate_variant:Nn \tl_gset:Nn {cV}
 \cs_new:Npn \fontspec_setkeys:xx #1#2
  {
   \use:x { \exp_not:N \setkeys*[zf]{#1}{#2} }
@@ -103,7 +108,7 @@
 }
 \msg_new:nnn {fontspec} {no-glyph}
 {
-  '\zf@fontname'~ does~ not~ contain~ glyph~ #1.
+  '\l_fontspec_fontname_tl'~ does~ not~ contain~ glyph~ #1.
 }
 \msg_new:nnnn {fontspec} {unknown-options}
 {
@@ -150,38 +155,40 @@
 }
 \msg_new:nnn {fontspec} {script-not-exist}
 {
-  Font~ '\zf@fontname'~ does~ not~ contain~ script~ '#1'.
+  Font~ '\l_fontspec_fontname_tl'~ does~ not~ contain~ script~ '#1'.\\
+  'Latin'~ script~ used~ instead.
 }
 \msg_new:nnn {fontspec} {aat-feature-not-exist}
 {
   '\XKV@tfam=\XKV@tkey'~ feature~ not~ supported\\
-  for~ AAT~ font~ '\zf@fontname'.
+  for~ AAT~ font~ '\l_fontspec_fontname_tl'.
 }
 \msg_new:nnn {fontspec} {aat-feature-not-exist-in-font}
 {
   AAT~ feature~ '\XKV@tfam=\XKV@tkey'~ (#1)~ not~ available\\
-  in~ font~ '\zf@fontname'.
+  in~ font~ '\l_fontspec_fontname_tl'.
 }
 \msg_new:nnn {fontspec} {icu-feature-not-exist}
 {
   '\XKV@tfam=\XKV@tkey'~ feature~ not~ supported\\
-  for~ ICU~ font~ '\zf@fontname'
+  for~ ICU~ font~ '\l_fontspec_fontname_tl'
 }
 \msg_new:nnn {fontspec} {icu-feature-not-exist-in-font}
 {
   OpenType~ feature~ '\XKV@tfam=\XKV@tkey'~ (#1)~ not~ available\\
-  for~ font~ '\zf@fontname', \\
+  for~ font~ '\l_fontspec_fontname_tl', \\
   with~ script~ '\l_fontspec_script_name_tl',~ and~ language~ '\l_fontspec_lang_name_tl'.
 }
 \msg_new:nnn {fontspec} {no-opticals}
 {
-  '\zf@fontname'~ doesn't~ appear~ to~ have~ an~ Optical~ Size~ axis.
+  '\l_fontspec_fontname_tl'~ doesn't~ appear~ to~ have~ an~ Optical~ Size~ axis.
 }
 \msg_new:nnn {fontspec} {language-not-exist}
 {
   Language~ '#1'~ not~ available\\
-  for~ font~ '\zf@fontname'\\
-  with~ script~ '\l_fontspec_script_name_tl'.
+  for~ font~ '\l_fontspec_fontname_tl'~
+  with~ script~ '\l_fontspec_script_name_tl'.\\
+  'Default'~ language~ used~ instead.
 }
 \msg_new:nnn {fontspec} {only-xetex-feature}
 {
@@ -206,7 +213,23 @@
 }
 \msg_new:nnn {fontspec} {defining-font}
 {
-  Defining~ font~ family~ for~ '#2'~ with~ options~ [\zf@default@options #1].
+  Defining~ font~ family~ for~ '#2'~ with~ options~ [\g_fontspec_default_fontopts_tl #1].
+}
+\msg_new:nnn {fontspec} {defining-raw}
+{
+  Defining~ shape~
+  '\prg_case_str:nnn {#1} {
+    {\mddefault/\updefault} {normal}
+    {\mddefault/\scdefault} {small~ caps}
+    {\bfdefault/\updefault} {bold}
+    {\bfdefault/\scdefault} {bold~ small~ caps}
+    {\mddefault/\itdefault} {italic}
+    {\mddefault/\sidefault} {italic~ small~ caps}
+    {\bfdefault/\itdefault} {bold~ italic}
+    {\bfdefault/\sidefault} {bold~ italic~ small~ caps}
+  } {#1}'~
+  with~ NFSS~ specification: \\
+  \l_fontspec_nfss_tl
 }
 \msg_new:nnn {fontspec} {no-font-shape}
 {
@@ -214,7 +237,7 @@
 }
 \msg_new:nnn {fontspec} {set-scale}
 {
-  \zf@fontname\space scale ~=~ \l_fontspec_scale_tl.
+  \l_fontspec_fontname_tl\space scale ~=~ \l_fontspec_scale_tl.
 }
 \msg_new:nnn {fontspec} {setup-math}
 {
@@ -222,7 +245,7 @@
 }
 \msg_new:nnn {fontspec} {no-scripts}
 {
-  Font~ \zf@fontname\space does~ not~ contain~ any~ OpenType~ `Script'~ information.
+  Font~ \l_fontspec_fontname_tl\space does~ not~ contain~ any~ OpenType~ `Script'~ information.
 }
 \msg_new:nnn {fontspec} {opa-twice}
 {
@@ -304,24 +327,24 @@
 }
 \cs_set_eq:NN \setromanfont \setmainfont
 \DeclareDocumentCommand \setmathrm { O{} m } {
-  \fontspec_set_family:Nnn \zf@rmmaths {#1}{#2}
+  \fontspec_set_family:Nnn \g_fontspec_mathrm_tl {#1}{#2}
 }
 \DeclareDocumentCommand \setboldmathrm { O{} m } {
-  \fontspec_set_family:Nnn \zf@rmboldmaths {#1}{#2}
+  \fontspec_set_family:Nnn \g_fontspec_bfmathrm_tl {#1}{#2}
 }
 \DeclareDocumentCommand \setmathsf { O{} m } {
-  \fontspec_set_family:Nnn \zf@sfmaths {#1}{#2}
+  \fontspec_set_family:Nnn \g_fontspec_mathsf_tl {#1}{#2}
 }
 \DeclareDocumentCommand \setmathtt { O{} m } {
-  \fontspec_set_family:Nnn \zf@ttmaths {#1}{#2}
+  \fontspec_set_family:Nnn \g_fontspec_mathtt_tl {#1}{#2}
 }
 \@onlypreamble\setmathrm
 \@onlypreamble\setboldmathrm
 \@onlypreamble\setmathsf
 \@onlypreamble\setmathtt
-\def\zf@rmmaths{\rmdefault}
-\def\zf@sfmaths{\sfdefault}
-\def\zf@ttmaths{\ttdefault}
+\def\g_fontspec_mathrm_tl{\rmdefault}
+\def\g_fontspec_mathsf_tl{\sfdefault}
+\def\g_fontspec_mathtt_tl{\ttdefault}
 \DeclareDocumentCommand \newfontfamily { m O{} m } {
   \fontspec_select:nn{#2}{#3}
   \use:x {
@@ -334,50 +357,50 @@
 \DeclareDocumentCommand \newfontface { m O{} m } {
   \newfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2 ] {#3}
 }
-\DeclareDocumentCommand \defaultfontfeatures {m} {\def\zf@default@options{#1,}}
-\let\zf@default@options\@empty
+\DeclareDocumentCommand \defaultfontfeatures {m} {
+  \tl_set:Nn \g_fontspec_default_fontopts_tl {#1,}
+}
+\tl_clear:N \g_fontspec_default_fontopts_tl
 \DeclareDocumentCommand \addfontfeatures {m} {
   \ifcsname zf@family@fontdef\f@family\endcsname
-    \begingroup
-      \let\zf@default@options\@empty
+    \group_begin:
+      \tl_clear:N \g_fontspec_default_fontopts_tl
       \use:x {
         \exp_not:N\fontspec_select:nn
           {\csname zf@family@options\f@family\endcsname,#1}
           {\csname zf@family@fontname\f@family\endcsname}
       }
-    \endgroup
+    \group_end:
     \fontfamily\zf@family\selectfont
   \else
     \fontspec_warning:n {addfontfeatures-ignored}
   \fi
   \ignorespaces
 }
-\let\addfontfeature\addfontfeatures
+\cs_set_eq:NN \addfontfeature \addfontfeatures
 \DeclareDocumentCommand \newfontfeature {mm} {
-  \stepcounter{zf@newff}
-  \cs_set:cpx{+zf-#1}{+zf-\the\c@zf@newff}
   \define@key[zf]{options}{#1}[]{
-    \zf@update@family{\csname+zf-#1\endcsname}
-    \zf@update@ff{#2}
+    \fontspec_update_fontid:n  {+zf-#1}
+    \fontspec_update_featstr:n {#2}
   }
 }
 \DeclareDocumentCommand \newAATfeature {mmmm} {
   \unless\ifcsname zf@options@#1\endcsname
-    \zf@define@font@feature{#1}
+    \fontspec_define_font_feature:n{#1}
   \fi
   \key@ifundefined[zf]{#1}{#2}{}{
     \fontspec_warning:nxx {feature-option-overwrite}{#1}{#2}
   }
-  \zf@define@feature@option{#1}{#2}{#3}{#4}{}
+  \fontspec_define_feature_option:nnnnn{#1}{#2}{#3}{#4}{}
 }
 \DeclareDocumentCommand \newICUfeature {mmm} {
   \unless\ifcsname zf@options@#1\endcsname
-    \zf@define@font@feature{#1}
+    \fontspec_define_font_feature:n{#1}
   \fi
   \key@ifundefined[zf]{#1}{#2}{}{
     \fontspec_warning:nxx {feature-option-overwrite}{#1}{#2}
   }
-  \zf@define@feature@option{#1}{#2}{}{}{#3}
+  \fontspec_define_feature_option:nnnnn{#1}{#2}{}{}{#3}
 }
 \cs_set_eq:NN \newopentypefeature \newICUfeature
 \DeclareDocumentCommand \aliasfontfeature {mm} {\multi@alias@key{#1}{#2}}
@@ -393,11 +416,12 @@
 {
   \define@key[zf@feat]{Script}{#1}[]{
     \fontspec_check_script:nTF {#2} {
-      \zf@update@family{+script=#1}
+      \fontspec_update_fontid:n {+script=#1}
       \tl_set:Nn \l_fontspec_script_tl {#2}
-      \c@zf@script=\l_fontspec_strnum_int\relax
+      \int_set:Nn \l_fontspec_script_int {\l_fontspec_strnum_int}
     }{
       \fontspec_warning:nx {script-not-exist} {#1}
+      \setkeys[zf@feat]{Script}{Latin}
     }
   }
 }
@@ -410,11 +434,12 @@
 {
   \define@key[zf@feat]{Lang}{#1}[]{
     \fontspec_check_lang:nTF {#2} {
-      \zf@update@family{+lang=#1}
+      \fontspec_update_fontid:n {+lang=#1}
       \tl_set:Nn \l_fontspec_lang_tl {#2}
-      \c@zf@language=\l_fontspec_strnum_int\relax
+      \int_set:Nn \l_fontspec_language_int {\l_fontspec_strnum_int}
     }{
       \fontspec_warning:nx {language-not-exist} {#1}
+      \setkeys[zf@feat]{Lang}{Default}
     }
   }
 }
@@ -431,24 +456,20 @@
   \fi
 }
 \prg_new_conditional:Nnn \fontspec_if_aat_feature:nn {TF,T,F} {
-  \ifcsname zf@family@fontdef\f@family\endcsname
+  \fontspec_if_fontspec_font:TF {
     \font_set:Nnn \zf@basefont {\use:c{zf@family@fontdef\f@family}} {\f@size pt}
     \ifzf@atsui
-      \fontspec_make_AAT_feature_string:nn{#1}{#2}
-      \ifx\@tempa\@empty
-        \prg_return_false:
-      \else
-        \prg_return_true:
-      \fi
+      \fontspec_make_AAT_feature_string:nnTF {#1}{#2}
+        \prg_return_true: \prg_return_false:
     \else
       \prg_return_false:
     \fi
-  \else
+  }{
     \prg_return_false:
-  \fi
+  }
 }
 \prg_new_conditional:Nnn \fontspec_if_opentype: {TF,T,F} {
-  \ifcsname zf@family@fontdef\f@family\endcsname
+  \fontspec_if_fontspec_font:TF {
     \font_set:Nnn \zf@basefont {\csname zf@family@fontdef\f@family\endcsname} {\f@size pt}
     \fontspec_set_font_type:
     \ifzf@icu
@@ -456,46 +477,44 @@
     \else
       \prg_return_false:
     \fi
-  \else
+  }{
     \prg_return_false:
-  \fi
+  }
 }
 \prg_new_conditional:Nnn \fontspec_if_feature:n {TF,T,F} {
-  \ifcsname zf@family@fontdef\f@family\endcsname
+  \fontspec_if_fontspec_font:TF {
     \font_set:Nnn \zf@basefont {\csname zf@family@fontdef\f@family\endcsname} {\f@size pt}
     \fontspec_set_font_type:
     \ifzf@icu
-      \int_set:Nn \c@zf@script
-        {\use:c {g_fontspec_script_num_(\zf@family)_tl}}
-      \int_set:Nn \c@zf@language
-        {\use:c {g_fontspec_lang_num_(\zf@family)_tl}}
-      \tl_set:Nv \l_fontspec_script_tl {g_fontspec_script_(\zf@family)_tl}
-      \tl_set:Nv \l_fontspec_lang_tl   {g_fontspec_lang_(\zf@family)_tl}
+      \int_set:Nv \l_fontspec_script_int {g_fontspec_script_num_(\f@family)_tl}
+      \int_set:Nv \l_fontspec_language_int {g_fontspec_lang_num_(\f@family)_tl}
+      \tl_set:Nv \l_fontspec_script_tl {g_fontspec_script_(\f@family)_tl}
+      \tl_set:Nv \l_fontspec_lang_tl   {g_fontspec_lang_(\f@family)_tl}
       \fontspec_check_ot_feat:nTF {#1} \prg_return_true: \prg_return_false:
     \else
       \prg_return_false:
     \fi
-  \else
+  }{
     \prg_return_false:
-  \fi
+  }
 }
 \prg_new_conditional:Nnn \fontspec_if_feature:nnn {TF,T,F} {
-  \ifcsname zf@family@fontdef\f@family\endcsname
+  \fontspec_if_fontspec_font:TF {
     \font_set:Nnn \zf@basefont {\csname zf@family@fontdef\f@family\endcsname} {\f@size pt}
     \fontspec_set_font_type:
     \ifzf@icu
-      \fontspec_iv_str_to_num:n{#1} \c@zf@script   = \l_fontspec_strnum_int \relax
-      \fontspec_iv_str_to_num:n{#2} \c@zf@language = \l_fontspec_strnum_int \relax
+      \fontspec_iv_str_to_num:Nn \l_fontspec_script_int {#1}
+      \fontspec_iv_str_to_num:Nn \l_fontspec_language_int {#2}
       \fontspec_check_ot_feat:nTF {#3} \prg_return_true: \prg_return_false:
     \else
       \prg_return_false:
     \fi
-  \else
+  }{
     \prg_return_false:
-  \fi
+  }
 }
 \prg_new_conditional:Nnn \fontspec_if_script:n {TF,T,F} {
-  \ifcsname zf@family@fontdef\f@family\endcsname
+  \fontspec_if_fontspec_font:TF {
     \font_set:Nnn \zf@basefont {\csname zf@family@fontdef\f@family\endcsname} {\f@size pt}
     \fontspec_set_font_type:
     \ifzf@icu
@@ -503,91 +522,100 @@
     \else
       \prg_return_false:
     \fi
-  \else
+  }{
     \prg_return_false:
-  \fi
+  }
 }
 \prg_new_conditional:Nnn \fontspec_if_language:n {TF,T,F} {
-  \ifcsname zf@family@fontdef\f@family\endcsname
+  \fontspec_if_fontspec_font:TF {
     \font_set:Nnn \zf@basefont {\csname zf@family@fontdef\f@family\endcsname} {\f@size pt}
     \fontspec_set_font_type:
     \ifzf@icu
-      \tl_set:Nv \l_fontspec_script_tl {g_fontspec_script_(\zf@family)_tl}
-      \int_set:Nn \c@zf@script
-        {\use:c {g_fontspec_script_num_(\zf@family)_tl}}
+      \tl_set:Nv \l_fontspec_script_tl {g_fontspec_script_(\f@family)_tl}
+      \int_set:Nv \l_fontspec_script_int {g_fontspec_script_num_(\f@family)_tl}
       \fontspec_check_lang:nTF {#1} \prg_return_true: \prg_return_false:
     \else
       \prg_return_false:
     \fi
-  \else
+  }{
     \prg_return_false:
-  \fi
+  }
 }
 \prg_new_conditional:Nnn \fontspec_if_language:nn {TF,T,F} {
-  \ifcsname zf@family@fontdef\f@family\endcsname
+  \fontspec_if_fontspec_font:TF {
     \font_set:Nnn \zf@basefont {\csname zf@family@fontdef\f@family\endcsname} {\f@size pt}
     \fontspec_set_font_type:
     \ifzf@icu
       \tl_set:Nn \l_fontspec_script_tl {#1}
-      \fontspec_iv_str_to_num:n{#1} \c@zf@script   = \l_fontspec_strnum_int \relax
+      \fontspec_iv_str_to_num:Nn \l_fontspec_script_int {#1}
       \fontspec_check_lang:nTF {#2} \prg_return_true: \prg_return_false:
     \else
       \prg_return_false:
     \fi
-  \else
+  }{
     \prg_return_false:
-  \fi
+  }
 }
 \prg_new_conditional:Nnn \fontspec_if_current_script:n {TF,T,F} {
-  \ifcsname zf@family@fontdef\f@family\endcsname
+  \fontspec_if_fontspec_font:TF {
     \font_set:Nnn \zf@basefont {\csname zf@family@fontdef\f@family\endcsname} {\f@size pt}
     \fontspec_set_font_type:
     \ifzf@icu
-      \tl_if_eq:nvTF {#1} {g_fontspec_script_(\zf@family)_tl}
+      \str_if_eq:nvTF {#1} {g_fontspec_script_(\f@family)_tl}
         {\prg_return_true:} {\prg_return_false:}
     \else
       \prg_return_false:
     \fi
-  \else
+  }{
     \prg_return_false:
-  \fi
+  }
 }
 \prg_new_conditional:Nnn \fontspec_if_current_language:n {TF,T,F} {
-  \ifcsname zf@family@fontdef\f@family\endcsname
+  \fontspec_if_fontspec_font:TF {
     \font_set:Nnn \zf@basefont {\csname zf@family@fontdef\f@family\endcsname} {\f@size pt}
     \fontspec_set_font_type:
     \ifzf@icu
-      \tl_if_eq:nvTF {#1} {g_fontspec_lang_(\zf@family)_tl}
+      \str_if_eq:nvTF {#1} {g_fontspec_lang_(\f@family)_tl}
         {\prg_return_true:} {\prg_return_false:}
     \else
       \prg_return_false:
     \fi
-  \else
+  }{
     \prg_return_false:
-  \fi
+  }
 }
-\cs_generate_variant:Nn \tl_if_eq:nnTF {nv}
 \cs_new:Npn \fontspec_set_family:Nnn #1#2#3 {
   \fontspec_select:nn {#2}{#3}
   \tl_set_eq:NN #1 \zf@family
 }
 \xetex_or_luatex:nnn { \cs_set:Npn \fontspec_fontwrap:n #1 } { "#1" } { {#1} }
 \cs_set:Npn \fontspec_fontwrap:n #1 { "#1" }
+\cs_set_eq:NN \font_set_eq:NN \tex_let:D
 \cs_new:Npn \font_set:Nnn #1#2#3 {
   \font #1 = \fontspec_fontwrap:n {#2} ~at~#3\scan_stop:
 }
 \cs_new:Npn \font_gset:Nnn #1#2#3 {
   \global \font #1 = \fontspec_fontwrap:n {#2} ~at~#3\scan_stop:
 }
+\prg_new_conditional:Nnn \font_glyph_if_exist:Nn {p,TF,T,F} {
+  \etex_iffontchar:D #1 #2 \scan_stop:
+    \prg_return_true:
+  \else:
+    \prg_return_false:
+  \fi:
+}
 \cs_set:Npn \fontspec_select:nn #1#2 {
-  \begingroup
+  \group_begin:
   \fontspec_init:
-  \edef\zf@fontname{#2}
-  \let\zf@family@long\zf@fontname
-  \let\zf@up\zf@fontname
+  \tl_set:Nx \l_fontspec_fontname_tl {#2}
+  \luatex_if_engine:T {
+    \tl_replace_all_in:Nnn \l_fontspec_fontname_tl {~} {}
+  }
+  \tl_set_eq:NN \l_fontspec_fontid_tl \l_fontspec_fontname_tl
+  \tl_set_eq:NN \l_fontspec_fontname_up_tl \l_fontspec_fontname_tl
   \fontspec_preparse_features:nn {#1}{#2}
   \fontspec_set_scriptlang:
-  \fontspec_get_features:n {\zf@font@feat}
+  \fontspec_get_features:n {}
   \zf@firsttimefalse
   \fontspec_save_family:nT {#2} {
     \fontspec_info:nxx {defining-font} {#1} {#2}
@@ -600,19 +628,19 @@
     \fontspec_set_bold_italic:
     \fontspec_set_bold_slanted:
   }
-  \endgroup
+  \group_end:
 }
 \cs_set_eq:NN \zf@fontspec \fontspec_select:nn
 \cs_new:Npn \fontspec_preparse_features:nn #1#2 {
   \fontspec_if_detect_external:nT {#2}
    { \setkeys[zf]{preparse-external}{ExternalLocation} }
-  \fontspec_setkeys:xx {preparse-external} {\zf@default@options #1}
-  \let\zf@fontname\zf@up
+  \fontspec_setkeys:xx {preparse-external} {\g_fontspec_default_fontopts_tl #1}
+  \tl_set_eq:NN \l_fontspec_fontname_tl \l_fontspec_fontname_up_tl
   \fontspec_setkeys:xx {preparse} {\XKV@rm}
-  \let\zf@font@feat\XKV@rm
-  \font_set:Nnn \zf@basefont {\fontspec_fullname:n {\zf@up}} {\f@size pt}
+  \clist_set_eq:NN \l_fontspec_fontfeat_clist \XKV@rm
+  \font_set:Nnn \zf@basefont {\fontspec_fullname:n {\l_fontspec_fontname_up_tl}} {\f@size pt}
   \fontspec_set_font_type:
-  \font_gset:Nnn \zf@basefont {\fontspec_fullname:n {\zf@up}} {\f@size pt}
+  \font_gset:Nnn \zf@basefont {\fontspec_fullname:n {\l_fontspec_fontname_up_tl}} {\f@size pt}
   \zf@basefont % this is necessary for LuaLaTeX to check the scripts properly
 }
 \prg_new_conditional:Nnn \fontspec_if_detect_external:n {T}
@@ -632,7 +660,7 @@
 }
 %% Now we have a unique (in fact, too unique!) string that contains
 \prg_new_conditional:Nnn \fontspec_save_family:n {T} {
-  \cs_if_exist:cF {g_fontspec_UID_\zf@family@long}
+  \cs_if_exist:cF {g_fontspec_UID_\l_fontspec_fontid_tl}
   {
     \cs_if_exist:cTF {g_fontspec_family_#1_int} {
       \int_gincr:c {g_fontspec_family_#1_int}
@@ -640,12 +668,12 @@
       \int_new:c {g_fontspec_family_#1_int}
     }
     \edef\@tempa{#1~}
-    \tl_gset:cx {g_fontspec_UID_\zf@family@long} {
+    \tl_gset:cx {g_fontspec_UID_\l_fontspec_fontid_tl} {
       \expandafter\zap@space\@tempa\@empty
           ( \int_use:c {g_fontspec_family_#1_int} )
     }
   }
-  \tl_gset:Nv \zf@family {g_fontspec_UID_\zf@family@long}
+  \tl_gset:Nv \zf@family {g_fontspec_UID_\l_fontspec_fontid_tl}
   \cs_if_exist:cTF {zf@family@fontname\zf@family}
     \prg_return_false: \prg_return_true:
 }
@@ -676,48 +704,43 @@
 }
 \cs_new:Npn \fontspec_save_fontinfo:nn #1#2 {
     \tl_gset:cx {zf@family@fontname\zf@family} {#2}
-    \tl_gset:cx {zf@family@options\zf@family} {\zf@default@options #1}
+    \tl_gset:cx {zf@family@options\zf@family} {\g_fontspec_default_fontopts_tl #1}
     \tl_gset:cx {zf@family@fontdef\zf@family} {
-      \fontspec_fullname:n {\zf@fontname} : \l_fontspec_pre_feat_tl \l_fontspec_rawfeatures_sclist
+      \fontspec_fullname:n {\l_fontspec_fontname_tl} : \l_fontspec_pre_feat_tl \l_fontspec_rawfeatures_sclist
     }
-    \tl_gset:cx {g_fontspec_script_num_(\zf@family)_tl}
-      { \int_use:N \c@zf@script   }
-    \tl_gset:cx {g_fontspec_lang_num_(\zf@family)_tl}
-      { \int_use:N \c@zf@language }
+    \tl_gset:cV {g_fontspec_script_num_(\zf@family)_tl} \l_fontspec_script_int
+    \tl_gset:cV {g_fontspec_lang_num_(\zf@family)_tl} \l_fontspec_language_int
     \tl_gset_eq:cN {g_fontspec_script_(\zf@family)_tl} \l_fontspec_script_tl
     \tl_gset_eq:cN {g_fontspec_lang_(\zf@family)_tl}   \l_fontspec_lang_tl
 }
 \cs_new:Npn \fontspec_set_upright: {
-  \zf@make@font@shapes{\zf@fontname}
-    {\mddefault}{\updefault}{\zf@font@feat\zf@up@feat}
+  \fontspec_make_font_shapes:nnnn \l_fontspec_fontname_tl
+    \mddefault \updefault \l_fontspec_fontfeat_up_clist
 }
 \cs_new:Npn \fontspec_set_bold: {
   \unless\ifzf@nobf
-    \ifx\zf@bf\@empty
-      \zf@make@font@shapes[\zf@fontname]{/B}
-        {\bfdefault}{\updefault}{\zf@font@feat\zf@bf@feat}
-    \else
-      \zf@make@font@shapes{\zf@bf}
-        {\bfdefault}{\updefault}{\zf@font@feat\zf@bf@feat}
-    \fi
+    \tl_if_empty:NTF \l_fontspec_fontname_bf_tl {
+      \fontspec_make_font_shapes:nnnnn \l_fontspec_fontname_tl {/B}
+        \bfdefault \updefault \l_fontspec_fontfeat_bf_clist
+    }{
+      \fontspec_make_font_shapes:nnnn \l_fontspec_fontname_bf_tl
+        \bfdefault \updefault \l_fontspec_fontfeat_bf_clist
+    }
   \fi
 }
 \cs_new:Npn \fontspec_set_italic: {
   \unless\ifzf@noit
-    \ifx\zf@it\@empty
-      \zf@make@font@shapes[\zf@fontname]{/I}
-        {\mddefault}{\itdefault}{\zf@font@feat\zf@it@feat}
-    \else
-      \zf@make@font@shapes{\zf@it}
-        {\mddefault}{\itdefault}{\zf@font@feat\zf@it@feat}
-    \fi
+    \tl_if_empty:NTF \l_fontspec_fontname_it_tl
+    { \fontspec_make_font_shapes:nnnnn \l_fontspec_fontname_tl {/I} }
+    { \fontspec_make_font_shapes:nnnn  \l_fontspec_fontname_it_tl    }
+        \mddefault \itdefault \l_fontspec_fontfeat_it_clist
   \fi
 }
 \cs_new:Npn \fontspec_set_slanted: {
-  \ifx\zf@sl\@empty\else
-    \zf@make@font@shapes{\zf@sl}
-      {\mddefault}{\sldefault}{\zf@font@feat\zf@sl@feat}
-  \fi
+  \tl_if_empty:NF \l_fontspec_fontname_sl_tl {
+    \fontspec_make_font_shapes:nnnn
+      \l_fontspec_fontname_sl_tl \mddefault \sldefault \l_fontspec_fontfeat_sl_clist
+  }
 }
 \cs_new:Npn \fontspec_set_bold_italic: {
   \@tempswatrue
@@ -725,35 +748,38 @@
   \ifzf@noit\@tempswafalse\fi
   \bool_if:NT \l_fontspec_external_bool \@tempswafalse
   \if@tempswa
-    \ifx\zf@bfit\@empty
-      \ifx\zf@bf\@empty
-        \ifx\zf@it\@empty
-          \zf@make@font@shapes[\zf@fontname]{/BI}
-            {\bfdefault}{\itdefault}{\zf@font@feat\zf@bfit@feat}
-        \else
-          \zf@make@font@shapes[\zf@it]{/B}
-            {\bfdefault}{\itdefault}{\zf@font@feat\zf@bfit@feat}
-        \fi
-      \else
-        \zf@make@font@shapes[\zf@bf]{/I}
-          {\bfdefault}{\itdefault}{\zf@font@feat\zf@bfit@feat}
-      \fi
-    \else
-      \zf@make@font@shapes{\zf@bfit}
-        {\bfdefault}{\itdefault}{\zf@font@feat\zf@bfit@feat}
-    \fi
+    \tl_if_empty:NTF \l_fontspec_fontname_bfit_tl
+    {
+      \tl_if_empty:NTF \l_fontspec_fontname_bf_tl
+      {
+        \tl_if_empty:NTF \l_fontspec_fontname_it_tl
+        {
+          \fontspec_make_font_shapes:nnnnn \l_fontspec_fontname_tl    {/BI}
+        }
+        {
+          \fontspec_make_font_shapes:nnnnn \l_fontspec_fontname_it_tl {/B}
+        }
+      }
+      {
+        \fontspec_make_font_shapes:nnnnn \l_fontspec_fontname_bf_tl {/I}
+      }
+    }
+    {
+      \fontspec_make_font_shapes:nnnn  \l_fontspec_fontname_bfit_tl
+    }
+    \bfdefault \itdefault \l_fontspec_fontfeat_bfit_clist
   \fi
 }
 \cs_new:Npn \fontspec_set_bold_slanted: {
-  \ifx\zf@bfsl\@empty
-    \ifx\zf@sl\@empty\else
-      \zf@make@font@shapes[\zf@sl]{/B}
-        {\bfdefault}{\sldefault}{\zf@font@feat\zf@bfsl@feat}
-    \fi
-  \else
-    \zf@make@font@shapes{\zf@bfsl}
-      {\bfdefault}{\sldefault}{\zf@font@feat\zf@bfsl@feat}
-  \fi
+  \tl_if_empty:NTF \l_fontspec_fontname_bfsl_tl {
+    \tl_if_empty:NF \l_fontspec_fontname_sl_tl {
+      \fontspec_make_font_shapes:nnnnn \l_fontspec_fontname_sl_tl {/B}
+         \bfdefault \sldefault \l_fontspec_fontfeat_bfsl_clist
+    }
+  }{
+    \fontspec_make_font_shapes:nnnn \l_fontspec_fontname_bfsl_tl
+      \bfdefault \sldefault \l_fontspec_fontfeat_bfsl_clist
+  }
 }
 \xetex_or_luatex:nnn { \cs_new:Npn \fontspec_set_font_type: }
    {
@@ -779,45 +805,44 @@
   {
     \zf@icutrue
   }
-\newcommand*\zf@make@font@shapes[5][]{
-  \begingroup
-    \edef\@tempa{#1}
-    \unless\ifx\@tempa\@empty
-      \font_set:Nnn \@tempfonta {\fontspec_fullname:n {#1}} {\f@size pt}
-      \edef\@tempa{\fontname\@tempfonta}
-    \fi
-    \font_set:Nnn \@tempfontb {\fontspec_fullname:n {#1#2}} {\f@size pt}
-    \edef\@tempb{\fontname\@tempfontb}
-    \ifx\@tempa\@tempb
-      \fontspec_info:nx {no-font-shape} {#1#2}
-    \else
-      \edef\zf@fontname{#1#2}
-      \let\zf@basefont\@tempfontb
-      \fontspec_declare_shape:nnnn {}{#3}{#4}{#5}
-      \ifx\zf@sc\@empty
-        \unless\ifzf@nosc
-          \zf@make@smallcaps
-          \unless\ifx\zf@smallcaps\@empty
-            \fontspec_declare_shape:nnnn {\zf@smallcaps}{#3}
-              {\ifx#4\itdefault\sidefault\else\scdefault\fi}{#5\zf@sc@feat}
-          \fi
-        \fi
-      \else
-        \edef\zf@fontname{\zf@sc}
-        \fontspec_declare_shape:nnnn {}{#3}
-          {\ifx#4\itdefault\sidefault\else\scdefault\fi}{#5\zf@sc@feat}
+\cs_new:Nn \fontspec_make_font_shapes:nnnnn {
+  \font_set:Nnn \l_tmpa_font {\fontspec_fullname:n {#1}}   {\f@size pt}
+  \font_set:Nnn \l_tmpb_font {\fontspec_fullname:n {#1#2}} {\f@size pt}
+  \str_if_eq:xxTF { \fontname \l_tmpa_font } { \fontname \l_tmpb_font }
+  { \fontspec_info:nx {no-font-shape} {#1#2} }
+  {
+    \fontspec_make_font_shapes:nnnn {#1#2}{#3}{#4}{#5}
+  }
+}
+\cs_new:Nn \fontspec_make_font_shapes:nnnn {
+  \group_begin:
+    \tl_set:Nx \l_fontspec_fontname_tl {#1}
+    \font_set:Nnn \zf@basefont {\fontspec_fullname:n {#1}} {\f@size pt}
+    \fontspec_declare_shape:nnnn {}{#2}{#3}{#4}
+    \tl_if_empty:NTF \l_fontspec_fontname_sc_tl {
+      \unless\ifzf@nosc
+        \fontspec_make_smallcaps:T {
+          \fontspec_declare_shape:nnnn {\l_fontspec_sc_featstr_sclist} {#2}
+            { \tl_if_eq:NNTF #3 \itdefault \sidefault \scdefault }
+            { #4 \l_fontspec_fontfeat_sc_clist }
+        }
       \fi
-    \fi
-  \endgroup
+    }{
+      \tl_set:Nx \l_fontspec_fontname_tl {\l_fontspec_fontname_sc_tl}
+      \fontspec_declare_shape:nnnn {}{#2}
+        { \tl_if_eq:NNTF #3 \itdefault \sidefault \scdefault }
+        { #4 \l_fontspec_fontfeat_sc_clist }
+    }
+  \group_end:
 }
 \cs_new:Npn \fontspec_declare_shape:nnnn #1#2#3#4 {
   \clist_if_empty:NTF \l_fontspec_sizefeat_clist
   {
-    \fontspec_get_features:n{#4}
+    \fontspec_get_features:n {#4}
     \tl_set:Nx \l_fontspec_nfss_tl {
       <-> \l_fontspec_scale_tl
       \fontspec_fontwrap:n {
-        \fontspec_fullname:n {\zf@fontname} :
+        \fontspec_fullname:n {\l_fontspec_fontname_tl} :
           \l_fontspec_pre_feat_tl \l_fontspec_rawfeatures_sclist #1
       }
     }
@@ -825,11 +850,14 @@
   {
     \tl_clear:N \l_fontspec_nfss_tl
     \clist_map_inline:Nn \l_fontspec_sizefeat_clist {
+
       \tl_clear:N \l_fontspec_size_tl
-      \tl_set_eq:NN \l_fontspec_sizedfont_tl \zf@fontname
-      \fontspec_setkeys:xx {sizing} { \expandafter \@firstofone ##1 }
+      \tl_set_eq:NN \l_fontspec_sizedfont_tl \l_fontspec_fontname_tl
+
+      \fontspec_setkeys:xx {sizing} { \expandafter \use:n ##1 }
       \tl_if_empty:NT \l_fontspec_size_tl { \fontspec_error:n {no-size-info} }
-      \fontspec_get_features:n{#4,\XKV@rm}
+      \fontspec_get_features:n{ #4 , \XKV@rm }
+
       \tl_put_right:Nx \l_fontspec_nfss_tl {
         <\l_fontspec_size_tl> \l_fontspec_scale_tl
         \fontspec_fontwrap:n {
@@ -837,21 +865,19 @@
           : \l_fontspec_pre_feat_tl \l_fontspec_rawfeatures_sclist #1
         }
       }
+
     }
   }
-  \PackageInfo{fontspec}{
-    Defining~ shape~ #2/#3~ with~ raw~ font~ features:
-    \MessageBreak \l_fontspec_rawfeatures_sclist
-  \@gobble}
+  \fontspec_info:nx {defining-raw} {#2/#3}
   \use:x{
     \exp_not:N\DeclareFontShape{\zf@enc}{\zf@family}{#2}{#3}
-      {\l_fontspec_nfss_tl}{\zf@adjust}
+      {\l_fontspec_nfss_tl}{\l_fontspec_postadjust_tl}
   }
-  \tl_if_eq:xxT {#3} {\itdefault}
+  \str_if_eq:xxT {#3} {\itdefault}
   {
     \use:x {
       \exp_not:N \DeclareFontShape {\zf@enc}{\zf@family}{#2}{\sldefault}
-        {<->ssub*\zf@family/#2/\itdefault}{\zf@adjust}
+        {<->ssub*\zf@family/#2/\itdefault}{\l_fontspec_postadjust_tl}
     }
   }
 }
@@ -873,38 +899,42 @@
       language = \l_fontspec_lang_tl   ;
     }
   }
-\newcommand*{\zf@update@family}[1]{
+\cs_new:Nn \fontspec_update_fontid:n {
   \ifzf@firsttime
-    \xdef\zf@family@long{\zf@family@long#1}
+    \tl_gput_right:Nx \l_fontspec_fontid_tl {#1}
   \fi
 }
 \cs_set:Npn \fontspec_get_features:n #1 {
-  \let\l_fontspec_rawfeatures_sclist     \@empty
+  \sclist_clear:N \l_fontspec_rawfeatures_sclist
   \tl_clear:N \l_fontspec_scale_tl
   \tl_set_eq:NN \l_fontspec_opacity_tl \g_fontspec_opacity_tl
   \tl_set_eq:NN \l_fontspec_hexcol_tl \g_fontspec_hexcol_tl
-  \let\zf@adjust \@empty
-  \fontspec_setkeys:xx {options} {#1}
+  \tl_clear:N \l_fontspec_postadjust_tl
+  \fontspec_setkeys:xx {options} {\l_fontspec_fontfeat_clist #1}
   \tl_if_empty:NF \XKV@rm {
     \fontspec_error:nx {unknown-options} { \exp_not:V \XKV@rm }
   }
-  \zf@update@ff{color=\l_fontspec_hexcol_tl\l_fontspec_opacity_tl}
-}
-\tl_clear:N \zf@bf
-\tl_clear:N \zf@it
-\tl_clear:N \zf@fake@slant
-\tl_clear:N \zf@fake@embolden
-\tl_clear:N \zf@bfit
-\tl_clear:N \zf@sl
-\tl_clear:N \zf@bfsl
-\tl_clear:N \zf@sc
-\tl_clear:N \zf@up@feat
-\tl_clear:N \zf@bf@feat
-\tl_clear:N \zf@it@feat
-\tl_clear:N \zf@bfit@feat
-\tl_clear:N \zf@sl@feat
-\tl_clear:N \zf@bfsl@feat
-\tl_clear:N \zf@sc@feat
+  \str_if_eq:xxF { \l_fontspec_hexcol_tl \l_fontspec_opacity_tl }
+                { \g_fontspec_hexcol_tl \g_fontspec_opacity_tl }
+  {
+    \fontspec_update_featstr:n{color=\l_fontspec_hexcol_tl\l_fontspec_opacity_tl}
+  }
+}
+\tl_clear:N \l_fontspec_fontname_bf_tl
+\tl_clear:N \l_fontspec_fontname_it_tl
+\tl_clear:N \l_fontspec_fake_slant_tl
+\tl_clear:N \l_fontspec_fake_embolden_tl
+\tl_clear:N \l_fontspec_fontname_bfit_tl
+\tl_clear:N \l_fontspec_fontname_sl_tl
+\tl_clear:N \l_fontspec_fontname_bfsl_tl
+\tl_clear:N \l_fontspec_fontname_sc_tl
+\tl_clear:N \l_fontspec_fontfeat_up_clist
+\tl_clear:N \l_fontspec_fontfeat_bf_clist
+\tl_clear:N \l_fontspec_fontfeat_it_clist
+\tl_clear:N \l_fontspec_fontfeat_bfit_clist
+\tl_clear:N \l_fontspec_fontfeat_sl_clist
+\tl_clear:N \l_fontspec_fontfeat_bfsl_clist
+\tl_clear:N \l_fontspec_fontfeat_sc_clist
 \tl_clear:N \l_fontspec_script_name_tl
 \tl_clear:N \l_fontspec_script_tl
 \tl_clear:N \l_fontspec_lang_name_tl
@@ -928,34 +958,44 @@
     \luatexpostexhyphenchar= 0   % fixme
   }
 }
-\newcommand*\zf@make@smallcaps{
-  \let\zf@smallcaps\@empty
-  \xetex_or_luatex:nn
-  {
+\cs_set:Nn \fontspec_make_ot_smallcaps:T {
+  \tl_clear:N \l_fontspec_sc_featstr_sclist
+  \fontspec_check_ot_feat:nT {+smcp} {
+    \tl_set:Nx \l_fontspec_sc_featstr_sclist {+smcp;}
+    #1
+  }
+}
+\xetex_or_luatex:nn
+{
+  \cs_set:Nn \fontspec_make_smallcaps:T {
     \ifzf@atsui
-      \fontspec_make_AAT_feature_string:nn{3}{3}
-      \unless\ifx\@tempa\@empty
-        \edef\zf@smallcaps{\@tempa;}
-      \fi
+      \tl_clear:N \l_fontspec_sc_featstr_sclist
+      \fontspec_make_AAT_feature_string:nnT {3}{3} {
+        \tl_set:Nx \l_fontspec_sc_featstr_sclist {\l_fontspec_feature_string_tl;}
+        #1
+      }
     \fi
     \ifzf@icu
-      \fontspec_check_ot_feat:nT {+smcp} {\edef\zf@smallcaps{+smcp;}}
+      \fontspec_make_ot_smallcaps:T {#1}
     \fi
   }
-  {
-    \fontspec_check_ot_feat:nT {+smcp} {\edef\zf@smallcaps{+smcp;}}
-  }
 }
-\cs_new:Npn \sclist_put_right:Nn #1#2 {
+{
+  \cs_set_eq:NN \fontspec_make_smallcaps:T \fontspec_make_ot_smallcaps:T
+}
+\cs_set_eq:NN \sclist_new:N \tl_new:N
+\cs_set_eq:NN \sclist_clear:N \tl_clear:N
+\cs_new:Npn \sclist_gput_right:Nn #1#2 {
   \tl_if_empty:NTF #1 {
-    \tl_set:Nn #1 {#2}
+    \tl_gset:Nn #1 {#2}
   }{
-    \tl_put_right:Nn #1 {;#2}
+    \tl_gput_right:Nn #1 {;#2}
   }
 }
-\newcommand*\zf@update@ff[1]{
+\cs_generate_variant:Nn \sclist_gput_right:Nn {Nx}
+\cs_new:Nn \fontspec_update_featstr:n {
   \unless\ifzf@firsttime
-    \xdef\l_fontspec_rawfeatures_sclist{\l_fontspec_rawfeatures_sclist #1;}
+    \sclist_gput_right:Nx \l_fontspec_rawfeatures_sclist {#1}
   \fi
 }
 \cs_new:Npn \fontspec_make_feature:nnn #1#2#3 {
@@ -975,37 +1015,32 @@
 \cs_generate_variant:Nn \fontspec_make_feature:nnn {nnx}
 \cs_new:Npn \fontspec_make_AAT_feature:nn #1#2 {
   \tl_if_empty:nTF {#1}
+  { \fontspec_warning:n {aat-feature-not-exist} }
   {
-    \fontspec_warning:n {aat-feature-not-exist}
-  }
-  {
-    \fontspec_make_AAT_feature_string:nn {#1}{#2}
-    \ifx\@tempa\@empty
-      \fontspec_warning:nx {aat-feature-not-exist-in-font} {#1,#2}
-    \else
-      \zf@update@family{+#1,#2}
-      \zf@update@ff\@tempa
-    \fi
+    \fontspec_make_AAT_feature_string:nnTF {#1}{#2}
+    {
+      \fontspec_update_fontid:n {+#1,#2}
+      \fontspec_update_featstr:n {\l_fontspec_feature_string_tl}
+    }
+    { \fontspec_warning:nx {aat-feature-not-exist-in-font} {#1,#2} }
   }
 }
 \cs_new:Npn \fontspec_make_ICU_feature:n #1 {
   \tl_if_empty:nTF {#1}
+  { \fontspec_warning:n {icu-feature-not-exist} }
   {
-    \fontspec_warning:n {icu-feature-not-exist}
-  }
-  {
-    \fontspec_check_ot_feat:nTF {#1} {
-      \zf@update@family{#1}
-      \zf@update@ff{#1}
-    }{
-      \fontspec_warning:nx {icu-feature-not-exist-in-font} {#1}
+    \fontspec_check_ot_feat:nTF {#1}
+    {
+      \fontspec_update_fontid:n {#1}
+      \fontspec_update_featstr:n{#1}
     }
+    { \fontspec_warning:nx {icu-feature-not-exist-in-font} {#1} }
   }
 }
-\newcommand*\zf@define@font@feature[1]{
+\cs_new:Nn \fontspec_define_font_feature:n {
   \define@key[zf]{options}{#1}{{\setkeys[zf@feat]{#1}{##1}}}
 }
-\newcommand*\zf@define@feature@option[5]{
+\cs_new:Nn \fontspec_define_feature_option:nnnnn {
   \define@key[zf@feat]{#1}{#2}[]{\fontspec_make_feature:nnn{#3}{#4}{#5}}
 }
 \newcommand*\keyval@alias@key[4][KV]{
@@ -1025,66 +1060,69 @@
     }
     { \keyval@alias@key[zf]{options}{#1}{#2} }
 }
-\cs_new:Npn \fontspec_make_AAT_feature_string:nn #1#2 {
-  \edef\@tempa{\XeTeXfeaturename\zf@basefont #1}
-  \unless\ifx\@tempa\@empty
-    \ifnum\XeTeXisexclusivefeature\zf@basefont #1>0
-      \edef\@tempb{\XeTeXselectorname\zf@basefont #1\space #2}
-    \else
-      \unless\ifodd #2
-        \edef\@tempb{\XeTeXselectorname\zf@basefont #1\space #2}
-      \else
-        \edef\@tempb{
+\prg_new_conditional:Nnn \fontspec_make_AAT_feature_string:nn {TF,T,F} {
+  \tl_set:Nx \l_tmpa_tl { \XeTeXfeaturename \zf@basefont #1 }
+  \tl_if_empty:NTF \l_tmpa_tl
+  { \prg_return_false: }
+  {
+    \intexpr_compare:nTF { \XeTeXisexclusivefeature\zf@basefont #1 > 0 }
+    {
+      \tl_set:Nx \l_tmpb_tl {\XeTeXselectorname\zf@basefont #1\space #2}
+    }{
+      \intexpr_if_even:nTF {#2}
+      {
+        \tl_set:Nx \l_tmpb_tl {\XeTeXselectorname\zf@basefont #1\space #2}
+      }{
+        \tl_set:Nx \l_tmpb_tl {
           \XeTeXselectorname\zf@basefont #1\space \numexpr#2-1\relax
         }
-        \unless\ifx\@tempb\@empty
-          \edef\@tempb{!\@tempb}
-        \fi
-      \fi
-    \fi
-    \unless\ifx\@tempb\@empty
-      \edef\@tempa{\@tempa=\@tempb}
-    \else
-      \let\@tempa\@empty
-    \fi
-  \fi
+        \tl_if_empty:NF \l_tmpb_tl { \tl_put_left:Nn \l_tmpb_tl {!} }
+      }
+    }
+    \tl_if_empty:NTF \l_tmpb_tl
+    { \prg_return_false: }
+    {
+      \tl_set:Nx \l_fontspec_feature_string_tl { \l_tmpa_tl = \l_tmpb_tl }
+      \prg_return_true:
+    }
+  }
 }
-\cs_set:Npn \fontspec_iv_str_to_num:n #1 {
-  \fontspec_iv_str_to_num:w #1 \@empty \@empty \q_nil
+\cs_set:Npn \fontspec_iv_str_to_num:Nn #1#2 {
+  \fontspec_iv_str_to_num:w #1 \q_nil #2 \@empty \@empty \q_nil
 }
-\cs_set:Npn \fontspec_iv_str_to_num:w #1#2#3#4#5 \q_nil {
-  \int_set:Nn \l_fontspec_strnum_int {
-      `#1 * "1000000
-    + `#2 * "10000
-    + \ifx \@empty #3 32 \else `#3 \fi * "100
-    + \ifx \@empty #4 32 \else `#4 \fi
+\cs_set:Npn \fontspec_iv_str_to_num:w #1 \q_nil #2#3#4#5#6 \q_nil {
+  \int_set:Nn #1 {
+      `#2 * "1000000
+    + `#3 * "10000
+    + \ifx \@empty #4 32 \else `#4 \fi * "100
+    + \ifx \@empty #5 32 \else `#5 \fi
   }
 }
-\cs_set:Npn \fontspec_v_str_to_num:n #1 {
+\cs_generate_variant:Nn \fontspec_iv_str_to_num:Nn {No}
+\cs_set:Npn \fontspec_v_str_to_num:Nn #1#2 {
   \bool_if:nTF
     {
-      \tl_if_head_eq_charcode_p:nN {#1} {+} ||
-      \tl_if_head_eq_charcode_p:nN {#1} {-}
-    }
-    {
-      \exp_after:wN \fontspec_iv_str_to_num:n
-      \exp_after:wN { \use_none:n #1 }
+      \tl_if_head_eq_charcode_p:nN {#2} {+} ||
+      \tl_if_head_eq_charcode_p:nN {#2} {-}
     }
-    { \fontspec_iv_str_to_num:n {#1} }
+    { \fontspec_iv_str_to_num:No #1 { \use_none:n #2 } }
+    { \fontspec_iv_str_to_num:Nn #1 {#2} }
 }
 \xetex_or_luatex:nnn {\prg_new_conditional:Nnn \fontspec_check_script:n {TF}}
   {
-    \fontspec_iv_str_to_num:n{#1}
-    \@tempcntb\XeTeXOTcountscripts\zf@basefont
-    \c@zf@index\z@ \@tempswafalse
-    \loop\ifnum\c@zf@index<\@tempcntb
-      \ifnum\XeTeXOTscripttag\zf@basefont\c@zf@index=\l_fontspec_strnum_int
+    \fontspec_iv_str_to_num:Nn \l_fontspec_strnum_int {#1}
+    \int_set:Nn \l_tmpb_int { \XeTeXOTcountscripts\zf@basefont }
+    \int_zero:N \l_tmpa_int
+    \@tempswafalse
+    \bool_until_do:nn { \intexpr_compare_p:nNn \l_tmpa_int = \l_tmpb_int }
+    {
+      \ifnum \XeTeXOTscripttag\zf@basefont \l_tmpa_int = \l_fontspec_strnum_int
         \@tempswatrue
-        \c@zf@index\@tempcntb
+        \int_set:Nn \l_tmpa_int {\l_tmpb_int}
       \else
-        \advance\c@zf@index\@ne
+        \int_incr:N \l_tmpa_int
       \fi
-    \repeat
+    }
     \if@tempswa \prg_return_true: \else: \prg_return_false: \fi:
   }
   {
@@ -1093,18 +1131,21 @@
   }
 \xetex_or_luatex:nnn {\prg_new_conditional:Nnn \fontspec_check_lang:n {TF}}
   {
-    \fontspec_iv_str_to_num:n{#1}
-    \@tempcntb\XeTeXOTcountlanguages\zf@basefont\c@zf@script
-    \c@zf@index\z@
+    \fontspec_iv_str_to_num:Nn \l_fontspec_strnum_int {#1}
+    \int_set:Nn \l_tmpb_int {
+      \XeTeXOTcountlanguages \zf@basefont \l_fontspec_script_int
+    }
+    \int_zero:N \l_tmpa_int
     \@tempswafalse
-    \loop\ifnum\c@zf@index<\@tempcntb
-      \ifnum\XeTeXOTlanguagetag\zf@basefont\c@zf@script\c@zf@index=\l_fontspec_strnum_int
+    \bool_until_do:nn { \intexpr_compare_p:nNn \l_tmpa_int = \l_tmpb_int }
+    {
+      \ifnum\XeTeXOTlanguagetag\zf@basefont\l_fontspec_script_int \l_tmpa_int =\l_fontspec_strnum_int
         \@tempswatrue
-        \c@zf@index\@tempcntb
+        \int_set:Nn \l_tmpa_int {\l_tmpb_int}
       \else
-        \advance\c@zf@index\@ne
+        \int_incr:N \l_tmpa_int
       \fi
-    \repeat
+    }
     \if@tempswa \prg_return_true: \else: \prg_return_false: \fi:
   }
   {
@@ -1116,19 +1157,24 @@
 \xetex_or_luatex:nnn
    { \prg_new_conditional:Nnn \fontspec_check_ot_feat:n {TF,T} }
    {
-    \@tempcntb\XeTeXOTcountfeatures\zf@basefont\c@zf@script\c@zf@language
-    \fontspec_v_str_to_num:n {#1}
-    \c@zf@index\z@
+    \int_set:Nn \l_tmpb_int {
+      \XeTeXOTcountfeatures \zf@basefont
+                            \l_fontspec_script_int
+                            \l_fontspec_language_int
+    }
+    \fontspec_v_str_to_num:Nn \l_fontspec_strnum_int {#1}
+    \int_zero:N \l_tmpa_int
     \@tempswafalse
-    \loop\ifnum\c@zf@index<\@tempcntb
-      \ifnum\XeTeXOTfeaturetag\zf@basefont\c@zf@script\c@zf@language
-            \c@zf@index=\l_fontspec_strnum_int
+    \bool_until_do:nn { \intexpr_compare_p:nNn \l_tmpa_int = \l_tmpb_int }
+    {
+      \ifnum\XeTeXOTfeaturetag\zf@basefont\l_fontspec_script_int\l_fontspec_language_int
+           \l_tmpa_int =\l_fontspec_strnum_int
         \@tempswatrue
-        \c@zf@index\@tempcntb
+        \int_set:Nn \l_tmpa_int {\l_tmpb_int}
       \else
-        \advance\c@zf@index\@ne
+        \int_incr:N \l_tmpa_int
       \fi
-    \repeat
+    }
     \if@tempswa \prg_return_true: \else: \prg_return_false: \fi:
   }
   {
@@ -1160,7 +1206,7 @@
 \tl_clear:N \l_fontspec_extension_tl
 \define@choicekey[zf]{preparse}{Renderer}[\l_tmpa_tl\l_tmpa_num]
     {AAT,ICU,Graphite,Full,Basic}{
-  \zf@update@family{+rend:#1}
+  \fontspec_update_fontid:n {+rend:#1}
   \intexpr_compare:nTF {\l_tmpa_num < 3} {
     \xetex_or_luatex:nn
     {
@@ -1183,98 +1229,102 @@
 \define@key[zf]{preparse}{Script}{
   \xetex_if_engine:T { \setkeys[zf]{preparse}{Renderer=ICU} }
   \tl_set:Nn \l_fontspec_script_name_tl {#1}
-  \zf@update@family{+script:#1}
+  \fontspec_update_fontid:n {+script:#1}
 }
 \define@key[zf]{preparse}{Language}{
   \xetex_if_engine:T { \setkeys[zf]{preparse}{Renderer=ICU} }
   \tl_set:Nn \l_fontspec_lang_name_tl {#1}
-  \zf@update@family{+language:#1}
+  \fontspec_update_fontid:n {+language:#1}
 }
 \define@key[zf]{preparse-external}{UprightFont}{
-  \fontspec_complete_fontname:Nn \zf@up {#1}
-  \zf@update@family{up:#1}
+  \fontspec_complete_fontname:Nn \l_fontspec_fontname_up_tl {#1}
+  \fontspec_update_fontid:n {up:#1}
 }
 \define@key[zf]{preparse-external}{BoldFont}{
-  \edef\@tempa{#1}
-  \ifx\@tempa\@empty
+  \tl_if_empty:nTF {#1}
+  {
     \zf@nobftrue
-    \zf@update@family{nobf}
-  \else
+    \fontspec_update_fontid:n {nobf}
+  }
+  {
     \zf@nobffalse
-    \fontspec_complete_fontname:Nn \zf@bf {#1}
-    \zf@update@family{bf:#1}
-  \fi
+    \fontspec_complete_fontname:Nn \l_fontspec_fontname_bf_tl {#1}
+    \fontspec_update_fontid:n {bf:#1}
+  }
 }
 \define@key[zf]{preparse-external}{ItalicFont}{
-  \edef\@tempa{#1}
-  \ifx\@tempa\@empty
+  \tl_if_empty:nTF {#1}
+  {
     \zf@noittrue
-    \zf@update@family{noit}
-  \else
+    \fontspec_update_fontid:n {noit}
+  }{
     \zf@noitfalse
-    \fontspec_complete_fontname:Nn \zf@it {#1}
-    \zf@update@family{it:#1}
-  \fi
+    \fontspec_complete_fontname:Nn \l_fontspec_fontname_it_tl {#1}
+    \fontspec_update_fontid:n {it:#1}
+  }
 }
 \define@key[zf]{preparse-external}{BoldItalicFont}{
-  \fontspec_complete_fontname:Nn \zf@bfit {#1}
-  \zf@update@family{bfit:#1}
+  \fontspec_complete_fontname:Nn \l_fontspec_fontname_bfit_tl {#1}
+  \fontspec_update_fontid:n {bfit:#1}
 }
 \define@key[zf]{preparse-external}{SlantedFont}{
-  \fontspec_complete_fontname:Nn \zf@sl {#1}
-  \zf@update@family{sl:#1}
+  \fontspec_complete_fontname:Nn \l_fontspec_fontname_sl_tl {#1}
+  \fontspec_update_fontid:n {sl:#1}
 }
 \define@key[zf]{preparse-external}{BoldSlantedFont}{
-  \fontspec_complete_fontname:Nn \zf@bfsl {#1}
-  \zf@update@family{bfsl:#1}
+  \fontspec_complete_fontname:Nn \l_fontspec_fontname_bfsl_tl {#1}
+  \fontspec_update_fontid:n {bfsl:#1}
 }
 \define@key[zf]{options}{SmallCapsFont}{
-  \edef\@tempa{#1}
-  \ifx\@tempa\@empty
+  \tl_if_empty:nTF {#1}
+  {
     \zf@nosctrue
-    \zf@update@family{nosc}
-  \else
+    \fontspec_update_fontid:n {nosc}
+  }{
     \zf@noscfalse
-    \fontspec_complete_fontname:Nn \zf@sc {#1}
-    \zf@update@family{sc:\zap@space #1~\@empty}
-  \fi
+    \fontspec_complete_fontname:Nn \l_fontspec_fontname_sc_tl {#1}
+    \fontspec_update_fontid:n {sc:\zap@space #1~\@empty}
+  }
 }
 \cs_set:Npn \fontspec_complete_fontname:Nn #1#2 {
   \tl_set:Nn #1 {#2}
-  \tl_replace_all_in:Nnx #1 {*} {\zf@fontname}
+  \tl_replace_all_in:Nnx #1 {*} {\l_fontspec_fontname_tl}
+  \luatex_if_engine:T {
+    \tl_replace_all_in:Nnn #1 {~} {}
+  }
 }
 \cs_generate_variant:Nn \tl_replace_all_in:Nnn {Nnx}
 \define@key[zf]{preparse}{UprightFeatures}{
-  \def\zf@up@feat{, #1}
-  \zf@update@family{rmfeat:#1}
+  \def\l_fontspec_fontfeat_up_clist{, #1}
+  \fontspec_update_fontid:n {rmfeat:#1}
 }
 \define@key[zf]{preparse}{BoldFeatures}{
-  \def\zf@bf@feat{, #1}
-  \zf@update@family{bffeat:#1}
+  \def\l_fontspec_fontfeat_bf_clist{, #1}
+  \fontspec_update_fontid:n {bffeat:#1}
 }
 \define@key[zf]{preparse}{ItalicFeatures}{
-  \def\zf@it@feat{, #1}
-  \zf@update@family{itfeat:#1}
+  \def\l_fontspec_fontfeat_it_clist{, #1}
+  \fontspec_update_fontid:n {itfeat:#1}
 }
 \define@key[zf]{preparse}{BoldItalicFeatures}{
-  \def\zf@bfit@feat{, #1}
-  \zf@update@family{bfitfeat:#1}
+  \def\l_fontspec_fontfeat_bfit_clist{, #1}
+  \fontspec_update_fontid:n {bfitfeat:#1}
 }
 \define@key[zf]{preparse}{SlantedFeatures}{
-  \def\zf@sl@feat{, #1}
-  \zf@update@family{slfeat:#1}
+  \def\l_fontspec_fontfeat_sl_clist{, #1}
+  \fontspec_update_fontid:n {slfeat:#1}
 }
 \define@key[zf]{preparse}{BoldSlantedFeatures}{
-  \def\zf@bfsl@feat{, #1}
-  \zf@update@family{bfslfeat:#1}
+  \def\l_fontspec_fontfeat_bfsl_clist{, #1}
+  \fontspec_update_fontid:n {bfslfeat:#1}
 }
 \define@key[zf]{options}{SmallCapsFeatures}{
-  \unless\ifzf@firsttime\def\zf@sc@feat{, #1}\fi
-  \zf@update@family{scfeat:\zap@space #1~\@empty}
+  \unless\ifzf@firsttime\def\l_fontspec_fontfeat_sc_clist{, #1}\fi
+  \fontspec_update_fontid:n {scfeat:\zap@space #1~\@empty}
 }
 \define@key[zf]{preparse}{SizeFeatures}{
   \tl_set:Nn \l_fontspec_sizefeat_clist {#1}
-  \zf@update@family{sizefeat:\zap@space #1~\@empty}
+  \fontspec_update_fontid:n {sizefeat:\zap@space #1~\@empty}
 }
 \define@key[zf]{sizing}{Size}{ \tl_set:Nn \l_fontspec_size_tl {#1} }
 \define@key[zf]{sizing}{Font}{
@@ -1287,7 +1337,7 @@
     {MatchUppercase} { \fontspec_calc_scale:n {8} }
   }
   { \tl_set:Nx \l_fontspec_scale_tl {#1} }
-  \zf@update@family{+scale:\l_fontspec_scale_tl}
+  \fontspec_update_fontid:n {+scale:\l_fontspec_scale_tl}
   \tl_set:Nx \l_fontspec_scale_tl { s*[\l_fontspec_scale_tl] }
 }
 \cs_new:Npn \fontspec_calc_scale:n #1 {
@@ -1305,7 +1355,7 @@
   \dim_set:Nn #1 { \fontdimen #2 #3 }
   \dim_compare:nNnT #1 = {0pt} {
     \settoheight #1 {
-      \tl_if_eq:nnTF {#3} {\font} \rmfamily #3
+      \str_if_eq:nnTF {#3} {\font} \rmfamily #3
       \prg_case_int:nnn #2 {
         {5} {x} % x-height
         {8} {X} % cap-height
@@ -1314,51 +1364,51 @@
   }
 }
 \define@key[zf]{options}{WordSpace}{
-  \zf@update@family{+wordspace:#1}
+  \fontspec_update_fontid:n {+wordspace:#1}
   \unless\ifzf@firsttime
-    \zf@wordspace@parse#1,\zf@@ii,\zf@@iii,\zf@@
+    \_fontspec_parse_wordspace:w #1,,,\q_stop
   \fi
 }
-\def\zf@wordspace@parse#1,#2,#3,#4\zf@@{
-  \def\@tempa{#4}
-  \ifx\@tempa\@empty
-    \setlength\@tempdima{#1\fontdimen2\zf@basefont}
-    \@tempdimb\@tempdima
-    \@tempdimc\@tempdima
-  \else
-    \setlength\@tempdima{#1\fontdimen2\zf@basefont}
-    \setlength\@tempdimb{#2\fontdimen3\zf@basefont}
-    \setlength\@tempdimc{#3\fontdimen4\zf@basefont}
-  \fi
-  \edef\zf@adjust{
-    \zf@adjust
+\cs_set:Npn \_fontspec_parse_wordspace:w #1,#2,#3,#4 \q_stop {
+  \tl_if_empty:nTF {#4}
+  {
+    \dim_set:Nn \@tempdima {#1\fontdimen2\zf@basefont}
+    \dim_set:Nn \@tempdimb {\@tempdima}
+    \dim_set:Nn \@tempdimc {\@tempdima}
+  }{
+    \dim_set:Nn \@tempdima {#1\fontdimen2\zf@basefont}
+    \dim_set:Nn \@tempdimb {#2\fontdimen3\zf@basefont}
+    \dim_set:Nn \@tempdimc {#3\fontdimen4\zf@basefont}
+  }
+  \tl_set:Nx \l_fontspec_postadjust_tl {
+    \l_fontspec_postadjust_tl
     \fontdimen2\font\the\@tempdima
     \fontdimen3\font\the\@tempdimb
     \fontdimen4\font\the\@tempdimc
   }
 }
 \define@key[zf]{options}{PunctuationSpace}{
-  \zf@update@family{+punctspace:#1}
+  \fontspec_update_fontid:n {+punctspace:#1}
   \setlength\@tempdima{#1\fontdimen7\zf@basefont}
-  \edef\zf@adjust{\zf@adjust\fontdimen7\font\the\@tempdima}
+  \tl_set:Nx \l_fontspec_postadjust_tl {\l_fontspec_postadjust_tl\fontdimen7\font\the\@tempdima}
 }
 \define@key[zf]{options}{LetterSpace}{
-  \zf@update@family{+tracking:#1}
-  \zf@update@ff{letterspace=#1}
+  \fontspec_update_fontid:n {+tracking:#1}
+  \fontspec_update_featstr:n{letterspace=#1}
 }
 \define@key[zf]{options}{HyphenChar}{
-  \zf@update@family{+hyphenchar:#1}
-  \tl_if_eq:nnTF {#1} {None}
+  \fontspec_update_fontid:n {+hyphenchar:#1}
+  \str_if_eq:nnTF {#1} {None}
   {
-    \tl_put_right:Nn \zf@adjust { \hyphenchar \font = \c_minus_one }
+    \tl_put_right:Nn \l_fontspec_postadjust_tl { \hyphenchar \font = \c_minus_one }
   }
   {
     \tl_if_single:nTF {#1}
       { \tl_set:Nn \l_fontspec_hyphenchar_tl {`#1} }
       { \tl_set:Nn \l_fontspec_hyphenchar_tl { #1} }
-    \fontspec_glyph_if_exist:NnTF \zf@basefont {\l_fontspec_hyphenchar_tl}
+    \font_glyph_if_exist:NnTF \zf@basefont {\l_fontspec_hyphenchar_tl}
     {
-      \xetex_or_luatex:nnn { \tl_put_right:Nn \zf@adjust }
+      \xetex_or_luatex:nnn { \tl_put_right:Nn \l_fontspec_postadjust_tl }
         { \hyphenchar \font = \l_fontspec_hyphenchar_tl \scan_stop: }
         {
           \hyphenchar \font = \c_zero
@@ -1369,7 +1419,7 @@
   }
 }
 \define@key[zf]{options}{Color}{
-  \zf@update@family{+col:#1}
+  \fontspec_update_fontid:n {+col:#1}
   \cs_if_exist:cTF {\token_to_str:N\color@#1}
   {
     \convertcolorspec{named}{#1}{HTML}\l_fontspec_hexcol_tl
@@ -1401,7 +1451,7 @@
 \keyval@alias@key[zf]{options}{Color}{Colour}
 \newcounter{fontspec_tmp_int}
 \define@key[zf]{options}{Opacity}{
-  \zf@update@family{+opac:#1}
+  \fontspec_update_fontid:n {+opac:#1}
   \setcounter {fontspec_tmp_int} { 255*\real{#1} }
   \tl_if_eq:NNF \l_fontspec_opacity_tl \g_fontspec_opacity_tl
    {
@@ -1415,10 +1465,10 @@
 \xetex_or_luatex:nnn {
   \define@key[zf]{options}{Mapping}
 }{
-  \zf@update@family{+map:#1}
-  \zf@update@ff{mapping=#1}
+  \fontspec_update_fontid:n {+map:#1}
+  \fontspec_update_featstr:n{mapping=#1}
 }{
-  \tl_if_eq:nnTF {#1} {tex-text} {
+  \str_if_eq:nnTF {#1} {tex-text} {
     \fontspec_warning:n {no-mapping-ligtex}
     \msg_redirect_name:nnn {fontspec} {no-mapping-ligtex} {none}
     \setkeys[zf]{options}{ Ligatures=TeX }
@@ -1427,26 +1477,26 @@
   }
 }
 \define@key[zf]{options}{FeatureFile}{
-  \zf@update@family{+fea:#1}
-  \zf@update@ff{featurefile=#1}
+  \fontspec_update_fontid:n {+fea:#1}
+  \fontspec_update_featstr:n{featurefile=#1}
 }
 \define@key[zf]{options}{Weight}{
-  \zf@update@family{+weight:#1}
-  \zf@update@ff{weight=#1}
+  \fontspec_update_fontid:n {+weight:#1}
+  \fontspec_update_featstr:n{weight=#1}
 }
 \define@key[zf]{options}{Width}{
-  \zf@update@family{+width:#1}
-  \zf@update@ff{width=#1}
+  \fontspec_update_fontid:n {+width:#1}
+  \fontspec_update_featstr:n{width=#1}
 }
 \define@key[zf]{options}{OpticalSize}{
   \xetex_or_luatex:nn {
     \ifzf@icu
       \tl_set:Nn \l_fontspec_optical_size_tl {/ S = #1}
-      \zf@update@family{+size:#1}
+      \fontspec_update_fontid:n {+size:#1}
     \fi
     \ifzf@mm
-      \zf@update@family{+size:#1}
-      \zf@update@ff{optical size=#1}
+      \fontspec_update_fontid:n {+size:#1}
+      \fontspec_update_featstr:n{optical size=#1}
     \fi
     \ifzf@icu\else
       \ifzf@mm\else
@@ -1457,154 +1507,154 @@
     \fi
   }{
     \tl_set:Nn \l_fontspec_optical_size_tl {/ S = #1}
-    \zf@update@family{+size:#1}
+    \fontspec_update_fontid:n {+size:#1}
   }
 }
 \define@key[zf]{options}{FakeSlant}[0.2]{
-  \zf@update@family{+slant:#1}
-  \zf@update@ff{slant=#1}
+  \fontspec_update_fontid:n {+slant:#1}
+  \fontspec_update_featstr:n{slant=#1}
 }
 \define@key[zf]{options}{FakeStretch}[1.2]{
-  \zf@update@family{+extend:#1}
-  \zf@update@ff{extend=#1}
+  \fontspec_update_fontid:n {+extend:#1}
+  \fontspec_update_featstr:n{extend=#1}
 }
 \define@key[zf]{options}{FakeBold}[1.5]{
-  \zf@update@family{+embolden:#1}
-  \zf@update@ff{embolden=#1}
+  \fontspec_update_fontid:n {+embolden:#1}
+  \fontspec_update_featstr:n{embolden=#1}
 }
 \define@key[zf]{options}{AutoFakeSlant}[0.2]{
   \ifzf@firsttime
-    \tl_set:Nn \zf@fake@slant {#1}
-    \tl_put_right:Nn \zf@it@feat {,FakeSlant=#1}
-    \tl_set_eq:NN \zf@it \zf@fontname
-    \zf@update@family{fakeit:#1}
-    \tl_if_empty:NF \zf@fake@embolden {
-      \tl_put_right:Nx \zf@bfit@feat
-        {,FakeBold=\zf@fake@embolden,FakeSlant=#1}
-      \tl_set_eq:NN \zf@bfit \zf@fontname
+    \tl_set:Nn \l_fontspec_fake_slant_tl {#1}
+    \clist_put_right:Nn \l_fontspec_fontfeat_it_clist {,FakeSlant=#1}
+    \tl_set_eq:NN \l_fontspec_fontname_it_tl \l_fontspec_fontname_tl
+    \fontspec_update_fontid:n {fakeit:#1}
+    \tl_if_empty:NF \l_fontspec_fake_embolden_tl {
+      \tl_put_right:Nx \l_fontspec_fontfeat_bfit_clist
+        {,FakeBold=\l_fontspec_fake_embolden_tl,FakeSlant=#1}
+      \tl_set_eq:NN \l_fontspec_fontname_bfit_tl \l_fontspec_fontname_tl
     }
   \fi
 }
 \define@key[zf]{options}{AutoFakeBold}[1.5]{
   \ifzf@firsttime
-    \tl_set:Nn \zf@fake@embolden {#1}
-    \tl_put_right:Nn \zf@bf@feat {,FakeBold=#1}
-    \tl_set_eq:NN \zf@bf \zf@fontname
-    \zf@update@family{fakebf:#1}
-    \tl_if_empty:NF \zf@fake@slant {
-      \tl_put_right:Nx \zf@bfit@feat
-        {,FakeSlant=\zf@fake@slant,FakeBold=#1}
-      \tl_set_eq:NN \zf@bfit \zf@fontname
+    \tl_set:Nn \l_fontspec_fake_embolden_tl {#1}
+    \tl_put_right:Nn \l_fontspec_fontfeat_bf_clist {,FakeBold=#1}
+    \tl_set_eq:NN \l_fontspec_fontname_bf_tl \l_fontspec_fontname_tl
+    \fontspec_update_fontid:n {fakebf:#1}
+    \tl_if_empty:NF \l_fontspec_fake_slant_tl {
+      \tl_put_right:Nx \l_fontspec_fontfeat_bfit_clist
+        {,FakeSlant=\l_fontspec_fake_slant_tl,FakeBold=#1}
+      \tl_set_eq:NN \l_fontspec_fontname_bfit_tl \l_fontspec_fontname_tl
     }
   \fi
 }
-\zf@define@font@feature{Ligatures}
-\zf@define@feature@option{Ligatures}{Required}       {1}{0}{+rlig}
-\zf@define@feature@option{Ligatures}{NoRequired}     {1}{1}{-rlig}
-\zf@define@feature@option{Ligatures}{Common}         {1}{2}{+liga}
-\zf@define@feature@option{Ligatures}{NoCommon}       {1}{3}{-liga}
-\zf@define@feature@option{Ligatures}{Rare}           {1}{4}{+dlig}
-\zf@define@feature@option{Ligatures}{NoRare}         {1}{5}{-dlig}
-\zf@define@feature@option{Ligatures}{Discretionary}  {1}{4}{+dlig}
-\zf@define@feature@option{Ligatures}{NoDiscretionary}{1}{5}{-dlig}
-\zf@define@feature@option{Ligatures}{Contextual}     {}{}  {+clig}
-\zf@define@feature@option{Ligatures}{NoContextual}   {}{}  {-clig}
-\zf@define@feature@option{Ligatures}{Historic}       {}{}  {+hlig}
-\zf@define@feature@option{Ligatures}{NoHistoric}     {}{}  {-hlig}
-\zf@define@feature@option{Ligatures}{Logos}          {1}{6} {}
-\zf@define@feature@option{Ligatures}{NoLogos}        {1}{7} {}
-\zf@define@feature@option{Ligatures}{Rebus}          {1}{8} {}
-\zf@define@feature@option{Ligatures}{NoRebus}        {1}{9} {}
-\zf@define@feature@option{Ligatures}{Diphthong}      {1}{10}{}
-\zf@define@feature@option{Ligatures}{NoDiphthong}    {1}{11}{}
-\zf@define@feature@option{Ligatures}{Squared}        {1}{12}{}
-\zf@define@feature@option{Ligatures}{NoSquared}      {1}{13}{}
-\zf@define@feature@option{Ligatures}{AbbrevSquared}  {1}{14}{}
-\zf@define@feature@option{Ligatures}{NoAbbrevSquared}{1}{15}{}
-\zf@define@feature@option{Ligatures}{Icelandic}      {1}{32}{}
-\zf@define@feature@option{Ligatures}{NoIcelandic}    {1}{33}{}
+\fontspec_define_font_feature:n{Ligatures}
+\fontspec_define_feature_option:nnnnn{Ligatures}{Required}       {1}{0}{+rlig}
+\fontspec_define_feature_option:nnnnn{Ligatures}{NoRequired}     {1}{1}{-rlig}
+\fontspec_define_feature_option:nnnnn{Ligatures}{Common}         {1}{2}{+liga}
+\fontspec_define_feature_option:nnnnn{Ligatures}{NoCommon}       {1}{3}{-liga}
+\fontspec_define_feature_option:nnnnn{Ligatures}{Rare}           {1}{4}{+dlig}
+\fontspec_define_feature_option:nnnnn{Ligatures}{NoRare}         {1}{5}{-dlig}
+\fontspec_define_feature_option:nnnnn{Ligatures}{Discretionary}  {1}{4}{+dlig}
+\fontspec_define_feature_option:nnnnn{Ligatures}{NoDiscretionary}{1}{5}{-dlig}
+\fontspec_define_feature_option:nnnnn{Ligatures}{Contextual}     {}{}  {+clig}
+\fontspec_define_feature_option:nnnnn{Ligatures}{NoContextual}   {}{}  {-clig}
+\fontspec_define_feature_option:nnnnn{Ligatures}{Historic}       {}{}  {+hlig}
+\fontspec_define_feature_option:nnnnn{Ligatures}{NoHistoric}     {}{}  {-hlig}
+\fontspec_define_feature_option:nnnnn{Ligatures}{Logos}          {1}{6} {}
+\fontspec_define_feature_option:nnnnn{Ligatures}{NoLogos}        {1}{7} {}
+\fontspec_define_feature_option:nnnnn{Ligatures}{Rebus}          {1}{8} {}
+\fontspec_define_feature_option:nnnnn{Ligatures}{NoRebus}        {1}{9} {}
+\fontspec_define_feature_option:nnnnn{Ligatures}{Diphthong}      {1}{10}{}
+\fontspec_define_feature_option:nnnnn{Ligatures}{NoDiphthong}    {1}{11}{}
+\fontspec_define_feature_option:nnnnn{Ligatures}{Squared}        {1}{12}{}
+\fontspec_define_feature_option:nnnnn{Ligatures}{NoSquared}      {1}{13}{}
+\fontspec_define_feature_option:nnnnn{Ligatures}{AbbrevSquared}  {1}{14}{}
+\fontspec_define_feature_option:nnnnn{Ligatures}{NoAbbrevSquared}{1}{15}{}
+\fontspec_define_feature_option:nnnnn{Ligatures}{Icelandic}      {1}{32}{}
+\fontspec_define_feature_option:nnnnn{Ligatures}{NoIcelandic}    {1}{33}{}
 \define@key[zf@feat]{Ligatures}{TeX}[]{
   \xetex_or_luatex:nn {
-    \zf@update@family{+map:tex-text}
-    \zf@update@ff{mapping=tex-text}
+    \fontspec_update_fontid:n {+map:tex-text}
+    \fontspec_update_featstr:n{mapping=tex-text}
   }{
-    \zf@update@family{+tlig+trep}
-    \zf@update@ff{+tlig;+trep}
-  }
-}
-\zf@define@font@feature{Letters}
-\zf@define@feature@option{Letters}{Normal}             {3}{0}{}
-\zf@define@feature@option{Letters}{Uppercase}          {3}{1}{+case}
-\zf@define@feature@option{Letters}{Lowercase}          {3}{2}{}
-\zf@define@feature@option{Letters}{SmallCaps}          {3}{3}{+smcp}
-\zf@define@feature@option{Letters}{PetiteCaps}         {} {} {+pcap}
-\zf@define@feature@option{Letters}{UppercaseSmallCaps} {} {} {+c2sc}
-\zf@define@feature@option{Letters}{UppercasePetiteCaps}{} {} {+c2pc}
-\zf@define@feature@option{Letters}{InitialCaps}        {3}{4}{}
-\zf@define@feature@option{Letters}{Unicase}            {} {} {+unic}
-\zf@define@font@feature{Numbers}
-\zf@define@feature@option{Numbers}{Monospaced}   {6} {0}{+tnum}
-\zf@define@feature@option{Numbers}{Proportional} {6} {1}{+pnum}
-\zf@define@feature@option{Numbers}{Lowercase}    {21}{0}{+onum}
-\zf@define@feature@option{Numbers}{OldStyle}     {21}{0}{+onum}
-\zf@define@feature@option{Numbers}{Uppercase}    {21}{1}{+lnum}
-\zf@define@feature@option{Numbers}{Lining}       {21}{1}{+lnum}
-\zf@define@feature@option{Numbers}{SlashedZero}  {14}{5}{+zero}
-\zf@define@feature@option{Numbers}{NoSlashedZero}{14}{4}{-zero}
+    \fontspec_update_fontid:n {+tlig+trep}
+    \fontspec_update_featstr:n{+tlig;+trep}
+  }
+}
+\fontspec_define_font_feature:n{Letters}
+\fontspec_define_feature_option:nnnnn{Letters}{Normal}             {3}{0}{}
+\fontspec_define_feature_option:nnnnn{Letters}{Uppercase}          {3}{1}{+case}
+\fontspec_define_feature_option:nnnnn{Letters}{Lowercase}          {3}{2}{}
+\fontspec_define_feature_option:nnnnn{Letters}{SmallCaps}          {3}{3}{+smcp}
+\fontspec_define_feature_option:nnnnn{Letters}{PetiteCaps}         {} {} {+pcap}
+\fontspec_define_feature_option:nnnnn{Letters}{UppercaseSmallCaps} {} {} {+c2sc}
+\fontspec_define_feature_option:nnnnn{Letters}{UppercasePetiteCaps}{} {} {+c2pc}
+\fontspec_define_feature_option:nnnnn{Letters}{InitialCaps}        {3}{4}{}
+\fontspec_define_feature_option:nnnnn{Letters}{Unicase}            {} {} {+unic}
+\fontspec_define_font_feature:n{Numbers}
+\fontspec_define_feature_option:nnnnn{Numbers}{Monospaced}   {6} {0}{+tnum}
+\fontspec_define_feature_option:nnnnn{Numbers}{Proportional} {6} {1}{+pnum}
+\fontspec_define_feature_option:nnnnn{Numbers}{Lowercase}    {21}{0}{+onum}
+\fontspec_define_feature_option:nnnnn{Numbers}{OldStyle}     {21}{0}{+onum}
+\fontspec_define_feature_option:nnnnn{Numbers}{Uppercase}    {21}{1}{+lnum}
+\fontspec_define_feature_option:nnnnn{Numbers}{Lining}       {21}{1}{+lnum}
+\fontspec_define_feature_option:nnnnn{Numbers}{SlashedZero}  {14}{5}{+zero}
+\fontspec_define_feature_option:nnnnn{Numbers}{NoSlashedZero}{14}{4}{-zero}
 \luatex_if_engine:T {
-  \zf@define@feature@option{Numbers}{Arabic}{}{}{+anum}
-}
-\zf@define@font@feature  {Contextuals}
-\zf@define@feature@option{Contextuals}{Swash}        {} {} {+cswh}
-\zf@define@feature@option{Contextuals}{NoSwash}      {} {} {-cswh}
-\zf@define@feature@option{Contextuals}{Alternate}    {} {} {+calt}
-\zf@define@feature@option{Contextuals}{NoAlternate}  {} {} {-calt}
-\zf@define@feature@option{Contextuals}{WordInitial}  {8}{0}{+init}
-\zf@define@feature@option{Contextuals}{NoWordInitial}{8}{1}{-init}
-\zf@define@feature@option{Contextuals}{WordFinal}    {8}{2}{+fina}
-\zf@define@feature@option{Contextuals}{NoWordFinal}  {8}{3}{-fina}
-\zf@define@feature@option{Contextuals}{LineInitial}  {8}{4}{}
-\zf@define@feature@option{Contextuals}{NoLineInitial}{8}{5}{}
-\zf@define@feature@option{Contextuals}{LineFinal}    {8}{6}{+falt}
-\zf@define@feature@option{Contextuals}{NoLineFinal}  {8}{7}{-falt}
-\zf@define@feature@option{Contextuals}{Inner}        {8}{8}{+medi}
-\zf@define@feature@option{Contextuals}{NoInner}      {8}{9}{-medi}
-\zf@define@font@feature{Diacritics}
-\zf@define@feature@option{Diacritics}{Show}        {9}{0}{}
-\zf@define@feature@option{Diacritics}{Hide}        {9}{1}{}
-\zf@define@feature@option{Diacritics}{Decompose}   {9}{2}{}
-\zf@define@feature@option{Diacritics}{MarkToBase}  {}{}{+mark}
-\zf@define@feature@option{Diacritics}{NoMarkToBase}{}{}{-mark}
-\zf@define@feature@option{Diacritics}{MarkToMark}  {}{}{+mkmk}
-\zf@define@feature@option{Diacritics}{NoMarkToMark}{}{}{-mkmk}
-\zf@define@feature@option{Diacritics}{AboveBase}   {}{}{+abvm}
-\zf@define@feature@option{Diacritics}{NoAboveBase} {}{}{-abvm}
-\zf@define@feature@option{Diacritics}{BelowBase}   {}{}{+blwm}
-\zf@define@feature@option{Diacritics}{NoBelowBase} {}{}{-blwm}
-\zf@define@font@feature{Kerning}
-\zf@define@feature@option{Kerning}{Uppercase}{}{}{+cpsp}
-\zf@define@feature@option{Kerning}{On}       {}{}{+kern}
-\zf@define@feature@option{Kerning}{Off}      {}{}{-kern}
-\zf@define@font@feature{VerticalPosition}
-\zf@define@feature@option{VerticalPosition}{Normal}     {10}{0}{}
-\zf@define@feature@option{VerticalPosition}{Superior}   {10}{1}{+sups}
-\zf@define@feature@option{VerticalPosition}{Inferior}   {10}{2}{+subs}
-\zf@define@feature@option{VerticalPosition}{Ordinal}    {10}{3}{+ordn}
-\zf@define@feature@option{VerticalPosition}{Numerator}  {}  {} {+numr}
-\zf@define@feature@option{VerticalPosition}{Denominator}{}  {} {+dnom}
-\zf@define@feature@option{VerticalPosition}{ScientificInferior}{}{}{+sinf}
-\zf@define@font@feature{Fractions}
-\zf@define@feature@option{Fractions}{On}       {11}{1}{+frac}
-\zf@define@feature@option{Fractions}{Off}      {11}{0}{-frac}
-\zf@define@feature@option{Fractions}{Diagonal} {11}{2}{}
-\zf@define@feature@option{Fractions}{Alternate}{}  {} {+afrc}
+  \fontspec_define_feature_option:nnnnn{Numbers}{Arabic}{}{}{+anum}
+}
+\fontspec_define_font_feature:n  {Contextuals}
+\fontspec_define_feature_option:nnnnn{Contextuals}{Swash}        {} {} {+cswh}
+\fontspec_define_feature_option:nnnnn{Contextuals}{NoSwash}      {} {} {-cswh}
+\fontspec_define_feature_option:nnnnn{Contextuals}{Alternate}    {} {} {+calt}
+\fontspec_define_feature_option:nnnnn{Contextuals}{NoAlternate}  {} {} {-calt}
+\fontspec_define_feature_option:nnnnn{Contextuals}{WordInitial}  {8}{0}{+init}
+\fontspec_define_feature_option:nnnnn{Contextuals}{NoWordInitial}{8}{1}{-init}
+\fontspec_define_feature_option:nnnnn{Contextuals}{WordFinal}    {8}{2}{+fina}
+\fontspec_define_feature_option:nnnnn{Contextuals}{NoWordFinal}  {8}{3}{-fina}
+\fontspec_define_feature_option:nnnnn{Contextuals}{LineInitial}  {8}{4}{}
+\fontspec_define_feature_option:nnnnn{Contextuals}{NoLineInitial}{8}{5}{}
+\fontspec_define_feature_option:nnnnn{Contextuals}{LineFinal}    {8}{6}{+falt}
+\fontspec_define_feature_option:nnnnn{Contextuals}{NoLineFinal}  {8}{7}{-falt}
+\fontspec_define_feature_option:nnnnn{Contextuals}{Inner}        {8}{8}{+medi}
+\fontspec_define_feature_option:nnnnn{Contextuals}{NoInner}      {8}{9}{-medi}
+\fontspec_define_font_feature:n{Diacritics}
+\fontspec_define_feature_option:nnnnn{Diacritics}{Show}        {9}{0}{}
+\fontspec_define_feature_option:nnnnn{Diacritics}{Hide}        {9}{1}{}
+\fontspec_define_feature_option:nnnnn{Diacritics}{Decompose}   {9}{2}{}
+\fontspec_define_feature_option:nnnnn{Diacritics}{MarkToBase}  {}{}{+mark}
+\fontspec_define_feature_option:nnnnn{Diacritics}{NoMarkToBase}{}{}{-mark}
+\fontspec_define_feature_option:nnnnn{Diacritics}{MarkToMark}  {}{}{+mkmk}
+\fontspec_define_feature_option:nnnnn{Diacritics}{NoMarkToMark}{}{}{-mkmk}
+\fontspec_define_feature_option:nnnnn{Diacritics}{AboveBase}   {}{}{+abvm}
+\fontspec_define_feature_option:nnnnn{Diacritics}{NoAboveBase} {}{}{-abvm}
+\fontspec_define_feature_option:nnnnn{Diacritics}{BelowBase}   {}{}{+blwm}
+\fontspec_define_feature_option:nnnnn{Diacritics}{NoBelowBase} {}{}{-blwm}
+\fontspec_define_font_feature:n{Kerning}
+\fontspec_define_feature_option:nnnnn{Kerning}{Uppercase}{}{}{+cpsp}
+\fontspec_define_feature_option:nnnnn{Kerning}{On}       {}{}{+kern}
+\fontspec_define_feature_option:nnnnn{Kerning}{Off}      {}{}{-kern}
+\fontspec_define_font_feature:n{VerticalPosition}
+\fontspec_define_feature_option:nnnnn{VerticalPosition}{Normal}     {10}{0}{}
+\fontspec_define_feature_option:nnnnn{VerticalPosition}{Superior}   {10}{1}{+sups}
+\fontspec_define_feature_option:nnnnn{VerticalPosition}{Inferior}   {10}{2}{+subs}
+\fontspec_define_feature_option:nnnnn{VerticalPosition}{Ordinal}    {10}{3}{+ordn}
+\fontspec_define_feature_option:nnnnn{VerticalPosition}{Numerator}  {}  {} {+numr}
+\fontspec_define_feature_option:nnnnn{VerticalPosition}{Denominator}{}  {} {+dnom}
+\fontspec_define_feature_option:nnnnn{VerticalPosition}{ScientificInferior}{}{}{+sinf}
+\fontspec_define_font_feature:n{Fractions}
+\fontspec_define_feature_option:nnnnn{Fractions}{On}       {11}{1}{+frac}
+\fontspec_define_feature_option:nnnnn{Fractions}{Off}      {11}{0}{-frac}
+\fontspec_define_feature_option:nnnnn{Fractions}{Diagonal} {11}{2}{}
+\fontspec_define_feature_option:nnnnn{Fractions}{Alternate}{}  {} {+afrc}
 \define@key[zf]{options}{Alternate}[0]{
   \clist_set_eq:NN \l_fontspec_tmpa_clist \XKV@rm
   \setkeys*[zf@feat]{Alternate}{#1}
-  \unless\ifx\XKV@rm\@empty
+  \tl_if_empty:NF \XKV@rm {
     \def\XKV@tfam{Alternate}
     \fontspec_make_feature:nnx {17}{#1} { \fontspec_salt:n {#1} }
-  \fi
+  }
   \clist_set_eq:NN \XKV@rm \l_fontspec_tmpa_clist
 }
 \xetex_or_luatex:nnn { \cs_set:Npn \fontspec_salt:n #1 }
@@ -1612,83 +1662,83 @@
 \define@key[zf]{options}{Variant}{
   \clist_set_eq:NN \l_fontspec_tmpa_clist \XKV@rm
   \setkeys*[zf@feat]{Variant}{#1}
-  \unless\ifx\XKV@rm\@empty
+  \tl_if_empty:NF \XKV@rm {
     \def\XKV@tfam{Variant}
     \fontspec_make_feature:nnx {18}{#1} { +ss \two@digits {#1} }
-  \fi
+  }
   \clist_set_eq:NN \XKV@rm \l_fontspec_tmpa_clist
 }
 \aliasfontfeature{Variant}{StylisticSet}
 \define@key[zf]{options}{CharacterVariant}{
   \clist_set_eq:NN \l_fontspec_tmpa_clist \XKV@rm
   \setkeys*[zf@feat]{CharacterVariant}{#1}
-  \unless\ifx\XKV@rm\@empty
+  \tl_if_empty:NF \XKV@rm {
     \def\XKV@tfam{CharacterVariant}
     \fontspec_make_feature:nnx {}{} { +cv \two@digits {#1} }
-  \fi
+  }
   \clist_set_eq:NN \XKV@rm \l_fontspec_tmpa_clist
 }
-\zf@define@font@feature{Style}
-\zf@define@feature@option{Style}{Alternate}     {}  {} {+salt}
-\zf@define@feature@option{Style}{Italic}        {32}{2}{+ital}
-\zf@define@feature@option{Style}{Ruby}          {28}{2}{+ruby}
-\zf@define@feature@option{Style}{Swash}         {}  {} {+swsh}
-\zf@define@feature@option{Style}{Historic}      {}  {} {+hist}
-\zf@define@feature@option{Style}{Display}       {19}{1}{}
-\zf@define@feature@option{Style}{Engraved}      {19}{2}{}
-\zf@define@feature@option{Style}{TitlingCaps}   {19}{4}{+titl}
-\zf@define@feature@option{Style}{TallCaps}      {19}{5}{}
-\zf@define@feature@option{Style}{HorizontalKana}{}  {} {+hkna}
-\zf@define@feature@option{Style}{VerticalKana}  {}  {} {+vkna}
-\zf@define@font@feature{CJKShape}
-\zf@define@feature@option{CJKShape}{Traditional}{20}{0} {+trad}
-\zf@define@feature@option{CJKShape}{Simplified} {20}{1} {+smpl}
-\zf@define@feature@option{CJKShape}{JIS1978}    {20}{2} {+jp78}
-\zf@define@feature@option{CJKShape}{JIS1983}    {20}{3} {+jp83}
-\zf@define@feature@option{CJKShape}{JIS1990}    {20}{4} {+jp90}
-\zf@define@feature@option{CJKShape}{Expert}     {20}{10}{+expt}
-\zf@define@feature@option{CJKShape}{NLC}        {20}{13}{+nlck}
-\zf@define@font@feature{CharacterWidth}
-\zf@define@feature@option{CharacterWidth}{Proportional}{22}{0}{+pwid}
-\zf@define@feature@option{CharacterWidth}{Full}{22}{1}{+fwid}
-\zf@define@feature@option{CharacterWidth}{Half}{22}{2}{+hwid}
-\zf@define@feature@option{CharacterWidth}{Third}{22}{3}{+twid}
-\zf@define@feature@option{CharacterWidth}{Quarter}{22}{4}{+qwid}
-\zf@define@feature@option{CharacterWidth}{AlternateProportional}{22}{5}{+palt}
-\zf@define@feature@option{CharacterWidth}{AlternateHalf}{22}{6}{+halt}
-\zf@define@feature@option{CharacterWidth}{Default}{22}{7}{}
-\zf@define@feature@option{Annotation}{Off}{24}{0}{}
-\zf@define@feature@option{Annotation}{Box}{24}{1}{}
-\zf@define@feature@option{Annotation}{RoundedBox}{24}{2}{}
-\zf@define@feature@option{Annotation}{Circle}{24}{3}{}
-\zf@define@feature@option{Annotation}{BlackCircle}{24}{4}{}
-\zf@define@feature@option{Annotation}{Parenthesis}{24}{5}{}
-\zf@define@feature@option{Annotation}{Period}{24}{6}{}
-\zf@define@feature@option{Annotation}{RomanNumerals}{24}{7}{}
-\zf@define@feature@option{Annotation}{Diamond}{24}{8}{}
-\zf@define@feature@option{Annotation}{BlackSquare}{24}{9}{}
-\zf@define@feature@option{Annotation}{BlackRoundSquare}{24}{10}{}
-\zf@define@feature@option{Annotation}{DoubleCircle}{24}{11}{}
+\fontspec_define_font_feature:n{Style}
+\fontspec_define_feature_option:nnnnn{Style}{Alternate}     {}  {} {+salt}
+\fontspec_define_feature_option:nnnnn{Style}{Italic}        {32}{2}{+ital}
+\fontspec_define_feature_option:nnnnn{Style}{Ruby}          {28}{2}{+ruby}
+\fontspec_define_feature_option:nnnnn{Style}{Swash}         {}  {} {+swsh}
+\fontspec_define_feature_option:nnnnn{Style}{Historic}      {}  {} {+hist}
+\fontspec_define_feature_option:nnnnn{Style}{Display}       {19}{1}{}
+\fontspec_define_feature_option:nnnnn{Style}{Engraved}      {19}{2}{}
+\fontspec_define_feature_option:nnnnn{Style}{TitlingCaps}   {19}{4}{+titl}
+\fontspec_define_feature_option:nnnnn{Style}{TallCaps}      {19}{5}{}
+\fontspec_define_feature_option:nnnnn{Style}{HorizontalKana}{}  {} {+hkna}
+\fontspec_define_feature_option:nnnnn{Style}{VerticalKana}  {}  {} {+vkna}
+\fontspec_define_font_feature:n{CJKShape}
+\fontspec_define_feature_option:nnnnn{CJKShape}{Traditional}{20}{0} {+trad}
+\fontspec_define_feature_option:nnnnn{CJKShape}{Simplified} {20}{1} {+smpl}
+\fontspec_define_feature_option:nnnnn{CJKShape}{JIS1978}    {20}{2} {+jp78}
+\fontspec_define_feature_option:nnnnn{CJKShape}{JIS1983}    {20}{3} {+jp83}
+\fontspec_define_feature_option:nnnnn{CJKShape}{JIS1990}    {20}{4} {+jp90}
+\fontspec_define_feature_option:nnnnn{CJKShape}{Expert}     {20}{10}{+expt}
+\fontspec_define_feature_option:nnnnn{CJKShape}{NLC}        {20}{13}{+nlck}
+\fontspec_define_font_feature:n{CharacterWidth}
+\fontspec_define_feature_option:nnnnn{CharacterWidth}{Proportional}{22}{0}{+pwid}
+\fontspec_define_feature_option:nnnnn{CharacterWidth}{Full}{22}{1}{+fwid}
+\fontspec_define_feature_option:nnnnn{CharacterWidth}{Half}{22}{2}{+hwid}
+\fontspec_define_feature_option:nnnnn{CharacterWidth}{Third}{22}{3}{+twid}
+\fontspec_define_feature_option:nnnnn{CharacterWidth}{Quarter}{22}{4}{+qwid}
+\fontspec_define_feature_option:nnnnn{CharacterWidth}{AlternateProportional}{22}{5}{+palt}
+\fontspec_define_feature_option:nnnnn{CharacterWidth}{AlternateHalf}{22}{6}{+halt}
+\fontspec_define_feature_option:nnnnn{CharacterWidth}{Default}{22}{7}{}
+\fontspec_define_feature_option:nnnnn{Annotation}{Off}{24}{0}{}
+\fontspec_define_feature_option:nnnnn{Annotation}{Box}{24}{1}{}
+\fontspec_define_feature_option:nnnnn{Annotation}{RoundedBox}{24}{2}{}
+\fontspec_define_feature_option:nnnnn{Annotation}{Circle}{24}{3}{}
+\fontspec_define_feature_option:nnnnn{Annotation}{BlackCircle}{24}{4}{}
+\fontspec_define_feature_option:nnnnn{Annotation}{Parenthesis}{24}{5}{}
+\fontspec_define_feature_option:nnnnn{Annotation}{Period}{24}{6}{}
+\fontspec_define_feature_option:nnnnn{Annotation}{RomanNumerals}{24}{7}{}
+\fontspec_define_feature_option:nnnnn{Annotation}{Diamond}{24}{8}{}
+\fontspec_define_feature_option:nnnnn{Annotation}{BlackSquare}{24}{9}{}
+\fontspec_define_feature_option:nnnnn{Annotation}{BlackRoundSquare}{24}{10}{}
+\fontspec_define_feature_option:nnnnn{Annotation}{DoubleCircle}{24}{11}{}
 \define@key[zf]{options}{Annotation}[0]{
   \clist_set_eq:NN \l_fontspec_tmpa_clist \XKV@rm
   \setkeys*[zf@feat]{Annotation}{#1}
-  \unless\ifx\XKV@rm\@empty
+  \tl_if_empty:NF \XKV@rm {
     \def\XKV@tfam{Alternate}
     \fontspec_make_feature:nnx {}{} { \fontspec_nalt:n {#1} }
-  \fi
+  }
   \clist_set_eq:NN \XKV@rm \l_fontspec_tmpa_clist
 }
 \xetex_or_luatex:nnn { \cs_set:Npn \fontspec_nalt:n #1 }
   {+nalt=#1} { +nalt= \intexpr_eval:n {#1+1} }
-\zf@define@font@feature{Vertical}
+\fontspec_define_font_feature:n{Vertical}
 \define@key[zf@feat]{Vertical}{RotatedGlyphs}[]{
   \ifzf@icu
     \fontspec_make_feature:nnn{}{}{+vrt2}
-    \zf@update@family{+vert}
-    \zf@update@ff{vertical}
+    \fontspec_update_fontid:n {+vert}
+    \fontspec_update_featstr:n{vertical}
   \else
-    \zf@update@family{+vert}
-    \zf@update@ff{vertical}
+    \fontspec_update_fontid:n {+vert}
+    \fontspec_update_featstr:n{vertical}
   \fi
 }
 \newfontscript{Arabic}{arab}            \newfontscript{Armenian}{armn}
@@ -1928,27 +1978,28 @@
 \newfontlanguage{Zulu}{ZUL}
 \define@key[zf@feat]{Lang}{Turkish}[]{
   \fontspec_check_lang:nTF {TRK} {
-    \c@zf@language\l_fontspec_strnum_int\relax
-    \zf@update@family{+lang=Turkish}
+    \int_set:Nn \l_fontspec_language_int {\l_fontspec_strnum_int}
+    \fontspec_update_fontid:n {+lang=Turkish}
     \tl_set:Nn \l_fontspec_lang_tl {TRK}
   }{
     \fontspec_check_lang:nTF {TUR} {
-      \c@zf@language\l_fontspec_strnum_int\relax
-      \zf@update@family{+lang=Turkish}
+      \int_set:Nn \l_fontspec_language_int {\l_fontspec_strnum_int}
+      \fontspec_update_fontid:n {+lang=Turkish}
       \tl_set:Nn \l_fontspec_lang_tl {TUR}
     }{
       \fontspec_warning:nx {language-not-exist} {#1}
+      \setkeys[zf@feat]{Lang}{Default}
     }
   }
 }
 \define@key[zf@feat]{Lang}{Default}[]{
-  \zf@update@family{+lang=dflt}
+  \fontspec_update_fontid:n {+lang=dflt}
   \tl_set:Nn \l_fontspec_lang_tl {DFLT}
-  \c@zf@language=0\relax
+  \int_zero:N \l_fontspec_language_int
 }
 \define@key[zf]{options}{RawFeature}{
-  \zf@update@family{+Raw:#1}
-  \zf@update@ff{#1}
+  \fontspec_update_fontid:n {+Raw:#1}
+  \fontspec_update_featstr:n{#1}
 }
 \providecommand*{\sidefault}{si}
 \DeclareRobustCommand{\sishape}{
@@ -1956,37 +2007,34 @@
   \fontshape\sidefault\selectfont
 }
 \DeclareTextFontCommand{\textsi}{\sishape}
-\newcommand*{\zf@merge@shape}[3]{
-  \edef\@tempa{#1}
-  \edef\@tempb{#2}
-  \ifx\f@shape\@tempb
-    \ifcsname\f@encoding/\f@family/\f@series/#3\endcsname
-      \edef\@tempa{#3}
-    \fi
-  \fi
-  \fontshape{\@tempa}\selectfont
+\cs_new:Nn \fontspec_blend_shape:nnn {
+  \bool_if:nTF
+  {
+    \str_if_eq_p:xx {\f@shape} {#2} &&
+    \cs_if_exist_p:c {\f@encoding/\f@family/\f@series/#3}
+  }
+  { \fontshape{#3}\selectfont }
+  { \fontshape{#1}\selectfont }
 }
 \DeclareRobustCommand \itshape {
   \not@math@alphabet\itshape\mathit
-  \zf@merge@shape\itdefault\scdefault\sidefault
+  \fontspec_blend_shape:nnn\itdefault\scdefault\sidefault
 }
 \DeclareRobustCommand \slshape {
   \not@math@alphabet\slshape\relax
-  \zf@merge@shape\sldefault\scdefault\sidefault
+  \fontspec_blend_shape:nnn\sldefault\scdefault\sidefault
 }
 \DeclareRobustCommand \scshape {
   \not@math@alphabet\scshape\relax
-  \zf@merge@shape\scdefault\itdefault\sidefault
+  \fontspec_blend_shape:nnn\scdefault\itdefault\sidefault
 }
 \DeclareRobustCommand \upshape {
   \not@math@alphabet\upshape\relax
-  \zf@merge@shape\updefault\sidefault\scdefault
+  \fontspec_blend_shape:nnn\updefault\sidefault\scdefault
 }
 \@ifpackageloaded{euler}{\zf@package@euler@loadedtrue}
                         {\zf@package@euler@loadedfalse}
-\def\zf@math{
-  \let\zf@font@warning\@font@warning
-  \let\@font@warning\@font@info
+\cs_set:Nn \fontspec_setup_maths: {
   \@ifpackageloaded{euler}{
     \ifzf@package@euler@loaded
       \zf@math@eulertrue
@@ -2009,13 +2057,12 @@
   \DeclareMathAccent{\hat}     {\mathalpha}{legacymaths}{94} % too bad, euler
   \DeclareMathAccent{\dot}     {\mathalpha}{legacymaths}{95}
   \DeclareMathAccent{\mathring}{\mathalpha}{legacymaths}{23}
-  \begingroup
+  \group_begin:
     \mathchardef\@tempa="603A \relax
-    \let\next\egroup
     \ifx\colon\@tempa
       \DeclareMathSymbol{\colon}{\mathpunct}{legacymaths}{58}
     \fi
-  \endgroup
+  \group_end:
   \ifzf@math@euler\else
     \DeclareMathSymbol{!}{\mathclose}{legacymaths}{33}
     \DeclareMathSymbol{:}{\mathrel}  {legacymaths}{58}
@@ -2053,26 +2100,26 @@
       \DeclareMathSymbol{\mathdollar}{\mathord}{legacymaths}{36}
     \fi
   \fi
-  \DeclareSymbolFont{operators}\zf@enc\zf@rmmaths\mddefault\updefault
-  \SetSymbolFont{operators}{normal}\zf@enc\zf@rmmaths\mddefault\updefault
-  \SetMathAlphabet\mathrm{normal}\zf@enc\zf@rmmaths\mddefault\updefault
-  \SetMathAlphabet\mathit{normal}\zf@enc\zf@rmmaths\mddefault\itdefault
-  \SetMathAlphabet\mathbf{normal}\zf@enc\zf@rmmaths\bfdefault\updefault
-  \SetMathAlphabet\mathsf{normal}\zf@enc\zf@sfmaths\mddefault\updefault
-  \SetMathAlphabet\mathtt{normal}\zf@enc\zf@ttmaths\mddefault\updefault
-  \SetSymbolFont{operators}{bold}\zf@enc\zf@rmmaths\bfdefault\updefault
-  \ifdefined\zf@rmboldmaths
-    \SetMathAlphabet\mathrm{bold}\zf@enc\zf@rmboldmaths\mddefault\updefault
-    \SetMathAlphabet\mathbf{bold}\zf@enc\zf@rmboldmaths\bfdefault\updefault
-    \SetMathAlphabet\mathit{bold}\zf@enc\zf@rmboldmaths\mddefault\itdefault
+  \DeclareSymbolFont{operators}\zf@enc\g_fontspec_mathrm_tl\mddefault\updefault
+  \SetSymbolFont{operators}{normal}\zf@enc\g_fontspec_mathrm_tl\mddefault\updefault
+  \SetMathAlphabet\mathrm{normal}\zf@enc\g_fontspec_mathrm_tl\mddefault\updefault
+  \SetMathAlphabet\mathit{normal}\zf@enc\g_fontspec_mathrm_tl\mddefault\itdefault
+  \SetMathAlphabet\mathbf{normal}\zf@enc\g_fontspec_mathrm_tl\bfdefault\updefault
+  \SetMathAlphabet\mathsf{normal}\zf@enc\g_fontspec_mathsf_tl\mddefault\updefault
+  \SetMathAlphabet\mathtt{normal}\zf@enc\g_fontspec_mathtt_tl\mddefault\updefault
+  \SetSymbolFont{operators}{bold}\zf@enc\g_fontspec_mathrm_tl\bfdefault\updefault
+  \ifdefined\g_fontspec_bfmathrm_tl
+    \SetMathAlphabet\mathrm{bold}\zf@enc\g_fontspec_bfmathrm_tl\mddefault\updefault
+    \SetMathAlphabet\mathbf{bold}\zf@enc\g_fontspec_bfmathrm_tl\bfdefault\updefault
+    \SetMathAlphabet\mathit{bold}\zf@enc\g_fontspec_bfmathrm_tl\mddefault\itdefault
   \else
-    \SetMathAlphabet\mathrm{bold}\zf@enc\zf@rmmaths\bfdefault\updefault
-    \SetMathAlphabet\mathit{bold}\zf@enc\zf@rmmaths\bfdefault\itdefault
+    \SetMathAlphabet\mathrm{bold}\zf@enc\g_fontspec_mathrm_tl\bfdefault\updefault
+    \SetMathAlphabet\mathit{bold}\zf@enc\g_fontspec_mathrm_tl\bfdefault\itdefault
   \fi
-  \SetMathAlphabet\mathsf{bold}\zf@enc\zf@sfmaths\bfdefault\updefault
-  \SetMathAlphabet\mathtt{bold}\zf@enc\zf@ttmaths\bfdefault\updefault
-  \let\font@warning\zf@font@warning}
-\def\zf@math@maybe{
+  \SetMathAlphabet\mathsf{bold}\zf@enc\g_fontspec_mathsf_tl\bfdefault\updefault
+  \SetMathAlphabet\mathtt{bold}\zf@enc\g_fontspec_mathtt_tl\bfdefault\updefault
+}
+\cs_new:Nn \fontspec_maybe_setup_maths: {
   \@ifpackageloaded{anttor}{
     \ifx\define@antt@mathversions a\@zf@mathfalse\fi}{}
   \@ifpackageloaded{arev}{\@zf@mathfalse}{}
@@ -2098,13 +2145,13 @@
   \@ifpackageloaded{breqn}{\@zf@mathfalse}{}
   \if@zf@math
     \fontspec_info:n {setup-math}
-    \zf@math
+    \fontspec_setup_maths:
   \fi
 }
-\AtBeginDocument{\zf@math@maybe}
+\AtBeginDocument{\fontspec_maybe_setup_maths:}
 \if@zf@configfile
   \InputIfFileExists{fontspec.cfg}
-    {\typeout{fontspec.cfg~ loaded.}}
+    {}
     {\typeout{No~ fontspec.cfg~ file~ found;~ no~ configuration~ loaded.}}
 \fi
 %% 
-- 
cgit v1.2.3

