Merge branch 'master' into var-subset
diff --git a/src/hb-bimap.hh b/src/hb-bimap.hh
index cae0a4d..e9f3a6a 100644
--- a/src/hb-bimap.hh
+++ b/src/hb-bimap.hh
@@ -151,9 +151,9 @@
 
     for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
       work[rhs] = back_map[rhs];
-  
+
     work.qsort (cmp_id);
-  
+
     clear ();
     for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
       set (work[rhs], rhs);
diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh
index ad20651..ffee690 100644
--- a/src/hb-ot-cff1-table.hh
+++ b/src/hb-ot-cff1-table.hh
@@ -612,7 +612,7 @@
     for (unsigned int i = 0; i < strings.count; i++)
     {
       hb_codepoint_t  j = sidmap[i];
-      if (j != CFF_UNDEF_CODE)
+      if (j != HB_MAP_VALUE_INVALID)
 	bytesArray[j] = strings[i];
     }
 
@@ -630,7 +630,7 @@
 
     unsigned int dataSize = 0;
     for (unsigned int i = 0; i < count; i++)
-      if (sidmap[i] != CFF_UNDEF_CODE)
+      if (sidmap[i] != HB_MAP_VALUE_INVALID)
 	dataSize += length_at (i);
 
     offSize_ = calcOffSize(dataSize);
diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh
index e20b372..415a5aa 100644
--- a/src/hb-ot-hmtx-table.hh
+++ b/src/hb-ot-hmtx-table.hh
@@ -250,7 +250,7 @@
 	return advance;
 
       if (var_table.get_length ())
-	return advance + roundf (var_table->get_advance_var (font, glyph)); // TODO Optimize?!
+	return advance + roundf (var_table->get_advance_var (glyph, font)); // TODO Optimize?!
 
       return _glyf_get_advance_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
 #else
diff --git a/src/hb-ot-var-hvar-table.hh b/src/hb-ot-var-hvar-table.hh
index 223430f..eda74c7 100644
--- a/src/hb-ot-var-hvar-table.hh
+++ b/src/hb-ot-var-hvar-table.hh
@@ -44,6 +44,38 @@
 				  get_width ()));
   }
 
+  template <typename T>
+  bool serialize (hb_serialize_context_t *c, const T &plan)
+  {
+    unsigned int width = plan.get_width ();
+    unsigned int inner_bit_count = plan.get_inner_bit_count ();
+    const hb_array_t<const unsigned int> output_map = plan.get_output_map ();
+
+    TRACE_SERIALIZE (this);
+    if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0))))
+      return_trace (false);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    format = ((width-1)<<4)|(inner_bit_count-1);
+    mapCount = output_map.length;
+    HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length);
+    if (unlikely (!p)) return_trace (false);
+    for (unsigned int i = 0; i < output_map.length; i++)
+    {
+      unsigned int v = output_map[i];
+      unsigned int outer = v >> 16;
+      unsigned int inner = v & 0xFFFF;
+      unsigned int u = (outer << inner_bit_count) | inner;
+      for (unsigned int w = width; w > 0;)
+      {
+	p[--w] = u;
+	u >>= 8;
+      }
+      p += width;
+    }
+    return_trace (true);
+  }
+
   unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */
   {
     /* If count is zero, pass value unchanged.  This takes
@@ -63,7 +95,7 @@
     }
 
     { /* Repack it. */
-      unsigned int n = get_inner_bitcount ();
+      unsigned int n = get_inner_bit_count ();
       unsigned int outer = u >> n;
       unsigned int inner = u & ((1 << n) - 1);
       u = (outer<<16) | inner;
@@ -72,10 +104,9 @@
     return u;
   }
 
-  protected:
-  unsigned int get_width () const          { return ((format >> 4) & 3) + 1; }
-
-  unsigned int get_inner_bitcount () const { return (format & 0xF) + 1; }
+  unsigned int get_map_count () const	    { return mapCount; }
+  unsigned int get_width () const           { return ((format >> 4) & 3) + 1; }
+  unsigned int get_inner_bit_count () const { return (format & 0xF) + 1; }
 
   protected:
   HBUINT16	format;		/* A packed field that describes the compressed
@@ -88,6 +119,212 @@
   DEFINE_SIZE_ARRAY (4, mapDataZ);
 };
 
+struct index_map_subset_plan_t
+{
+  enum index_map_index_t {
+    ADV_INDEX,
+    LSB_INDEX,	/* dual as TSB */
+    RSB_INDEX,	/* dual as BSB */
+    VORG_INDEX
+  };
+
+  void init (const DeltaSetIndexMap	&index_map,
+	     hb_inc_bimap_t	  	&outer_map,
+	     hb_vector_t<hb_set_t *>	&inner_sets,
+	     const hb_subset_plan_t *plan)
+  {
+    map_count = 0;
+    outer_bit_count = 0;
+    inner_bit_count = 1;
+    max_inners.init ();
+    output_map.init ();
+
+    if (&index_map == &Null(DeltaSetIndexMap)) return;
+
+    unsigned int	last_val = (unsigned int)-1;
+    hb_codepoint_t	last_gid = (hb_codepoint_t)-1;
+    hb_codepoint_t	gid = (hb_codepoint_t) hb_min (index_map.get_map_count (), plan->num_output_glyphs ());
+
+    outer_bit_count = (index_map.get_width () * 8) - index_map.get_inner_bit_count ();
+    max_inners.resize (inner_sets.length);
+    for (unsigned i = 0; i < inner_sets.length; i++) max_inners[i] = 0;
+
+    /* Search backwards for a map value different from the last map value */
+    for (; gid > 0; gid--)
+    {
+      hb_codepoint_t	old_gid;
+      if (!plan->old_gid_for_new_gid (gid - 1, &old_gid))
+      {
+	if (last_gid == (hb_codepoint_t) -1)
+	  continue;
+	else
+	  break;
+      }
+
+      unsigned int v = index_map.map (old_gid);
+      if (last_gid == (hb_codepoint_t) -1)
+      {
+	last_val = v;
+	last_gid = gid;
+	continue;
+      }
+      if (v != last_val) break;
+
+      last_gid = gid;
+    }
+
+    if (unlikely (last_gid == (hb_codepoint_t)-1)) return;
+    map_count = last_gid;
+    for (gid = 0; gid < map_count; gid++)
+    {
+      hb_codepoint_t	old_gid;
+      if (plan->old_gid_for_new_gid (gid, &old_gid))
+      {
+	unsigned int v = index_map.map (old_gid);
+	unsigned int outer = v >> 16;
+	unsigned int inner = v & 0xFFFF;
+	outer_map.add (outer);
+	if (inner > max_inners[outer]) max_inners[outer] = inner;
+	hb_set_add (inner_sets[outer], inner);
+      }
+    }
+  }
+
+  void fini ()
+  {
+    max_inners.fini ();
+    output_map.fini ();
+  }
+
+  void remap (const DeltaSetIndexMap *input_map,
+	      const hb_inc_bimap_t &outer_map,
+	      const hb_vector_t<hb_inc_bimap_t> &inner_maps,
+	      const hb_subset_plan_t *plan)
+  {
+    if (input_map == &Null(DeltaSetIndexMap)) return;
+
+    for (unsigned int i = 0; i < max_inners.length; i++)
+    {
+      if (inner_maps[i].get_population () == 0) continue;
+      unsigned int bit_count = (max_inners[i]==0)? 1: hb_bit_storage (inner_maps[i][max_inners[i]]);
+      if (bit_count > inner_bit_count) inner_bit_count = bit_count;
+    }
+
+    output_map.resize (map_count);
+    for (hb_codepoint_t gid = 0; gid < output_map.length; gid++)
+    {
+      hb_codepoint_t	old_gid;
+      if (plan->old_gid_for_new_gid (gid, &old_gid))
+      {
+	unsigned int v = input_map->map (old_gid);
+	unsigned int outer = v >> 16;
+	output_map[gid] = (outer_map[outer] << 16) | (inner_maps[outer][v & 0xFFFF]);
+      }
+      else
+	output_map[gid] = 0;	/* Map unused glyph to outer/inner=0/0 */
+    }
+  }
+
+  unsigned int get_inner_bit_count () const { return inner_bit_count; }
+  unsigned int get_width ()           const { return ((outer_bit_count + inner_bit_count + 7) / 8); }
+  unsigned int get_map_count ()       const { return map_count; }
+
+  unsigned int get_size () const
+  { return (map_count? (DeltaSetIndexMap::min_size + get_width () * map_count): 0); }
+
+  bool is_identity () const { return get_output_map ().length == 0; }
+  hb_array_t<const unsigned int> get_output_map () const { return output_map.as_array (); }
+
+  protected:
+  unsigned int map_count;
+  hb_vector_t<unsigned int> max_inners;
+  unsigned int outer_bit_count;
+  unsigned int inner_bit_count;
+  hb_vector_t<unsigned int> output_map;
+};
+
+struct hvarvvar_subset_plan_t
+{
+  hvarvvar_subset_plan_t() : inner_maps (), index_map_plans () {}
+  ~hvarvvar_subset_plan_t() { fini (); }
+
+  void init (const hb_array_t<const DeltaSetIndexMap *> &index_maps,
+	     const VariationStore &_var_store,
+	     const hb_subset_plan_t *plan)
+  {
+    index_map_plans.resize (index_maps.length);
+
+    var_store = &_var_store;
+    inner_sets.resize (var_store->get_sub_table_count ());
+    for (unsigned int i = 0; i < inner_sets.length; i++)
+      inner_sets[i] = hb_set_create ();
+    adv_set = hb_set_create ();
+
+    inner_maps.resize (var_store->get_sub_table_count ());
+
+    for (unsigned int i = 0; i < inner_maps.length; i++)
+      inner_maps[i].init ();
+
+    bool retain_adv_map = false;
+    index_map_plans[0].init (*index_maps[0], outer_map, inner_sets, plan);
+    if (index_maps[0] == &Null(DeltaSetIndexMap))
+    {
+      retain_adv_map = plan->retain_gids;
+      outer_map.add (0);
+      for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++)
+      {
+	hb_codepoint_t old_gid;
+	if (plan->old_gid_for_new_gid (gid, &old_gid))
+	  hb_set_add (inner_sets[0], old_gid);
+      }
+      hb_set_union (adv_set, inner_sets[0]);
+    }
+
+    for (unsigned int i = 1; i < index_maps.length; i++)
+      index_map_plans[i].init (*index_maps[i], outer_map, inner_sets, plan);
+
+    outer_map.sort ();
+
+    if (retain_adv_map)
+    {
+      for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++)
+      	if (hb_set_has (inner_sets[0], gid))
+	  inner_maps[0].add (gid);
+	else
+	  inner_maps[0].skip ();
+    }
+    else
+    {
+      inner_maps[0].add_set (adv_set);
+      hb_set_subtract (inner_sets[0], adv_set);
+      inner_maps[0].add_set (inner_sets[0]);
+    }
+
+    for (unsigned int i = 1; i < inner_maps.length; i++)
+      inner_maps[i].add_set (inner_sets[i]);
+
+    for (unsigned int i = 0; i < index_maps.length; i++)
+      index_map_plans[i].remap (index_maps[i], outer_map, inner_maps, plan);
+  }
+
+  void fini ()
+  {
+    for (unsigned int i = 0; i < inner_sets.length; i++)
+      hb_set_destroy (inner_sets[i]);
+    hb_set_destroy (adv_set);
+    inner_maps.fini_deep ();
+    index_map_plans.fini_deep ();
+  }
+
+  hb_inc_bimap_t outer_map;
+  hb_vector_t<hb_inc_bimap_t> inner_maps;
+  hb_vector_t<index_map_subset_plan_t> index_map_plans;
+  const VariationStore *var_store;
+
+  protected:
+  hb_vector_t<hb_set_t *> inner_sets;
+  hb_set_t *adv_set;
+};
 
 /*
  * HVAR -- Horizontal Metrics Variations
@@ -114,7 +351,59 @@
 		  rsbMap.sanitize (c, this));
   }
 
-  float get_advance_var (hb_font_t *font, hb_codepoint_t glyph) const
+  void listup_index_maps (hb_vector_t<const DeltaSetIndexMap *> &index_maps) const
+  {
+    index_maps.push (&(this+advMap));
+    index_maps.push (&(this+lsbMap));
+    index_maps.push (&(this+rsbMap));
+  }
+
+  bool serialize_index_maps (hb_serialize_context_t *c,
+			     const hb_array_t<index_map_subset_plan_t> &im_plans)
+  {
+    TRACE_SERIALIZE (this);
+    if (im_plans[index_map_subset_plan_t::ADV_INDEX].is_identity ())
+      advMap = 0;
+    else if (unlikely (!advMap.serialize (c, this).serialize (c, im_plans[index_map_subset_plan_t::ADV_INDEX])))
+      return_trace (false);
+    if (im_plans[index_map_subset_plan_t::LSB_INDEX].is_identity ())
+      lsbMap = 0;
+    else if (unlikely (!lsbMap.serialize (c, this).serialize (c, im_plans[index_map_subset_plan_t::LSB_INDEX])))
+      return_trace (false);
+    if (im_plans[index_map_subset_plan_t::RSB_INDEX].is_identity ())
+      rsbMap = 0;
+    else if (unlikely (!rsbMap.serialize (c, this).serialize (c, im_plans[index_map_subset_plan_t::RSB_INDEX])))
+      return_trace (false);
+
+    return_trace (true);
+  }
+
+  template <typename T>
+  bool _subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    hvarvvar_subset_plan_t	hvar_plan;
+    hb_vector_t<const DeltaSetIndexMap *>
+				index_maps;
+
+    ((T*)this)->listup_index_maps (index_maps);
+    hvar_plan.init (index_maps.as_array (), this+varStore, c->plan);
+
+    T *out = c->serializer->allocate_min<T> ();
+    if (unlikely (!out)) return_trace (false);
+
+    out->version.major = 1;
+    out->version.minor = 0;
+
+    if (!unlikely (out->varStore.serialize (c->serializer, out)
+		     .serialize (c->serializer, hvar_plan.var_store, hvar_plan.inner_maps.as_array ())))
+      return_trace (false);
+
+    return_trace (out->T::serialize_index_maps (c->serializer,
+						hvar_plan.index_map_plans.as_array ()));
+  }
+
+  float get_advance_var (hb_codepoint_t glyph, hb_font_t *font) const
   {
     unsigned int varidx = (this+advMap).map (glyph);
     return (this+varStore).get_delta (varidx, font->coords, font->num_coords);
@@ -148,6 +437,7 @@
 
 struct HVAR : HVARVVAR {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_HVAR;
+  bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<HVAR> (c); }
 };
 struct VVAR : HVARVVAR {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_VVAR;
@@ -159,6 +449,28 @@
 		  vorgMap.sanitize (c, this));
   }
 
+  void listup_index_maps (hb_vector_t<const DeltaSetIndexMap *> &index_maps) const
+  {
+    HVARVVAR::listup_index_maps (index_maps);
+    index_maps.push (&(this+vorgMap));
+  }
+
+  bool serialize_index_maps (hb_serialize_context_t *c,
+			     const hb_array_t<index_map_subset_plan_t> &im_plans)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!HVARVVAR::serialize_index_maps (c, im_plans)))
+      return_trace (false);
+    if (!im_plans[index_map_subset_plan_t::VORG_INDEX].get_map_count ())
+      vorgMap = 0;
+    else if (unlikely (!vorgMap.serialize (c, this).serialize (c, im_plans[index_map_subset_plan_t::VORG_INDEX])))
+      return_trace (false);
+
+    return_trace (true);
+  }
+
+  bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<VVAR> (c); }
+
   protected:
   LOffsetTo<DeltaSetIndexMap>
 		vorgMap;	/* Offset to vertical-origin var-idx mapping. */
diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh
index 3c66119..1df9fb7 100644
--- a/src/hb-subset-cff-common.hh
+++ b/src/hb-subset-cff-common.hh
@@ -677,8 +677,8 @@
       if (unlikely (!interp.interpret (param)))
 	return false;
 
-      /* finalize parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
-      SUBSETTER::finalize_parsed_str (interp.env, param, parsed_charstrings[i]);
+      /* complete parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
+      SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[i]);
     }
 
     if (plan->drop_hints)
diff --git a/src/hb-subset-cff1.cc b/src/hb-subset-cff1.cc
index e9e0757..dda8302 100644
--- a/src/hb-subset-cff1.cc
+++ b/src/hb-subset-cff1.cc
@@ -331,7 +331,7 @@
 struct range_list_t : hb_vector_t<code_pair_t>
 {
   /* replace the first glyph ID in the "glyph" field each range with a nLeft value */
-  bool finalize (unsigned int last_glyph)
+  bool complete (unsigned int last_glyph)
   {
     bool  two_byte = false;
     for (unsigned int i = (*this).length; i > 0; i--)
@@ -402,7 +402,7 @@
   cff1_subr_subsetter_t (const OT::cff1::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_)
     : subr_subsetter_t (acc_, plan_) {}
 
-  static void finalize_parsed_str (cff1_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
+  static void complete_parsed_str (cff1_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
   {
     /* insert width at the beginning of the charstring as necessary */
     if (env.has_width)
@@ -515,7 +515,7 @@
     }
     supp_codes.fini ();
 
-    subset_enc_code_ranges.finalize (glyph);
+    subset_enc_code_ranges.complete (glyph);
 
     assert (subset_enc_num_codes <= 0xFF);
     size0 = Encoding0::min_size + HBUINT8::static_size * subset_enc_num_codes;
@@ -560,7 +560,7 @@
       last_sid = sid;
     }
 
-    bool two_byte = subset_charset_ranges.finalize (glyph);
+    bool two_byte = subset_charset_ranges.complete (glyph);
 
     size0 = Charset0::min_size + HBUINT16::static_size * (plan->num_output_glyphs () - 1);
     if (!two_byte)
diff --git a/src/hb-subset-cff2.cc b/src/hb-subset-cff2.cc
index 7edc3f5..2117fd3 100644
--- a/src/hb-subset-cff2.cc
+++ b/src/hb-subset-cff2.cc
@@ -232,7 +232,7 @@
   cff2_subr_subsetter_t (const OT::cff2::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_)
     : subr_subsetter_t (acc_, plan_) {}
 
-  static void finalize_parsed_str (cff2_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
+  static void complete_parsed_str (cff2_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
   {
     /* vsindex is inserted at the beginning of the charstring as necessary */
     if (env.seen_vsindex ())
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index ec2f889..f812444 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -45,6 +45,8 @@
 #include "hb-ot-name-table.hh"
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
+#include "hb-ot-var-gvar-table.hh"
+#include "hb-ot-var-hvar-table.hh"
 
 
 HB_UNUSED static inline unsigned int
@@ -220,6 +222,15 @@
     case HB_OT_TAG_GPOS:
       result = _subset2<const OT::GPOS> (plan);
       break;
+    case HB_OT_TAG_gvar:
+      result = _subset2<const OT::gvar> (plan);
+      break;
+    case HB_OT_TAG_HVAR:
+      result = _subset2<const OT::HVAR> (plan);
+      break;
+    case HB_OT_TAG_VVAR:
+      result = _subset2<const OT::VVAR> (plan);
+      break;
 #endif
 
     default:
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index 9d4084b..33b5fdf 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -51,6 +51,9 @@
 	test-subset-vmtx \
 	test-subset-cff1 \
 	test-subset-cff2 \
+	test-subset-gvar \
+	test-subset-hvar \
+	test-subset-vvar \
 	test-unicode \
 	test-version \
 	test-subset-nameids \
@@ -67,6 +70,9 @@
 test_subset_vmtx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_cff1_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_cff2_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+test_subset_gvar_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+test_subset_hvar_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+test_subset_vvar_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_nameids_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 
 test_unicode_CPPFLAGS = \
diff --git a/test/api/fonts/AdobeVFPrototype.abc.otf b/test/api/fonts/AdobeVFPrototype.abc.otf
index cc47708..5e6a928 100644
--- a/test/api/fonts/AdobeVFPrototype.abc.otf
+++ b/test/api/fonts/AdobeVFPrototype.abc.otf
Binary files differ
diff --git a/test/api/fonts/AdobeVFPrototype.ac.nohints.otf b/test/api/fonts/AdobeVFPrototype.ac.nohints.otf
index 935bdbf..89e1973 100644
--- a/test/api/fonts/AdobeVFPrototype.ac.nohints.otf
+++ b/test/api/fonts/AdobeVFPrototype.ac.nohints.otf
Binary files differ
diff --git a/test/api/fonts/AdobeVFPrototype.ac.nosubrs.nohints.otf b/test/api/fonts/AdobeVFPrototype.ac.nosubrs.nohints.otf
index 85f6cf6..941760d 100644
--- a/test/api/fonts/AdobeVFPrototype.ac.nosubrs.nohints.otf
+++ b/test/api/fonts/AdobeVFPrototype.ac.nosubrs.nohints.otf
Binary files differ
diff --git a/test/api/fonts/AdobeVFPrototype.ac.nosubrs.otf b/test/api/fonts/AdobeVFPrototype.ac.nosubrs.otf
index ad4d53b..7d2f79a 100644
--- a/test/api/fonts/AdobeVFPrototype.ac.nosubrs.otf
+++ b/test/api/fonts/AdobeVFPrototype.ac.nosubrs.otf
Binary files differ
diff --git a/test/api/fonts/AdobeVFPrototype.ac.otf b/test/api/fonts/AdobeVFPrototype.ac.otf
index beab7d5..193404f 100644
--- a/test/api/fonts/AdobeVFPrototype.ac.otf
+++ b/test/api/fonts/AdobeVFPrototype.ac.otf
Binary files differ
diff --git a/test/api/fonts/AdobeVFPrototype.ac.retaingids.otf b/test/api/fonts/AdobeVFPrototype.ac.retaingids.otf
index 8cb3005..15419b0 100644
--- a/test/api/fonts/AdobeVFPrototype.ac.retaingids.otf
+++ b/test/api/fonts/AdobeVFPrototype.ac.retaingids.otf
Binary files differ
diff --git a/test/api/fonts/SourceHanSans-Regular.41,4C2E.retaingids.otf b/test/api/fonts/SourceHanSans-Regular.41,4C2E.retaingids.otf
index fa2a0e4..1e5cc96 100644
--- a/test/api/fonts/SourceHanSans-Regular.41,4C2E.retaingids.otf
+++ b/test/api/fonts/SourceHanSans-Regular.41,4C2E.retaingids.otf
Binary files differ
diff --git a/test/api/fonts/SourceSansVariable-Roman-modHVAR.abc.ttf b/test/api/fonts/SourceSansVariable-Roman-modHVAR.abc.ttf
new file mode 100644
index 0000000..397e7a5
--- /dev/null
+++ b/test/api/fonts/SourceSansVariable-Roman-modHVAR.abc.ttf
Binary files differ
diff --git a/test/api/fonts/SourceSansVariable-Roman-modHVAR.ac.ttf b/test/api/fonts/SourceSansVariable-Roman-modHVAR.ac.ttf
new file mode 100644
index 0000000..cfdbe1d
--- /dev/null
+++ b/test/api/fonts/SourceSansVariable-Roman-modHVAR.ac.ttf
Binary files differ
diff --git a/test/api/fonts/SourceSansVariable-Roman.abc.ttf b/test/api/fonts/SourceSansVariable-Roman.abc.ttf
new file mode 100644
index 0000000..690d7d5
--- /dev/null
+++ b/test/api/fonts/SourceSansVariable-Roman.abc.ttf
Binary files differ
diff --git a/test/api/fonts/SourceSansVariable-Roman.ac.retaingids.ttf b/test/api/fonts/SourceSansVariable-Roman.ac.retaingids.ttf
new file mode 100644
index 0000000..b2e744d
--- /dev/null
+++ b/test/api/fonts/SourceSansVariable-Roman.ac.retaingids.ttf
Binary files differ
diff --git a/test/api/fonts/SourceSansVariable-Roman.ac.ttf b/test/api/fonts/SourceSansVariable-Roman.ac.ttf
new file mode 100644
index 0000000..2387ea7
--- /dev/null
+++ b/test/api/fonts/SourceSansVariable-Roman.ac.ttf
Binary files differ
diff --git a/test/api/fonts/SourceSerifVariable-Roman-VVAR.ac.retaingids.ttf b/test/api/fonts/SourceSerifVariable-Roman-VVAR.ac.retaingids.ttf
new file mode 100644
index 0000000..734f6e8
--- /dev/null
+++ b/test/api/fonts/SourceSerifVariable-Roman-VVAR.ac.retaingids.ttf
Binary files differ
diff --git a/test/api/fonts/SourceSerifVariable-Roman-VVAR.ac.ttf b/test/api/fonts/SourceSerifVariable-Roman-VVAR.ac.ttf
new file mode 100644
index 0000000..b6b9e97
--- /dev/null
+++ b/test/api/fonts/SourceSerifVariable-Roman-VVAR.ac.ttf
Binary files differ
diff --git a/test/api/test-subset-gvar.c b/test/api/test-subset-gvar.c
new file mode 100644
index 0000000..991be8f
--- /dev/null
+++ b/test/api/test-subset-gvar.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright © 2019 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-test.h"
+#include "hb-subset-test.h"
+
+/* Unit tests for gvar subsetting */
+
+static void
+test_subset_gvar_noop (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file("fonts/SourceSansVariable-Roman.abc.ttf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'b');
+  hb_set_add (codepoints, 'c');
+  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('g','v','a','r'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+}
+
+static void
+test_subset_gvar (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/SourceSansVariable-Roman.abc.ttf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/SourceSansVariable-Roman.ac.ttf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','v','a','r'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+static void
+test_subset_gvar_retaingids (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/SourceSansVariable-Roman.abc.ttf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/SourceSansVariable-Roman.ac.retaingids.ttf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_retain_gids (input, true);
+  face_abc_subset = hb_subset_test_create_subset (face_abc, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','v','a','r'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_subset_gvar_noop);
+  hb_test_add (test_subset_gvar);
+  hb_test_add (test_subset_gvar_retaingids);
+
+  return hb_test_run ();
+}
diff --git a/test/api/test-subset-hvar.c b/test/api/test-subset-hvar.c
new file mode 100644
index 0000000..2a6c2a9
--- /dev/null
+++ b/test/api/test-subset-hvar.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright © 2019 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-test.h"
+#include "hb-subset-test.h"
+
+/* Unit tests for HVAR subsetting */
+
+static void
+test_subset_map_HVAR_noop (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file("fonts/AdobeVFPrototype.abc.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'b');
+  hb_set_add (codepoints, 'c');
+  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('H','V','A','R'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+}
+
+static void
+test_subset_map_HVAR (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/AdobeVFPrototype.abc.otf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/AdobeVFPrototype.ac.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('H','V','A','R'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+static void
+test_subset_map_HVAR_retaingids (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/AdobeVFPrototype.abc.otf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/AdobeVFPrototype.ac.retaingids.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_retain_gids (input, true);
+  face_abc_subset = hb_subset_test_create_subset (face_abc, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('H','V','A','R'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+static void
+test_subset_map_modHVAR (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/SourceSansVariable-Roman-modHVAR.abc.ttf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/SourceSansVariable-Roman-modHVAR.ac.ttf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('H','V','A','R'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+static void
+test_subset_identity_HVAR_noop (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file("fonts/SourceSansVariable-Roman.abc.ttf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'b');
+  hb_set_add (codepoints, 'c');
+  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('H','V','A','R'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+}
+
+static void
+test_subset_identity_HVAR (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/SourceSansVariable-Roman.abc.ttf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/SourceSansVariable-Roman.ac.ttf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('H','V','A','R'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+static void
+test_subset_identity_HVAR_retaingids (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/SourceSansVariable-Roman.abc.ttf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/SourceSansVariable-Roman.ac.retaingids.ttf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_retain_gids (input, true);
+  face_abc_subset = hb_subset_test_create_subset (face_abc, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('H','V','A','R'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_subset_map_HVAR_noop);
+  hb_test_add (test_subset_map_HVAR);
+  hb_test_add (test_subset_map_HVAR_retaingids);
+  hb_test_add (test_subset_map_modHVAR);
+  hb_test_add (test_subset_identity_HVAR_noop);
+  hb_test_add (test_subset_identity_HVAR);
+  hb_test_add (test_subset_identity_HVAR_retaingids);
+
+  return hb_test_run ();
+}
diff --git a/test/api/test-subset-vvar.c b/test/api/test-subset-vvar.c
new file mode 100644
index 0000000..2b829a3
--- /dev/null
+++ b/test/api/test-subset-vvar.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright © 2019 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-test.h"
+#include "hb-subset-test.h"
+
+/* Unit tests for VVAR subsetting */
+
+static void
+test_subset_VVAR_noop (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file("fonts/SourceSerifVariable-Roman-VVAR.abc.ttf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'b');
+  hb_set_add (codepoints, 'c');
+  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('V','V','A','R'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+}
+
+static void
+test_subset_VVAR (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/SourceSerifVariable-Roman-VVAR.abc.ttf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/SourceSerifVariable-Roman-VVAR.ac.ttf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('V','V','A','R'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+static void
+test_subset_VVAR_retaingids (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/SourceSerifVariable-Roman-VVAR.abc.ttf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/SourceSerifVariable-Roman-VVAR.ac.retaingids.ttf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_retain_gids (input, true);
+  face_abc_subset = hb_subset_test_create_subset (face_abc, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('V','V','A','R'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_subset_VVAR_noop);
+  hb_test_add (test_subset_VVAR);
+  hb_test_add (test_subset_VVAR_retaingids);
+
+  return hb_test_run ();
+}
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,62,63.ttf
index efe5bcb..bb28743 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,62,63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,63.ttf
index 8e12241..5b61a31 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61.ttf
index bd802a5..687c82b 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.62.ttf
index 9fbebb5..ff9379c 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.62.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.62.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.63.ttf
index 7391741..7658bc3 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.retain-all-codepoint.ttf
index 5de8d89..1e2d19f 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.retain-all-codepoint.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.retain-all-codepoint.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,62,63.ttf
index 05d83d8..edc9c66 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,62,63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,63.ttf
index f47887e..3137fc4 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61.ttf
index bfa9267..619b427 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.62.ttf
index 8c12158..5d2f4eb 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.62.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.62.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.63.ttf
index 6a47c39..419f9bb 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.retain-all-codepoint.ttf
index e3c0727..9382c52 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.retain-all-codepoint.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.retain-all-codepoint.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,62,63.ttf
index 36a4b9a..53bdbd1 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,62,63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,63.ttf
index 251794c..a0390b1 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61.ttf
index 9e65c83..fd9fc0c 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.62.ttf
index ada1649..467f0fb 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.62.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.62.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.63.ttf
index 6b0dc6c..c265754 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.retain-all-codepoint.ttf
index 6425ecf..c85ca1e 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.retain-all-codepoint.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.retain-all-codepoint.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,62,63.ttf
index 90e49be..ea9bb95 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,62,63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,63.ttf
index 5277d15..fb23713 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61.ttf
index de06660..72e0860 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.62.ttf
index effad7b..15b4d19 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.62.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.62.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.63.ttf
index 21c8205..fdc0413 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.retain-all-codepoint.ttf
index fbb8c33..2f5944e 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.retain-all-codepoint.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.retain-all-codepoint.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,62,63.ttf
index 3c0f4cd..a028adc 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,62,63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,63.ttf
index a5ce9e0..32d959e 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61.ttf
index 1b84335..41b0744 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.62.ttf
index 97eaa26..3352e31 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.62.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.62.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.63.ttf
index f42edb7..afb2037 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.63.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.retain-all-codepoint.ttf
index cc2805a..4b0138f 100644
--- a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.retain-all-codepoint.ttf
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.retain-all-codepoint.ttf
Binary files differ
diff --git a/test/subset/data/expected/full-font/SourceSerifVariable-Roman.default.1FC,21,41,20,62,63.ttf b/test/subset/data/expected/full-font/SourceSerifVariable-Roman.default.1FC,21,41,20,62,63.ttf
new file mode 100644
index 0000000..3424a3d
--- /dev/null
+++ b/test/subset/data/expected/full-font/SourceSerifVariable-Roman.default.1FC,21,41,20,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/full-font/SourceSerifVariable-Roman.default.61,62,63.ttf b/test/subset/data/expected/full-font/SourceSerifVariable-Roman.default.61,62,63.ttf
new file mode 100644
index 0000000..ae4ee43
--- /dev/null
+++ b/test/subset/data/expected/full-font/SourceSerifVariable-Roman.default.61,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/full-font/SourceSerifVariable-Roman.default.D7,D8,D9,DA,DE.ttf b/test/subset/data/expected/full-font/SourceSerifVariable-Roman.default.D7,D8,D9,DA,DE.ttf
new file mode 100644
index 0000000..1a5ba47
--- /dev/null
+++ b/test/subset/data/expected/full-font/SourceSerifVariable-Roman.default.D7,D8,D9,DA,DE.ttf
Binary files differ
diff --git a/test/subset/data/expected/full-font/SourceSerifVariable-Roman.drop-hints.1FC,21,41,20,62,63.ttf b/test/subset/data/expected/full-font/SourceSerifVariable-Roman.drop-hints.1FC,21,41,20,62,63.ttf
new file mode 100644
index 0000000..3424a3d
--- /dev/null
+++ b/test/subset/data/expected/full-font/SourceSerifVariable-Roman.drop-hints.1FC,21,41,20,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/full-font/SourceSerifVariable-Roman.drop-hints.61,62,63.ttf b/test/subset/data/expected/full-font/SourceSerifVariable-Roman.drop-hints.61,62,63.ttf
new file mode 100644
index 0000000..ae4ee43
--- /dev/null
+++ b/test/subset/data/expected/full-font/SourceSerifVariable-Roman.drop-hints.61,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/full-font/SourceSerifVariable-Roman.drop-hints.D7,D8,D9,DA,DE.ttf b/test/subset/data/expected/full-font/SourceSerifVariable-Roman.drop-hints.D7,D8,D9,DA,DE.ttf
new file mode 100644
index 0000000..1a5ba47
--- /dev/null
+++ b/test/subset/data/expected/full-font/SourceSerifVariable-Roman.drop-hints.D7,D8,D9,DA,DE.ttf
Binary files differ
diff --git a/test/subset/data/fonts/SourceSerifVariable-Roman.ttf b/test/subset/data/fonts/SourceSerifVariable-Roman.ttf
new file mode 100644
index 0000000..4a73845
--- /dev/null
+++ b/test/subset/data/fonts/SourceSerifVariable-Roman.ttf
Binary files differ
diff --git a/test/subset/data/tests/full-font.tests b/test/subset/data/tests/full-font.tests
index 225bb48..d9519b6 100644
--- a/test/subset/data/tests/full-font.tests
+++ b/test/subset/data/tests/full-font.tests
@@ -1,5 +1,6 @@
 FONTS:
 Roboto-Regular.ttf
+SourceSerifVariable-Roman.ttf
 
 PROFILES:
 default.txt
diff --git a/test/subset/generate-expected-outputs.py b/test/subset/generate-expected-outputs.py
index 6c65627..c33a49f 100755
--- a/test/subset/generate-expected-outputs.py
+++ b/test/subset/generate-expected-outputs.py
@@ -23,7 +23,7 @@
 		     "--name-languages=*",
 		     "--name-legacy",
                      "--layout-features=*",
-		     "--drop-tables+=DSIG,GPOS,GSUB,GDEF,gvar,avar,MVAR,HVAR",
+		     "--drop-tables+=DSIG,GPOS,GSUB,GDEF",
 		     "--unicodes=%s" % unicodes,
 		     "--output-file=%s" % output_path])
 	args.extend(profile_flags)
diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py
index 5d221e6..4bf5714 100755
--- a/test/subset/run-tests.py
+++ b/test/subset/run-tests.py
@@ -67,7 +67,7 @@
 		    "--font-file=" + test.font_path,
 		    "--output-file=" + out_file,
 		    "--unicodes=%s" % test.unicodes (),
-		    "--drop-tables+=DSIG,GPOS,GSUB,GDEF,gvar,avar,MVAR,HVAR"]
+		    "--drop-tables+=DSIG,GPOS,GSUB,GDEF"]
 	cli_args.extend (test.get_profile_flags ())
 	print (' '.join (cli_args))
 	_, return_code = cmd (cli_args)