[>64k:layout] Split GSUBGPOSVersion1 into own struct
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
index 40071fd..c1ed59c 100644
--- a/src/hb-ot-layout-gsubgpos.hh
+++ b/src/hb-ot-layout-gsubgpos.hh
@@ -3983,104 +3983,51 @@
 #endif
 };
 
-struct GSUBGPOS
+struct GSUBGPOSVersion1
 {
-  bool has_data () const { return version.to_int (); }
-  unsigned int get_script_count () const
-  { return (this+scriptList).len; }
-  const Tag& get_script_tag (unsigned int i) const
-  { return (this+scriptList).get_tag (i); }
-  unsigned int get_script_tags (unsigned int start_offset,
-				unsigned int *script_count /* IN/OUT */,
-				hb_tag_t     *script_tags /* OUT */) const
-  { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
-  const Script& get_script (unsigned int i) const
-  { return (this+scriptList)[i]; }
-  bool find_script_index (hb_tag_t tag, unsigned int *index) const
-  { return (this+scriptList).find_index (tag, index); }
+  friend struct GSUBGPOS;
 
-  unsigned int get_feature_count () const
-  { return (this+featureList).len; }
-  hb_tag_t get_feature_tag (unsigned int i) const
-  { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
-  unsigned int get_feature_tags (unsigned int start_offset,
-				 unsigned int *feature_count /* IN/OUT */,
-				 hb_tag_t     *feature_tags /* OUT */) const
-  { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
-  const Feature& get_feature (unsigned int i) const
-  { return (this+featureList)[i]; }
-  bool find_feature_index (hb_tag_t tag, unsigned int *index) const
-  { return (this+featureList).find_index (tag, index); }
+  protected:
+  FixedVersion<>version;	/* Version of the GSUB/GPOS table--initially set
+				 * to 0x00010000u */
+  Offset16To<ScriptList>
+		scriptList;	/* ScriptList table */
+  Offset16To<FeatureList>
+		featureList;	/* FeatureList table */
+  Offset16To<LookupList>
+		lookupList;	/* LookupList table */
+  Offset32To<FeatureVariations>
+		featureVars;	/* Offset to Feature Variations
+				   table--from beginning of table
+				 * (may be NULL).  Introduced
+				 * in version 0x00010001. */
+  public:
+  DEFINE_SIZE_MIN (10);
 
-  unsigned int get_lookup_count () const
-  { return (this+lookupList).len; }
-  const Lookup& get_lookup (unsigned int i) const
-  { return (this+lookupList)[i]; }
-
-  bool find_variations_index (const int *coords, unsigned int num_coords,
-			      unsigned int *index) const
+  unsigned int get_size () const
   {
-#ifdef HB_NO_VAR
-    *index = FeatureVariations::NOT_FOUND_INDEX;
-    return false;
-#endif
-    return (version.to_int () >= 0x00010001u ? this+featureVars : Null (FeatureVariations))
-	    .find_index (coords, num_coords, index);
-  }
-  const Feature& get_feature_variation (unsigned int feature_index,
-					unsigned int variations_index) const
-  {
-#ifndef HB_NO_VAR
-    if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
-	version.to_int () >= 0x00010001u)
-    {
-      const Feature *feature = (this+featureVars).find_substitute (variations_index,
-								   feature_index);
-      if (feature)
-	return *feature;
-    }
-#endif
-    return get_feature (feature_index);
-  }
-
-  void feature_variation_collect_lookups (const hb_set_t *feature_indexes,
-					  hb_set_t       *lookup_indexes /* OUT */) const
-  {
-#ifndef HB_NO_VAR
-    if (version.to_int () >= 0x00010001u)
-      (this+featureVars).collect_lookups (feature_indexes, lookup_indexes);
-#endif
+    return min_size +
+	   (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
   }
 
   template <typename TLookup>
-  void closure_lookups (hb_face_t      *face,
-			const hb_set_t *glyphs,
-			hb_set_t       *lookup_indexes /* IN/OUT */) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
-    hb_set_t visited_lookups, inactive_lookups;
-    OT::hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups);
+    TRACE_SANITIZE (this);
+    typedef List16OfOffset16To<TLookup> TLookupList;
+    if (unlikely (!(version.sanitize (c) &&
+		    likely (version.major == 1) &&
+		    scriptList.sanitize (c, this) &&
+		    featureList.sanitize (c, this) &&
+		    reinterpret_cast<const Offset16To<TLookupList> &> (lookupList).sanitize (c, this))))
+      return_trace (false);
 
-    c.set_recurse_func (TLookup::template dispatch_recurse_func<hb_closure_lookups_context_t>);
+#ifndef HB_NO_VAR
+    if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
+      return_trace (false);
+#endif
 
-    for (unsigned lookup_index : + hb_iter (lookup_indexes))
-      reinterpret_cast<const TLookup &> (get_lookup (lookup_index)).closure_lookups (&c, lookup_index);
-
-    hb_set_union (lookup_indexes, &visited_lookups);
-    hb_set_subtract (lookup_indexes, &inactive_lookups);
-  }
-
-  void prune_langsys (const hb_map_t *duplicate_feature_map,
-                      hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map,
-                      hb_set_t       *new_feature_indexes /* OUT */) const
-  {
-    hb_prune_langsys_context_t c (this, script_langsys_map, duplicate_feature_map, new_feature_indexes);
-
-    unsigned count = get_script_count ();
-    for (unsigned script_index = 0; script_index < count; script_index++)
-    {
-      const Script& s = get_script (script_index);
-      s.prune_langsys (&c, script_index);
-    }
+    return_trace (true);
   }
 
   template <typename TLookup>
@@ -4123,6 +4070,165 @@
     return_trace (true);
   }
 
+};
+
+struct GSUBGPOS
+{
+  unsigned int get_size () const
+  {
+    switch (u.version.major) {
+    case 1: return u.version1.get_size ();
+    default: return u.version.static_size;
+    }
+  }
+
+  template <typename TLookup>
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!u.version.sanitize (c))) return_trace (false);
+    switch (u.version.major) {
+    case 1: return_trace (u.version1.sanitize<TLookup> (c));
+    default: return_trace (true);
+    }
+  }
+
+  template <typename TLookup>
+  bool subset (hb_subset_layout_context_t *c) const
+  {
+    switch (u.version.major) {
+    case 1: return u.version1.subset<TLookup> (c);
+    default: return false;
+    }
+  }
+
+  const ScriptList &get_script_list () const
+  {
+    switch (u.version.major) {
+    case 1: return this+u.version1.scriptList;
+    default: return Null (ScriptList);
+    }
+  }
+  const FeatureList &get_feature_list () const
+  {
+    switch (u.version.major) {
+    case 1: return this+u.version1.featureList;
+    default: return Null (FeatureList);
+    }
+  }
+  unsigned int get_lookup_count () const
+  {
+    switch (u.version.major) {
+    case 1: return (this+u.version1.lookupList).len;
+    default: return 0;
+    }
+  }
+  const Lookup& get_lookup (unsigned int i) const
+  {
+    switch (u.version.major) {
+    case 1: return (this+u.version1.lookupList)[i];
+    default: return Null (Lookup);
+    }
+  }
+  const FeatureVariations &get_feature_variations () const
+  {
+    switch (u.version.major) {
+    case 1: return (u.version.to_int () >= 0x00010001u ? this+u.version1.featureVars : Null (FeatureVariations));
+    default: return Null (FeatureVariations);
+    }
+  }
+
+  bool has_data () const { return u.version.to_int (); }
+  unsigned int get_script_count () const
+  { return get_script_list ().len; }
+  const Tag& get_script_tag (unsigned int i) const
+  { return get_script_list ().get_tag (i); }
+  unsigned int get_script_tags (unsigned int start_offset,
+				unsigned int *script_count /* IN/OUT */,
+				hb_tag_t     *script_tags /* OUT */) const
+  { return get_script_list ().get_tags (start_offset, script_count, script_tags); }
+  const Script& get_script (unsigned int i) const
+  { return get_script_list ()[i]; }
+  bool find_script_index (hb_tag_t tag, unsigned int *index) const
+  { return get_script_list ().find_index (tag, index); }
+
+  unsigned int get_feature_count () const
+  { return get_feature_list ().len; }
+  hb_tag_t get_feature_tag (unsigned int i) const
+  { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : get_feature_list ().get_tag (i); }
+  unsigned int get_feature_tags (unsigned int start_offset,
+				 unsigned int *feature_count /* IN/OUT */,
+				 hb_tag_t     *feature_tags /* OUT */) const
+  { return get_feature_list ().get_tags (start_offset, feature_count, feature_tags); }
+  const Feature& get_feature (unsigned int i) const
+  { return get_feature_list ()[i]; }
+  bool find_feature_index (hb_tag_t tag, unsigned int *index) const
+  { return get_feature_list ().find_index (tag, index); }
+
+  bool find_variations_index (const int *coords, unsigned int num_coords,
+			      unsigned int *index) const
+  {
+#ifdef HB_NO_VAR
+    *index = FeatureVariations::NOT_FOUND_INDEX;
+    return false;
+#endif
+    return get_feature_variations ().find_index (coords, num_coords, index);
+  }
+  const Feature& get_feature_variation (unsigned int feature_index,
+					unsigned int variations_index) const
+  {
+#ifndef HB_NO_VAR
+    if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
+	u.version.to_int () >= 0x00010001u)
+    {
+      const Feature *feature = get_feature_variations ().find_substitute (variations_index,
+									  feature_index);
+      if (feature)
+	return *feature;
+    }
+#endif
+    return get_feature (feature_index);
+  }
+
+  void feature_variation_collect_lookups (const hb_set_t *feature_indexes,
+					  hb_set_t       *lookup_indexes /* OUT */) const
+  {
+#ifndef HB_NO_VAR
+    get_feature_variations ().collect_lookups (feature_indexes, lookup_indexes);
+#endif
+  }
+
+  template <typename TLookup>
+  void closure_lookups (hb_face_t      *face,
+			const hb_set_t *glyphs,
+			hb_set_t       *lookup_indexes /* IN/OUT */) const
+  {
+    hb_set_t visited_lookups, inactive_lookups;
+    OT::hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups);
+
+    c.set_recurse_func (TLookup::template dispatch_recurse_func<hb_closure_lookups_context_t>);
+
+    for (unsigned lookup_index : + hb_iter (lookup_indexes))
+      reinterpret_cast<const TLookup &> (get_lookup (lookup_index)).closure_lookups (&c, lookup_index);
+
+    hb_set_union (lookup_indexes, &visited_lookups);
+    hb_set_subtract (lookup_indexes, &inactive_lookups);
+  }
+
+  void prune_langsys (const hb_map_t *duplicate_feature_map,
+                      hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map,
+                      hb_set_t       *new_feature_indexes /* OUT */) const
+  {
+    hb_prune_langsys_context_t c (this, script_langsys_map, duplicate_feature_map, new_feature_indexes);
+
+    unsigned count = get_script_count ();
+    for (unsigned script_index = 0; script_index < count; script_index++)
+    {
+      const Script& s = get_script (script_index);
+      s.prune_langsys (&c, script_index);
+    }
+  }
+
   void prune_features (const hb_map_t *lookup_indices, /* IN */
 		       hb_set_t       *feature_indices /* IN/OUT */) const
   {
@@ -4131,8 +4237,7 @@
     // if the FeatureVariation's table and the alternate version(s) intersect the
     // set of lookup indices.
     hb_set_t alternate_feature_indices;
-    if (version.to_int () >= 0x00010001u)
-      (this+featureVars).closure_features (lookup_indices, &alternate_feature_indices);
+    get_feature_variations ().closure_features (lookup_indices, &alternate_feature_indices);
     if (unlikely (alternate_feature_indices.in_error()))
     {
       feature_indices->err ();
@@ -4165,32 +4270,6 @@
     }
   }
 
-  unsigned int get_size () const
-  {
-    return min_size +
-	   (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
-  }
-
-  template <typename TLookup>
-  bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    typedef List16OfOffset16To<TLookup> TLookupList;
-    if (unlikely (!(version.sanitize (c) &&
-		    likely (version.major == 1) &&
-		    scriptList.sanitize (c, this) &&
-		    featureList.sanitize (c, this) &&
-		    reinterpret_cast<const Offset16To<TLookupList> &> (lookupList).sanitize (c, this))))
-      return_trace (false);
-
-#ifndef HB_NO_VAR
-    if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
-      return_trace (false);
-#endif
-
-    return_trace (true);
-  }
-
   template <typename T>
   struct accelerator_t
   {
@@ -4230,21 +4309,12 @@
   };
 
   protected:
-  FixedVersion<>version;	/* Version of the GSUB/GPOS table--initially set
-				 * to 0x00010000u */
-  Offset16To<ScriptList>
-		scriptList;	/* ScriptList table */
-  Offset16To<FeatureList>
-		featureList;	/* FeatureList table */
-  Offset16To<LookupList>
-		lookupList;	/* LookupList table */
-  Offset32To<FeatureVariations>
-		featureVars;	/* Offset to Feature Variations
-				   table--from beginning of table
-				 * (may be NULL).  Introduced
-				 * in version 0x00010001. */
+  union {
+  FixedVersion<>	version;	/* Version identifier */
+  GSUBGPOSVersion1	version1;
+  } u;
   public:
-  DEFINE_SIZE_MIN (10);
+  DEFINE_SIZE_MIN (4);
 };