Merge branch 'master' into cff-subset
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 320813a..e6a5a1d 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -22,28 +22,28 @@
       - run: make -j4
       - run: make check || .ci/fail.sh
 
-  # macos-llvm-gcc-4.2:
-  #   macos:
-  #     xcode: "8.3.3"
-  #   steps:
-  #     - checkout
-  #     - run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget pkg-config libtool ragel freetype glib cairo
-  #     - run: wget https://packages.macports.org/llvm-gcc42/llvm-gcc42-2336.11_3+universal.darwin_15.i386-x86_64.tbz2 && tar zxvf llvm-gcc42-2336.11_3+universal.darwin_15.i386-x86_64.tbz2
-  #     - run: CC=$PWD/opt/local/bin/llvm-gcc-4.2 CXX=$PWD/opt/local/bin/llvm-g++-4.2 ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo
-  #     # Ignoring assembler complains, https://stackoverflow.com/a/39867021
-  #     - run: make 2>&1 | grep -v -e '^/var/folders/*' -e '^[[:space:]]*\.section' -e '^[[:space:]]*\^[[:space:]]*~*'
-  #     - run: make check || .ci/fail.sh
+  macos-llvm-gcc-4.2:
+    macos:
+      xcode: "8.3.3"
+    steps:
+      - checkout
+      - run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget pkg-config libtool ragel freetype glib cairo
+      - run: wget https://packages.macports.org/llvm-gcc42/llvm-gcc42-2336.11_3+universal.darwin_15.i386-x86_64.tbz2 && tar zxvf llvm-gcc42-2336.11_3+universal.darwin_15.i386-x86_64.tbz2
+      - run: CC=$PWD/opt/local/bin/llvm-gcc-4.2 CXX=$PWD/opt/local/bin/llvm-g++-4.2 ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo
+      # Ignoring assembler complains, https://stackoverflow.com/a/39867021
+      - run: make 2>&1 | grep -v -e '^/var/folders/*' -e '^[[:space:]]*\.section' -e '^[[:space:]]*\^[[:space:]]*~*'
+      - run: make check || .ci/fail.sh
 
-  # macos-notest-apple-gcc-i686-4.2:
-  #   macos:
-  #     xcode: "8.3.3"
-  #   steps:
-  #     - checkout
-  #     - run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget pkg-config libtool ragel
-  #     - run: wget https://packages.macports.org/apple-gcc42/apple-gcc42-5666.3_15+universal.darwin_15.i386-x86_64.tbz2 && tar zxvf apple-gcc42-5666.3_15+universal.darwin_15.i386-x86_64.tbz2
-  #     - run: CPP=$PWD/opt/local/bin/i686-apple-darwin15-cpp-apple-4.2.1 CC=$PWD/opt/local/bin/i686-apple-darwin15-gcc-apple-4.2.1 CXX=$PWD/opt/local/bin/i686-apple-darwin15-g++-apple-4.2.1 ./autogen.sh
-  #     # Ignoring assembler complains, https://stackoverflow.com/a/39867021
-  #     - run: make 2>&1 | grep -v -e '^/var/folders/*' -e '^[[:space:]]*\.section' -e '^[[:space:]]*\^[[:space:]]*~*'
+  macos-notest-apple-gcc-i686-4.2:
+    macos:
+      xcode: "8.3.3"
+    steps:
+      - checkout
+      - run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget pkg-config libtool ragel
+      - run: wget https://packages.macports.org/apple-gcc42/apple-gcc42-5666.3_15+universal.darwin_15.i386-x86_64.tbz2 && tar zxvf apple-gcc42-5666.3_15+universal.darwin_15.i386-x86_64.tbz2
+      - run: CPP=$PWD/opt/local/bin/i686-apple-darwin15-cpp-apple-4.2.1 CC=$PWD/opt/local/bin/i686-apple-darwin15-gcc-apple-4.2.1 CXX=$PWD/opt/local/bin/i686-apple-darwin15-g++-apple-4.2.1 ./autogen.sh
+      # Ignoring assembler complains, https://stackoverflow.com/a/39867021
+      - run: make 2>&1 | grep -v -e '^/var/folders/*' -e '^[[:space:]]*\.section' -e '^[[:space:]]*\^[[:space:]]*~*'
 
   macos-notest-ios:
     macos:
@@ -321,8 +321,8 @@
       # macOS
       - macos-10.12.6-aat-fonts
       - macos-10.13.6-aat-fonts
-      #- macos-llvm-gcc-4.2
-      #- macos-notest-apple-gcc-i686-4.2
+      - macos-llvm-gcc-4.2
+      - macos-notest-apple-gcc-i686-4.2
       - macos-notest-ios
 
       # both autotools and cmake
diff --git a/NEWS b/NEWS
index 9bfe99a..ff4f6e2 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,38 @@
+Overview of changes leading to 2.2.0
+Thursday, November 29, 2018
+====================================
+- Misc shaping bug fixes.
+- Add font variations named-instance API.
+- Deprecate font variations axis enumeration API and add replacement.
+- AAT shaping improvements:
+  o Fixed 'kern' table Format 2 implementation.
+  o Implement 'feat' table API for feature detection.
+  o Blacklist 'GSUB' table of fonts from 'MUTF' foundry that also have 'morx'.
+
+New API:
++hb_aat_layout_feature_type_t
++hb_aat_layout_feature_selector_t
++hb_aat_layout_get_feature_types()
++hb_aat_layout_feature_type_get_name_id
++hb_aat_layout_feature_selector_info_t
++HB_AAT_LAYOUT_NO_SELECTOR_INDEX
++hb_aat_layout_feature_type_get_selector_infos()
++hb_ot_var_axis_flags_t
++hb_ot_var_axis_info_t
++hb_ot_var_get_axis_infos()
++hb_ot_var_find_axis_info()
++hb_ot_var_get_named_instance_count()
++hb_ot_var_named_instance_get_subfamily_name_id()
++hb_ot_var_named_instance_get_postscript_name_id()
++hb_ot_var_named_instance_get_design_coords()
+
+Deprecated API:
++HB_OT_VAR_NO_AXIS_INDEX
++hb_ot_var_axis_t
++hb_ot_var_get_axes()
++hb_ot_var_find_axis()
+
+
 Overview of changes leading to 2.1.3
 Friday, November 16, 2018
 ====================================
diff --git a/configure.ac b/configure.ac
index e9db42a..0649464 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [2.1.3],
+        [2.2.0],
         [https://github.com/harfbuzz/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
diff --git a/src/Makefile.sources b/src/Makefile.sources
index b1a3d0a..40f1d7a 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -196,6 +196,7 @@
 	hb-aat-layout.h \
 	hb-ot.h \
 	hb-ot-color.h \
+	hb-ot-deprecated.h \
 	hb-ot-font.h \
 	hb-ot-layout.h \
 	hb-ot-math.h \
diff --git a/src/hb-aat-layout-ankr-table.hh b/src/hb-aat-layout-ankr-table.hh
index b793245..763bbed 100644
--- a/src/hb-aat-layout-ankr-table.hh
+++ b/src/hb-aat-layout-ankr-table.hh
@@ -58,7 +58,7 @@
 
 struct ankr
 {
-  static const hb_tag_t tableTag = HB_AAT_TAG_ankr;
+  enum { tableTag = HB_AAT_TAG_ankr };
 
   inline const Anchor &get_anchor (hb_codepoint_t glyph_id,
 				   unsigned int i,
diff --git a/src/hb-aat-layout-bsln-table.hh b/src/hb-aat-layout-bsln-table.hh
index b864086..d2ea71d 100644
--- a/src/hb-aat-layout-bsln-table.hh
+++ b/src/hb-aat-layout-bsln-table.hh
@@ -116,7 +116,7 @@
 
 struct bsln
 {
-  static const hb_tag_t tableTag = HB_AAT_TAG_bsln;
+  enum { tableTag = HB_AAT_TAG_bsln };
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh
index c0b0e37..588dbdf 100644
--- a/src/hb-aat-layout-common.hh
+++ b/src/hb-aat-layout-common.hh
@@ -675,7 +675,7 @@
 
 struct ObsoleteTypes
 {
-  static const bool extended = false;
+  enum { extended = false };
   typedef HBUINT16 HBUINT;
   typedef HBUINT8 HBUSHORT;
   typedef ClassTable<HBUINT8> ClassTypeNarrow;
@@ -705,7 +705,7 @@
 };
 struct ExtendedTypes
 {
-  static const bool extended = true;
+  enum { extended = true };
   typedef HBUINT32 HBUINT;
   typedef HBUINT16 HBUSHORT;
   typedef Lookup<HBUINT16> ClassTypeNarrow;
diff --git a/src/hb-aat-layout-feat-table.hh b/src/hb-aat-layout-feat-table.hh
index 4e63ec8..1565d43 100644
--- a/src/hb-aat-layout-feat-table.hh
+++ b/src/hb-aat-layout-feat-table.hh
@@ -155,7 +155,7 @@
 
 struct feat
 {
-  static const hb_tag_t tableTag = HB_AAT_TAG_feat;
+  enum { tableTag = HB_AAT_TAG_feat };
 
   inline bool has_data (void) const { return version.to_int (); }
 
diff --git a/src/hb-aat-layout-just-table.hh b/src/hb-aat-layout-just-table.hh
index 92ca660..295205f 100644
--- a/src/hb-aat-layout-just-table.hh
+++ b/src/hb-aat-layout-just-table.hh
@@ -382,7 +382,7 @@
 
 struct just
 {
-  static const hb_tag_t tableTag = HB_AAT_TAG_just;
+  enum { tableTag = HB_AAT_TAG_just };
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh
index 7caf45d..b25feea 100644
--- a/src/hb-aat-layout-kerx-table.hh
+++ b/src/hb-aat-layout-kerx-table.hh
@@ -211,7 +211,7 @@
 
   struct driver_context_t
   {
-    static const bool in_place = true;
+    enum { in_place = true };
     enum
     {
       DontAdvance	= Format1EntryT::DontAdvance,
@@ -472,7 +472,7 @@
 
   struct driver_context_t
   {
-    static const bool in_place = true;
+    enum { in_place = true };
     enum Flags
     {
       Mark		= 0x8000,	/* If set, remember this glyph as the marked glyph. */
@@ -947,7 +947,7 @@
   {
     TRACE_SANITIZE (this);
     if (unlikely (!thiz()->version.sanitize (c) ||
-		  thiz()->version < T::minVersion ||
+		  (unsigned) thiz()->version < (unsigned) T::minVersion ||
 		  !thiz()->tableCount.sanitize (c)))
       return_trace (false);
 
@@ -982,8 +982,8 @@
 {
   friend struct KerxTable<kerx>;
 
-  static const hb_tag_t tableTag = HB_AAT_TAG_kerx;
-  static const uint16_t minVersion = 2;
+  enum { tableTag = HB_AAT_TAG_kerx };
+  enum { minVersion = 2u };
 
   typedef KerxSubTableHeader SubTableHeader;
   typedef SubTableHeader::Types Types;
diff --git a/src/hb-aat-layout-lcar-table.hh b/src/hb-aat-layout-lcar-table.hh
index 40d34f5..9bfb684 100644
--- a/src/hb-aat-layout-lcar-table.hh
+++ b/src/hb-aat-layout-lcar-table.hh
@@ -40,7 +40,7 @@
 
 struct lcar
 {
-  static const hb_tag_t tableTag = HB_AAT_TAG_lcar;
+  enum { tableTag = HB_AAT_TAG_lcar };
 
   inline unsigned int get_lig_carets (hb_font_t      *font,
 				      hb_direction_t  direction,
diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index 171ee4a..78a7b7d 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -54,7 +54,7 @@
 
   struct driver_context_t
   {
-    static const bool in_place = true;
+    enum { in_place = true };
     enum Flags
     {
       MarkFirst		= 0x8000,	/* If set, make the current glyph the first
@@ -204,7 +204,7 @@
 
   struct driver_context_t
   {
-    static const bool in_place = true;
+    enum { in_place = true };
     enum Flags
     {
       SetMark		= 0x8000,	/* If set, make the current glyph the marked glyph. */
@@ -249,7 +249,7 @@
       {
 	if (entry->data.markIndex != 0xFFFF)
 	{
-	  const Lookup<GlyphID> &lookup = subs[entry->data.markIndex];
+	  const Lookup<GlyphID> &lookup = subs[(unsigned) entry->data.markIndex];
 	  replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs);
 	}
       }
@@ -274,7 +274,7 @@
       {
 	if (entry->data.currentIndex != 0xFFFF)
 	{
-	  const Lookup<GlyphID> &lookup = subs[entry->data.currentIndex];
+	  const Lookup<GlyphID> &lookup = subs[(unsigned) entry->data.currentIndex];
 	  replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs);
 	}
       }
@@ -424,7 +424,7 @@
 
   struct driver_context_t
   {
-    static const bool in_place = false;
+    enum { in_place = false };
     enum
     {
       DontAdvance	= LigatureEntryT::DontAdvance,
@@ -660,7 +660,7 @@
 
   struct driver_context_t
   {
-    static const bool in_place = false;
+    enum { in_place = false };
     enum Flags
     {
       SetMark		= 0x8000,	/* If set, mark the current glyph. */
@@ -1096,7 +1096,7 @@
 template <typename Types>
 struct mortmorx
 {
-  static const hb_tag_t tableTag = HB_AAT_TAG_morx;
+  enum { tableTag = HB_AAT_TAG_morx };
 
   inline bool has_data (void) const { return version != 0; }
 
@@ -1158,11 +1158,11 @@
 
 struct morx : mortmorx<ExtendedTypes>
 {
-  static const hb_tag_t tableTag	= HB_AAT_TAG_morx;
+  enum { tableTag = HB_AAT_TAG_morx };
 };
 struct mort : mortmorx<ObsoleteTypes>
 {
-  static const hb_tag_t tableTag	= HB_AAT_TAG_mort;
+  enum { tableTag = HB_AAT_TAG_mort };
 };
 
 
diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh
index 5474d1d..1658e0f 100644
--- a/src/hb-aat-layout-trak-table.hh
+++ b/src/hb-aat-layout-trak-table.hh
@@ -166,7 +166,7 @@
 
 struct trak
 {
-  static const hb_tag_t tableTag = HB_AAT_TAG_trak;
+  enum { tableTag = HB_AAT_TAG_trak };
 
   inline bool has_data (void) const { return version.to_int (); }
 
diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc
index 727da42..fae6780 100644
--- a/src/hb-aat-layout.cc
+++ b/src/hb-aat-layout.cc
@@ -318,7 +318,7 @@
  *
  * Return value: Number of all available feature types.
  *
- * Since: REPLACEME
+ * Since: 2.2.0
  */
 unsigned int
 hb_aat_layout_get_feature_types (hb_face_t                    *face,
@@ -336,7 +336,7 @@
  *
  * Return value: Name ID index
  *
- * Since: REPLACEME
+ * Since: 2.2.0
  */
 hb_ot_name_id_t
 hb_aat_layout_feature_type_get_name_id (hb_face_t                    *face,
@@ -358,7 +358,7 @@
  *
  * Return value: Number of all available feature selectors.
  *
- * Since: REPLACEME
+ * Since: 2.2.0
  */
 unsigned int
 hb_aat_layout_feature_type_get_selector_infos (hb_face_t                             *face,
diff --git a/src/hb-aat-layout.h b/src/hb-aat-layout.h
index 5912e01..696e903 100644
--- a/src/hb-aat-layout.h
+++ b/src/hb-aat-layout.h
@@ -39,7 +39,7 @@
  * hb_aat_layout_feature_type_t:
  *
  *
- * Since: REPLACEME
+ * Since: 2.2.0
  */
 typedef enum
 {
@@ -92,7 +92,7 @@
  * hb_aat_layout_feature_selector_t:
  *
  *
- * Since: REPLACEME
+ * Since: 2.2.0
  */
 typedef enum
 {
diff --git a/src/hb-aat-ltag-table.hh b/src/hb-aat-ltag-table.hh
index 8a42b35..c7c4b46 100644
--- a/src/hb-aat-ltag-table.hh
+++ b/src/hb-aat-ltag-table.hh
@@ -60,7 +60,7 @@
 
 struct ltag
 {
-  static const hb_tag_t tableTag = HB_AAT_TAG_ltag;
+  enum { tableTag = HB_AAT_TAG_ltag };
 
   inline hb_language_t get_language (unsigned int i) const
   {
diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc
index 918f649..15b8c62 100644
--- a/src/hb-coretext.cc
+++ b/src/hb-coretext.cc
@@ -598,7 +598,7 @@
       } else {
         active_feature_t *feature = active_features.find (&event->feature);
 	if (feature)
-	  active_features.remove (feature - active_features);
+	  active_features.remove (feature - active_features.arrayZ ());
       }
     }
   }
diff --git a/src/hb-deprecated.h b/src/hb-deprecated.h
index a74431f..4a5e702 100644
--- a/src/hb-deprecated.h
+++ b/src/hb-deprecated.h
@@ -52,6 +52,7 @@
 
 #ifndef HB_DISABLE_DEPRECATED
 
+
 #define HB_SCRIPT_CANADIAN_ABORIGINAL		HB_SCRIPT_CANADIAN_SYLLABICS
 
 #define HB_BUFFER_FLAGS_DEFAULT			HB_BUFFER_FLAG_DEFAULT
@@ -217,66 +218,6 @@
 					 hb_direction_t direction,
 					 hb_position_t *x, hb_position_t *y);
 
-/* Like hb_ot_layout_table_find_script, but takes zero-terminated array of scripts to test */
-HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_table_select_script) hb_bool_t
-hb_ot_layout_table_choose_script (hb_face_t      *face,
-				  hb_tag_t        table_tag,
-				  const hb_tag_t *script_tags,
-				  unsigned int   *script_index,
-				  hb_tag_t       *chosen_script);
-
-HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_script_select_language) hb_bool_t
-hb_ot_layout_script_find_language (hb_face_t    *face,
-				   hb_tag_t      table_tag,
-				   unsigned int  script_index,
-				   hb_tag_t      language_tag,
-				   unsigned int *language_index);
-
-HB_EXTERN HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language) void
-hb_ot_tags_from_script (hb_script_t  script,
-			hb_tag_t    *script_tag_1,
-			hb_tag_t    *script_tag_2);
-
-HB_EXTERN HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language) hb_tag_t
-hb_ot_tag_from_language (hb_language_t language);
-
-
-typedef unsigned int hb_ot_name_id_t; /* Since is in hb-ot.h */
-
-/**
- * HB_OT_VAR_NO_AXIS_INDEX:
- *
- * Since: 1.4.2
- * Deprecated: REPLACEME
- */
-#define HB_OT_VAR_NO_AXIS_INDEX		0xFFFFFFFFu
-
-/**
- * hb_ot_var_axis_t:
- *
- * Since: 1.4.2
- * Deprecated: REPLACEME
- */
-typedef struct hb_ot_var_axis_t
-{
-  hb_tag_t tag;
-  hb_ot_name_id_t name_id;
-  float min_value;
-  float default_value;
-  float max_value;
-} hb_ot_var_axis_t;
-
-HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_get_axis_infos) unsigned int
-hb_ot_var_get_axes (hb_face_t        *face,
-		    unsigned int      start_offset,
-		    unsigned int     *axes_count /* IN/OUT */,
-		    hb_ot_var_axis_t *axes_array /* OUT */);
-
-HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_find_axis_info) hb_bool_t
-hb_ot_var_find_axis (hb_face_t        *face,
-		     hb_tag_t          axis_tag,
-		     unsigned int     *axis_index,
-		     hb_ot_var_axis_t *axis_info);
 
 #endif
 
diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh
index 5773596..4a8144b 100644
--- a/src/hb-dsalgs.hh
+++ b/src/hb-dsalgs.hh
@@ -735,26 +735,26 @@
 
 struct HbOpOr
 {
-  static const bool passthru_left = true;
-  static const bool passthru_right = true;
+  enum { passthru_left = true };
+  enum { passthru_right = true };
   template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
 };
 struct HbOpAnd
 {
-  static const bool passthru_left = false;
-  static const bool passthru_right = false;
+  enum { passthru_left = false };
+  enum { passthru_right = false };
   template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
 };
 struct HbOpMinus
 {
-  static const bool passthru_left = true;
-  static const bool passthru_right = false;
+  enum { passthru_left = true };
+  enum { passthru_right = false };
   template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
 };
 struct HbOpXor
 {
-  static const bool passthru_left = true;
-  static const bool passthru_right = true;
+  enum { passthru_left = true };
+  enum { passthru_right = true };
   template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
 };
 
diff --git a/src/hb-face.cc b/src/hb-face.cc
index 5b33784..a1ae1d7 100644
--- a/src/hb-face.cc
+++ b/src/hb-face.cc
@@ -647,8 +647,8 @@
   bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
   hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
 
-  Supplier<hb_tag_t>    tags_supplier  (&data->tables[0].tag, table_count, sizeof (data->tables[0]));
-  Supplier<hb_blob_t *> blobs_supplier (&data->tables[0].blob, table_count, sizeof (data->tables[0]));
+  Supplier<hb_tag_t>    tags_supplier  (&data->tables[0u].tag, table_count, data->tables.item_size);
+  Supplier<hb_blob_t *> blobs_supplier (&data->tables[0u].blob, table_count, data->tables.item_size);
   bool ret = f->serialize_single (&c,
 				  sfnt_tag,
 				  tags_supplier,
diff --git a/src/hb-icu.cc b/src/hb-icu.cc
index 4e51eb0..287f863 100644
--- a/src/hb-icu.cc
+++ b/src/hb-icu.cc
@@ -65,7 +65,8 @@
   if (unlikely (script == HB_SCRIPT_INVALID))
     return USCRIPT_INVALID_CODE;
 
-  for (unsigned int i = 0; i < USCRIPT_CODE_LIMIT; i++)
+  unsigned int numScriptCode = 1 + u_getIntPropertyMaxValue (UCHAR_SCRIPT);
+  for (unsigned int i = 0; i < numScriptCode; i++)
     if (unlikely (hb_icu_script_to_script ((UScriptCode) i) == script))
       return (UScriptCode) i;
 
diff --git a/src/hb-machinery.hh b/src/hb-machinery.hh
index 39e9629..19d2e17 100644
--- a/src/hb-machinery.hh
+++ b/src/hb-machinery.hh
@@ -117,8 +117,8 @@
   enum { min_size = (size) }
 
 #define DEFINE_SIZE_ARRAY(size, array) \
-  DEFINE_COMPILES_ASSERTION ((void) (array)[0].static_size) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + VAR * sizeof ((array)[0])) \
+  DEFINE_COMPILES_ASSERTION ((void) (array)[0u].static_size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + VAR * sizeof ((array)[0u])) \
   enum { null_size = (size) }; \
   enum { min_size = (size) }
 
@@ -658,7 +658,7 @@
   }
   inline Supplier (const hb_vector_t<Type> *v)
   {
-    head = *v;
+    head = (const Type *) *v;
     len = v->len;
     stride = sizeof (Type);
   }
@@ -721,7 +721,7 @@
   }
   inline operator Type (void) const
   {
-#if defined(__GNUC__) || defined(__clang__)
+#if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
     /* Spoon-feed the compiler a big-endian integer with alignment 1.
      * https://github.com/harfbuzz/harfbuzz/pull/1398 */
     struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
diff --git a/src/hb-map.hh b/src/hb-map.hh
index c54c9d7..16b2255 100644
--- a/src/hb-map.hh
+++ b/src/hb-map.hh
@@ -168,7 +168,7 @@
   inline hb_codepoint_t operator [] (unsigned int key) const
   { return get (key); }
 
-  static const hb_codepoint_t INVALID = HB_MAP_VALUE_INVALID;
+  enum { INVALID = HB_MAP_VALUE_INVALID };
 
   inline void clear (void)
   {
diff --git a/src/hb-null.hh b/src/hb-null.hh
index 080e0b5..6a86868 100644
--- a/src/hb-null.hh
+++ b/src/hb-null.hh
@@ -77,6 +77,7 @@
 /*
  * Null()
  */
+
 extern HB_INTERNAL
 hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
 
@@ -86,7 +87,13 @@
   static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
   return *reinterpret_cast<Type const *> (_hb_NullPool);
 }
-#define Null(Type) Null<typename hb_remove_const (typename hb_remove_reference (Type))> ()
+template <typename QType>
+struct NullHelper
+{
+  typedef typename hb_remove_const (typename hb_remove_reference (QType)) Type;
+  static inline const Type & get_null (void) { return Null<Type> (); }
+};
+#define Null(Type) NullHelper<Type>::get_null ()
 
 /* Specializations for arbitrary-content Null objects expressed in bytes. */
 #define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
@@ -129,17 +136,23 @@
   memcpy (obj, &Null(Type), sizeof (*obj));
   return *obj;
 }
-#define Crap(Type) Crap<typename hb_remove_const (typename hb_remove_reference (Type))> ()
+template <typename QType>
+struct CrapHelper
+{
+  typedef typename hb_remove_const (typename hb_remove_reference (QType)) Type;
+  static inline Type & get_crap (void) { return Crap<Type> (); }
+};
+#define Crap(Type) CrapHelper<Type>::get_crap ()
 
 template <typename Type>
-struct CrapOrNull {
+struct CrapOrNullHelper {
   static inline Type & get (void) { return Crap(Type); }
 };
 template <typename Type>
-struct CrapOrNull<const Type> {
-  static inline Type const & get (void) { return Null(Type); }
+struct CrapOrNullHelper<const Type> {
+  static inline const Type & get (void) { return Null(Type); }
 };
-#define CrapOrNull(Type) CrapOrNull<Type>::get ()
+#define CrapOrNull(Type) CrapOrNullHelper<Type>::get ()
 
 
 /*
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index cdc610b..7f32fb3 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -495,7 +495,8 @@
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    Supplier<CmapSubtableLongGroup> supplier (group_data, group_data.len);
+    Supplier<CmapSubtableLongGroup> supplier ((const OT::CmapSubtableLongGroup*) group_data,
+					      group_data.len);
     if (unlikely (!groups.serialize (c, supplier, group_data.len))) return_trace (false);
     return true;
   }
@@ -842,7 +843,7 @@
 
 struct cmap
 {
-  static const hb_tag_t tableTag	= HB_OT_TAG_cmap;
+  enum { tableTag = HB_OT_TAG_cmap };
 
   struct subset_plan
   {
diff --git a/src/hb-ot-color-cbdt-table.hh b/src/hb-ot-color-cbdt-table.hh
index 47774fd..2b49f2c 100644
--- a/src/hb-ot-color-cbdt-table.hh
+++ b/src/hb-ot-color-cbdt-table.hh
@@ -332,7 +332,7 @@
 {
   friend struct CBDT;
 
-  static const hb_tag_t tableTag = HB_OT_TAG_CBLC;
+  enum { tableTag = HB_OT_TAG_CBLC };
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -378,7 +378,7 @@
 
 struct CBDT
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
+  enum { tableTag = HB_OT_TAG_CBDT };
 
   struct accelerator_t
   {
diff --git a/src/hb-ot-color-colr-table.hh b/src/hb-ot-color-colr-table.hh
index 84c3433..fd73255 100644
--- a/src/hb-ot-color-colr-table.hh
+++ b/src/hb-ot-color-colr-table.hh
@@ -87,7 +87,7 @@
 
 struct COLR
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_COLR;
+  enum { tableTag = HB_OT_TAG_COLR };
 
   inline bool has_data (void) const { return numBaseGlyphs; }
 
diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh
index 332f0dd..85bdc7e 100644
--- a/src/hb-ot-color-cpal-table.hh
+++ b/src/hb-ot-color-cpal-table.hh
@@ -110,12 +110,12 @@
 
 struct CPAL
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_CPAL;
+  enum { tableTag = HB_OT_TAG_CPAL };
 
   inline bool has_data (void) const { return numPalettes; }
 
   inline unsigned int get_size (void) const
-  { return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); }
+  { return min_size + numPalettes * sizeof (colorRecordIndicesZ[0u]); }
 
   inline unsigned int get_palette_count () const { return numPalettes; }
   inline unsigned int get_color_count () const { return numColors; }
diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh
index 08dee2a..2d24fba 100644
--- a/src/hb-ot-color-sbix-table.hh
+++ b/src/hb-ot-color-sbix-table.hh
@@ -130,7 +130,7 @@
 
 struct sbix
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_sbix;
+  enum { tableTag = HB_OT_TAG_sbix };
 
   inline bool has_data (void) const { return version; }
 
diff --git a/src/hb-ot-color-svg-table.hh b/src/hb-ot-color-svg-table.hh
index ad35510..0b8ec1a 100644
--- a/src/hb-ot-color-svg-table.hh
+++ b/src/hb-ot-color-svg-table.hh
@@ -73,7 +73,7 @@
 
 struct SVG
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_SVG;
+  enum { tableTag = HB_OT_TAG_SVG };
 
   inline bool has_data (void) const { return svgDocEntries; }
 
diff --git a/src/hb-ot-deprecated.h b/src/hb-ot-deprecated.h
new file mode 100644
index 0000000..bce51b7
--- /dev/null
+++ b/src/hb-ot-deprecated.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright © 2018  Google, 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
+#ifndef HB_OT_DEPRECATED_H
+#define HB_OT_DEPRECATED_H
+
+#include "hb.h"
+#include "hb-ot-name.h"
+
+
+HB_BEGIN_DECLS
+
+#ifndef HB_DISABLE_DEPRECATED
+
+
+/* Like hb_ot_layout_table_find_script, but takes zero-terminated array of scripts to test */
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_table_select_script) hb_bool_t
+hb_ot_layout_table_choose_script (hb_face_t      *face,
+				  hb_tag_t        table_tag,
+				  const hb_tag_t *script_tags,
+				  unsigned int   *script_index,
+				  hb_tag_t       *chosen_script);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_script_select_language) hb_bool_t
+hb_ot_layout_script_find_language (hb_face_t    *face,
+				   hb_tag_t      table_tag,
+				   unsigned int  script_index,
+				   hb_tag_t      language_tag,
+				   unsigned int *language_index);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language) void
+hb_ot_tags_from_script (hb_script_t  script,
+			hb_tag_t    *script_tag_1,
+			hb_tag_t    *script_tag_2);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language) hb_tag_t
+hb_ot_tag_from_language (hb_language_t language);
+
+
+/**
+ * HB_OT_VAR_NO_AXIS_INDEX:
+ *
+ * Since: 1.4.2
+ * Deprecated: 2.2.0
+ */
+#define HB_OT_VAR_NO_AXIS_INDEX		0xFFFFFFFFu
+
+/**
+ * hb_ot_var_axis_t:
+ *
+ * Since: 1.4.2
+ * Deprecated: 2.2.0
+ */
+typedef struct hb_ot_var_axis_t
+{
+  hb_tag_t tag;
+  hb_ot_name_id_t name_id;
+  float min_value;
+  float default_value;
+  float max_value;
+} hb_ot_var_axis_t;
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_get_axis_infos) unsigned int
+hb_ot_var_get_axes (hb_face_t        *face,
+		    unsigned int      start_offset,
+		    unsigned int     *axes_count /* IN/OUT */,
+		    hb_ot_var_axis_t *axes_array /* OUT */);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_find_axis_info) hb_bool_t
+hb_ot_var_find_axis (hb_face_t        *face,
+		     hb_tag_t          axis_tag,
+		     unsigned int     *axis_index,
+		     hb_ot_var_axis_t *axis_info);
+
+
+#endif
+
+HB_END_DECLS
+
+#endif /* HB_OT_DEPRECATED_H */
diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index c88f433..23d16a7 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -45,7 +45,7 @@
 {
   friend struct glyf;
 
-  static const hb_tag_t tableTag = HB_OT_TAG_loca;
+  enum { tableTag = HB_OT_TAG_loca };
 
   inline bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
   {
@@ -71,7 +71,7 @@
 
 struct glyf
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_glyf;
+  enum { tableTag = HB_OT_TAG_glyf };
 
   inline bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
   {
diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh
index 0fea24b..6545f26 100644
--- a/src/hb-ot-hdmx-table.hh
+++ b/src/hb-ot-hdmx-table.hh
@@ -123,7 +123,7 @@
 
 struct hdmx
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_hdmx;
+  enum { tableTag = HB_OT_TAG_hdmx };
 
   inline unsigned int get_size (void) const
   {
diff --git a/src/hb-ot-head-table.hh b/src/hb-ot-head-table.hh
index 602e365..931ccd4 100644
--- a/src/hb-ot-head-table.hh
+++ b/src/hb-ot-head-table.hh
@@ -45,7 +45,7 @@
 {
   friend struct OffsetTable;
 
-  static const hb_tag_t tableTag	= HB_OT_TAG_head;
+  enum { tableTag = HB_OT_TAG_head };
 
   inline unsigned int get_upem (void) const
   {
diff --git a/src/hb-ot-hhea-table.hh b/src/hb-ot-hhea-table.hh
index 3336cad..0f47c63 100644
--- a/src/hb-ot-hhea-table.hh
+++ b/src/hb-ot-hhea-table.hh
@@ -86,10 +86,10 @@
 };
 
 struct hhea : _hea<hhea> {
-  static const hb_tag_t tableTag	= HB_OT_TAG_hhea;
+  enum { tableTag = HB_OT_TAG_hhea };
 };
 struct vhea : _hea<vhea> {
-  static const hb_tag_t tableTag	= HB_OT_TAG_vhea;
+  enum { tableTag = HB_OT_TAG_vhea };
 };
 
 
diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh
index 091b601..f22ed1d 100644
--- a/src/hb-ot-hmtx-table.hh
+++ b/src/hb-ot-hmtx-table.hh
@@ -192,7 +192,7 @@
       default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
 
       bool got_font_extents = false;
-      if (T::os2Tag)
+      if (T::os2Tag != HB_TAG_NONE)
       {
 #define USE_TYPO_METRICS (1u<<7)
 	if (0 != (face->table.OS2->fsSelection & USE_TYPO_METRICS))
@@ -327,14 +327,14 @@
 };
 
 struct hmtx : hmtxvmtx<hmtx, hhea> {
-  static const hb_tag_t tableTag	= HB_OT_TAG_hmtx;
-  static const hb_tag_t variationsTag	= HB_OT_TAG_HVAR;
-  static const hb_tag_t os2Tag		= HB_OT_TAG_OS2;
+  enum { tableTag = HB_OT_TAG_hmtx };
+  enum { variationsTag = HB_OT_TAG_HVAR };
+  enum { os2Tag = HB_OT_TAG_OS2 };
 };
 struct vmtx : hmtxvmtx<vmtx, vhea> {
-  static const hb_tag_t tableTag	= HB_OT_TAG_vmtx;
-  static const hb_tag_t variationsTag	= HB_OT_TAG_VVAR;
-  static const hb_tag_t os2Tag		= HB_TAG_NONE;
+  enum { tableTag = HB_OT_TAG_vmtx };
+  enum { variationsTag = HB_OT_TAG_VVAR };
+  enum { os2Tag = HB_TAG_NONE };
 };
 
 struct hmtx_accelerator_t : hmtx::accelerator_t {};
diff --git a/src/hb-ot-kern-table.hh b/src/hb-ot-kern-table.hh
index b57ebae..a184f2e 100644
--- a/src/hb-ot-kern-table.hh
+++ b/src/hb-ot-kern-table.hh
@@ -56,7 +56,7 @@
     if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount))
       return 0;
     unsigned int i = leftC * rightClassCount + rightC;
-    return kernValue[kernIndex[i]];
+    return kernValue[(unsigned) kernIndex[i]];
   }
 
   inline bool apply (AAT::hb_aat_apply_context_t *c) const
@@ -160,7 +160,7 @@
 
 struct KernOTSubTableHeader
 {
-  static const bool apple = false;
+  enum { apple = false };
   typedef AAT::ObsoleteTypes Types;
 
   inline unsigned int tuple_count (void) const { return 0; }
@@ -197,8 +197,8 @@
 {
   friend struct AAT::KerxTable<KernOT>;
 
-  static const hb_tag_t tableTag = HB_OT_TAG_kern;
-  static const uint16_t minVersion = 0;
+  enum { tableTag = HB_OT_TAG_kern };
+  enum { minVersion = 0u };
 
   typedef KernOTSubTableHeader SubTableHeader;
   typedef SubTableHeader::Types Types;
@@ -215,7 +215,7 @@
 
 struct KernAATSubTableHeader
 {
-  static const bool apple = true;
+  enum { apple = true };
   typedef AAT::ObsoleteTypes Types;
 
   inline unsigned int tuple_count (void) const { return 0; }
@@ -252,8 +252,8 @@
 {
   friend struct AAT::KerxTable<KernAAT>;
 
-  static const hb_tag_t tableTag = HB_OT_TAG_kern;
-  static const uint32_t minVersion = 0x00010000u;
+  enum { tableTag = HB_OT_TAG_kern };
+  enum { minVersion = 0x00010000u };
 
   typedef KernAATSubTableHeader SubTableHeader;
   typedef SubTableHeader::Types Types;
@@ -269,7 +269,7 @@
 
 struct kern
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_kern;
+  enum { tableTag = HB_OT_TAG_kern };
 
   inline bool has_data (void) const { return u.version32; }
   inline unsigned int get_type (void) const { return u.major; }
diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index fb57e76..320f003 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -465,7 +465,7 @@
 
 struct BASE
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_BASE;
+  enum { tableTag = HB_OT_TAG_BASE };
 
   inline const Axis &get_axis (hb_direction_t direction) const
   { return HB_DIRECTION_IS_VERTICAL (direction) ? this+vAxis : this+hAxis; }
diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh
index a0ae27e..f1052d8 100644
--- a/src/hb-ot-layout-gdef-table.hh
+++ b/src/hb-ot-layout-gdef-table.hh
@@ -340,7 +340,7 @@
 
 struct GDEF
 {
-  static const hb_tag_t tableTag	= HB_OT_TAG_GDEF;
+  enum { tableTag = HB_OT_TAG_GDEF };
 
   enum GlyphClasses {
     UnclassifiedGlyph	= 0,
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 2589218..8559744 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -625,8 +625,8 @@
   inline bool intersects (const hb_set_t *glyphs,
 			  const ValueFormat *valueFormats) const
   {
-    unsigned int len1 = valueFormats[0].get_len ();
-    unsigned int len2 = valueFormats[1].get_len ();
+    unsigned int len1 = valueFormats[0u].get_len ();
+    unsigned int len2 = valueFormats[1u].get_len ();
     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
 
     const PairValueRecord *record = &firstPairValueRecord;
@@ -644,8 +644,8 @@
 			      const ValueFormat *valueFormats) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    unsigned int len1 = valueFormats[0].get_len ();
-    unsigned int len2 = valueFormats[1].get_len ();
+    unsigned int len1 = valueFormats[0u].get_len ();
+    unsigned int len2 = valueFormats[1u].get_len ();
     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
 
     const PairValueRecord *record = &firstPairValueRecord;
@@ -658,8 +658,8 @@
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
-    unsigned int len1 = valueFormats[0].get_len ();
-    unsigned int len2 = valueFormats[1].get_len ();
+    unsigned int len1 = valueFormats[0u].get_len ();
+    unsigned int len2 = valueFormats[1u].get_len ();
     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
 
     unsigned int count = len;
@@ -681,8 +681,8 @@
       else
       {
 	/* Note the intentional use of "|" instead of short-circuit "||". */
-	if (valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()) |
-	    valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]))
+	if (valueFormats[0u].apply_value (c, this, &record->values[0u], buffer->cur_pos()) |
+	    valueFormats[1u].apply_value (c, this, &record->values[len1], buffer->pos[pos]))
 	  buffer->unsafe_to_break (buffer->idx, pos + 1);
 	if (len2)
 	  pos++;
@@ -698,7 +698,7 @@
   {
     const void *base;
     const ValueFormat *valueFormats;
-    unsigned int len1; /* valueFormats[0].get_len() */
+    unsigned int len1; /* valueFormats[0u].get_len() */
     unsigned int stride; /* 1 + len1 + len2 */
   };
 
@@ -713,8 +713,8 @@
 
     unsigned int count = len;
     const PairValueRecord *record = &firstPairValueRecord;
-    return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) &&
-		  closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
+    return_trace (closure->valueFormats[0u].sanitize_values_stride_unsafe (c, closure->base, &record->values[0u], count, closure->stride) &&
+		  closure->valueFormats[1u].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
   }
 
   protected:
@@ -781,8 +781,8 @@
 
     if (!c->check_struct (this)) return_trace (false);
 
-    unsigned int len1 = valueFormat[0].get_len ();
-    unsigned int len2 = valueFormat[1].get_len ();
+    unsigned int len1 = valueFormat[0u].get_len ();
+    unsigned int len2 = valueFormat[1u].get_len ();
     PairSet::sanitize_closure_t closure =
     {
       this,
@@ -799,10 +799,10 @@
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
-  ValueFormat	valueFormat[2];		/* [0] Defines the types of data in
+  ValueFormat	valueFormat[2u];	/* [0u] Defines the types of data in
 					 * ValueRecord1--for the first glyph
 					 * in the pair--may be zero (0) */
-					/* [1] Defines the types of data in
+					/* [1u] Defines the types of data in
 					 * ValueRecord2--for the second glyph
 					 * in the pair--may be zero (0) */
   OffsetArrayOf<PairSet>
@@ -885,7 +885,7 @@
     return_trace (c->check_range ((const void *) values,
 				  count,
 				  record_size) &&
-		  valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
+		  valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0u], count, stride) &&
 		  valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
   }
 
@@ -1628,7 +1628,7 @@
 
 struct GPOS : GSUBGPOS
 {
-  static const hb_tag_t tableTag	= HB_OT_TAG_GPOS;
+  enum { tableTag = HB_OT_TAG_GPOS };
 
   inline const PosLookup& get_lookup (unsigned int i) const
   { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 27bd440..6acdcf2 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -1475,7 +1475,7 @@
 
 struct GSUB : GSUBGPOS
 {
-  static const hb_tag_t tableTag	= HB_OT_TAG_GSUB;
+  enum { tableTag = HB_OT_TAG_GSUB };
 
   inline const SubstLookup& get_lookup (unsigned int i) const
   { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
index a9bfee1..3429997 100644
--- a/src/hb-ot-layout-gsubgpos.hh
+++ b/src/hb-ot-layout-gsubgpos.hh
@@ -1350,7 +1350,7 @@
     return_trace (inputCount.sanitize (c) &&
 		  lookupCount.sanitize (c) &&
 		  c->check_range (inputZ.arrayZ,
-				  inputZ[0].static_size * (inputCount ? inputCount - 1 : 0) +
+				  inputZ.item_size * (inputCount ? inputCount - 1 : 0) +
 				  LookupRecord::static_size * lookupCount));
   }
 
@@ -1672,7 +1672,7 @@
 {
   inline bool intersects (const hb_set_t *glyphs) const
   {
-    if (!(this+coverageZ[0]).intersects (glyphs))
+    if (!(this+coverageZ[0u]).intersects (glyphs))
       return false;
 
     struct ContextClosureLookupContext lookup_context = {
@@ -1687,7 +1687,7 @@
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
-    if (!(this+coverageZ[0]).intersects (c->glyphs))
+    if (!(this+coverageZ[0u]).intersects (c->glyphs))
       return;
 
     const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
@@ -1704,7 +1704,7 @@
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    (this+coverageZ[0]).add_coverage (c->input);
+    (this+coverageZ[0u]).add_coverage (c->input);
 
     const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
     struct ContextCollectGlyphsLookupContext lookup_context = {
@@ -1731,12 +1731,12 @@
   }
 
   inline const Coverage &get_coverage (void) const
-  { return this+coverageZ[0]; }
+  { return this+coverageZ[0u]; }
 
   inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
+    unsigned int index = (this+coverageZ[0u]).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
     const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
@@ -1759,7 +1759,7 @@
     TRACE_SANITIZE (this);
     if (!c->check_struct (this)) return_trace (false);
     unsigned int count = glyphCount;
-    if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
+    if (!count) return_trace (false); /* We want to access coverageZ[0u] freely. */
     if (!c->check_array (coverageZ.arrayZ, count)) return_trace (false);
     for (unsigned int i = 0; i < count; i++)
       if (!coverageZ[i].sanitize (c, this)) return_trace (false);
@@ -1838,7 +1838,7 @@
 {
   return intersects_array (glyphs,
 			   backtrackCount, backtrack,
-			   lookup_context.funcs.intersects, lookup_context.intersects_data[0])
+			   lookup_context.funcs.intersects, lookup_context.intersects_data[0u])
       && intersects_array (glyphs,
 			   inputCount ? inputCount - 1 : 0, input,
 			   lookup_context.funcs.intersects, lookup_context.intersects_data[1])
diff --git a/src/hb-ot-layout-jstf-table.hh b/src/hb-ot-layout-jstf-table.hh
index 2fb23cb..d05f813 100644
--- a/src/hb-ot-layout-jstf-table.hh
+++ b/src/hb-ot-layout-jstf-table.hh
@@ -195,7 +195,7 @@
 
 struct JSTF
 {
-  static const hb_tag_t tableTag	= HB_OT_TAG_JSTF;
+  enum { tableTag = HB_OT_TAG_JSTF };
 
   inline unsigned int get_script_count (void) const
   { return scriptList.len; }
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index d0b22ef..b08ee7f 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1299,7 +1299,7 @@
 struct GSUBProxy
 {
   enum { table_index = 0 };
-  static const bool inplace = false;
+  enum { inplace = false };
   typedef OT::SubstLookup Lookup;
 
   GSUBProxy (hb_face_t *face) :
@@ -1313,7 +1313,7 @@
 struct GPOSProxy
 {
   enum { table_index = 1 };
-  static const bool inplace = true;
+  enum { inplace = true };
   typedef OT::PosLookup Lookup;
 
   GPOSProxy (hb_face_t *face) :
diff --git a/src/hb-ot-math-table.hh b/src/hb-ot-math-table.hh
index 153a417..e100991 100644
--- a/src/hb-ot-math-table.hh
+++ b/src/hb-ot-math-table.hh
@@ -680,7 +680,7 @@
 
 struct MATH
 {
-  static const hb_tag_t tableTag	= HB_OT_TAG_MATH;
+  enum { tableTag = HB_OT_TAG_MATH };
 
   inline bool has_data (void) const { return version.to_int (); }
 
diff --git a/src/hb-ot-maxp-table.hh b/src/hb-ot-maxp-table.hh
index 198dd25..885685d 100644
--- a/src/hb-ot-maxp-table.hh
+++ b/src/hb-ot-maxp-table.hh
@@ -71,7 +71,7 @@
 
 struct maxp
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_maxp;
+  enum { tableTag = HB_OT_TAG_maxp };
 
   inline unsigned int get_num_glyphs (void) const
   {
diff --git a/src/hb-ot-name-table.hh b/src/hb-ot-name-table.hh
index ab07b71..a903e1c 100644
--- a/src/hb-ot-name-table.hh
+++ b/src/hb-ot-name-table.hh
@@ -151,10 +151,10 @@
 
 struct name
 {
-  static const hb_tag_t tableTag	= HB_OT_TAG_name;
+  enum { tableTag = HB_OT_TAG_name };
 
   inline unsigned int get_size (void) const
-  { return min_size + count * nameRecordZ[0].min_size; }
+  { return min_size + count * nameRecordZ.item_size; }
 
   inline bool sanitize_records (hb_sanitize_context_t *c) const {
     TRACE_SANITIZE (this);
@@ -189,7 +189,7 @@
       this->names.init ();
       this->names.alloc (all_names.len);
 
-      for (uint16_t i = 0; i < all_names.len; i++)
+      for (unsigned int i = 0; i < all_names.len; i++)
       {
 	hb_ot_name_entry_t *entry = this->names.push ();
 
diff --git a/src/hb-ot-os2-table.hh b/src/hb-ot-os2-table.hh
index a5a9c07..e53eda7 100644
--- a/src/hb-ot-os2-table.hh
+++ b/src/hb-ot-os2-table.hh
@@ -40,7 +40,7 @@
 
 struct OS2
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_OS2;
+  enum { tableTag = HB_OT_TAG_OS2 };
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh
index 98df3e7..64f0936 100644
--- a/src/hb-ot-post-table.hh
+++ b/src/hb-ot-post-table.hh
@@ -71,7 +71,7 @@
 
 struct post
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_post;
+  enum { tableTag = HB_OT_TAG_post };
 
   inline bool subset (hb_subset_plan_t *plan) const
   {
@@ -107,7 +107,7 @@
       version = table->version.to_int ();
       if (version != 0x00020000) return;
 
-      const postV2Tail &v2 = table->v2;
+      const postV2Tail &v2 = table->v2X;
 
       glyphNameIndex = &v2.glyphNameIndex;
       pool = &StructAfter<uint8_t> (v2.glyphNameIndex);
@@ -250,7 +250,7 @@
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
 			  (version.to_int () == 0x00010000 ||
-			   (version.to_int () == 0x00020000 && v2.sanitize (c)) ||
+			   (version.to_int () == 0x00020000 && v2X.sanitize (c)) ||
 			   version.to_int () == 0x00030000)));
   }
 
@@ -286,7 +286,7 @@
 					 * is downloaded as a Type 1 font. */
   HBUINT32	maxMemType1;		/* Maximum memory usage when an OpenType font
 					 * is downloaded as a Type 1 font. */
-  postV2Tail	v2;
+  postV2Tail	v2X;
   DEFINE_SIZE_MIN (32);
 };
 
diff --git a/src/hb-ot-shape-complex-khmer.cc b/src/hb-ot-shape-complex-khmer.cc
index 497891e..8b6ec51 100644
--- a/src/hb-ot-shape-complex-khmer.cc
+++ b/src/hb-ot-shape-complex-khmer.cc
@@ -127,22 +127,25 @@
 
   for (; i < KHMER_NUM_FEATURES; i++)
     map->add_feature (khmer_features[i]);
-
-  map->enable_feature (HB_TAG('c','a','l','t'));
-  map->enable_feature (HB_TAG('c','l','i','g'));
-
 }
 
 static void
 override_features_khmer (hb_ot_shape_planner_t *plan)
 {
+  hb_ot_map_builder_t *map = &plan->map;
+
+  /* Khmer spec has 'clig' as part of required shaping features:
+   * "Apply feature 'clig' to form ligatures that are desired for
+   * typographical correctness.", hence in overrides... */
+  map->enable_feature (HB_TAG('c','l','i','g'));
+
   /* Uniscribe does not apply 'kern' in Khmer. */
   if (hb_options ().uniscribe_bug_compatible)
   {
-    plan->map.disable_feature (HB_TAG('k','e','r','n'));
+    map->disable_feature (HB_TAG('k','e','r','n'));
   }
 
-  plan->map.disable_feature (HB_TAG('l','i','g','a'));
+  map->disable_feature (HB_TAG('l','i','g','a'));
 }
 
 
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index ef97435..e0074d5 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -309,9 +309,6 @@
     map->enable_feature (HB_TAG ('v','e','r','t'), F_GLOBAL_SEARCH);
   }
 
-  if (planner->shaper->override_features)
-    planner->shaper->override_features (planner);
-
   for (unsigned int i = 0; i < num_user_features; i++)
   {
     const hb_feature_t *feature = &user_features[i];
@@ -330,6 +327,9 @@
       aat_map->add_feature (feature->tag, feature->value);
     }
   }
+
+  if (planner->shaper->override_features)
+    planner->shaper->override_features (planner);
 }
 
 
diff --git a/src/hb-ot-stat-table.hh b/src/hb-ot-stat-table.hh
index 02c376e..7ad45db 100644
--- a/src/hb-ot-stat-table.hh
+++ b/src/hb-ot-stat-table.hh
@@ -225,7 +225,7 @@
 
 struct STAT
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_STAT;
+  enum { tableTag = HB_OT_TAG_STAT };
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
diff --git a/src/hb-ot-var-avar-table.hh b/src/hb-ot-var-avar-table.hh
index c2b110a..70feb12 100644
--- a/src/hb-ot-var-avar-table.hh
+++ b/src/hb-ot-var-avar-table.hh
@@ -99,7 +99,7 @@
 
 struct avar
 {
-  static const hb_tag_t tableTag	= HB_OT_TAG_avar;
+  enum { tableTag = HB_OT_TAG_avar };
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh
index fed334e..975dae9 100644
--- a/src/hb-ot-var-fvar-table.hh
+++ b/src/hb-ot-var-fvar-table.hh
@@ -96,7 +96,7 @@
 
 struct fvar
 {
-  static const hb_tag_t tableTag	= HB_OT_TAG_fvar;
+  enum { tableTag = HB_OT_TAG_fvar };
 
   inline bool has_data (void) const { return version.to_int (); }
 
diff --git a/src/hb-ot-var-hvar-table.hh b/src/hb-ot-var-hvar-table.hh
index 62a6547..a60e35b 100644
--- a/src/hb-ot-var-hvar-table.hh
+++ b/src/hb-ot-var-hvar-table.hh
@@ -102,8 +102,8 @@
 
 struct HVARVVAR
 {
-  static const hb_tag_t HVARTag	= HB_OT_TAG_HVAR;
-  static const hb_tag_t VVARTag	= HB_OT_TAG_VVAR;
+  enum { HVARTag = HB_OT_TAG_HVAR };
+  enum { VVARTag = HB_OT_TAG_VVAR };
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -143,10 +143,10 @@
 };
 
 struct HVAR : HVARVVAR {
-  static const hb_tag_t tableTag	= HB_OT_TAG_HVAR;
+  enum { tableTag = HB_OT_TAG_HVAR };
 };
 struct VVAR : HVARVVAR {
-  static const hb_tag_t tableTag	= HB_OT_TAG_VVAR;
+  enum { tableTag = HB_OT_TAG_VVAR };
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
diff --git a/src/hb-ot-var-mvar-table.hh b/src/hb-ot-var-mvar-table.hh
index b16a09b..23d2649 100644
--- a/src/hb-ot-var-mvar-table.hh
+++ b/src/hb-ot-var-mvar-table.hh
@@ -58,7 +58,7 @@
 
 struct MVAR
 {
-  static const hb_tag_t tableTag	= HB_OT_TAG_MVAR;
+  enum { tableTag = HB_OT_TAG_MVAR };
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc
index 56d2481..e327fb7 100644
--- a/src/hb-ot-var.cc
+++ b/src/hb-ot-var.cc
@@ -79,7 +79,7 @@
  * hb_ot_var_get_axes:
  *
  * Since: 1.4.2
- * Deprecated: REPLACEME
+ * Deprecated: 2.2.0
  **/
 unsigned int
 hb_ot_var_get_axes (hb_face_t        *face,
@@ -94,7 +94,7 @@
  * hb_ot_var_find_axis:
  *
  * Since: 1.4.2
- * Deprecated: REPLACEME
+ * Deprecated: 2.2.0
  **/
 hb_bool_t
 hb_ot_var_find_axis (hb_face_t        *face,
@@ -108,7 +108,7 @@
 /**
  * hb_ot_var_get_axis_infos:
  *
- * Since: REPLACEME
+ * Since: 2.2.0
  **/
 HB_EXTERN unsigned int
 hb_ot_var_get_axis_infos (hb_face_t             *face,
@@ -122,7 +122,7 @@
 /**
  * hb_ot_var_find_axis_info:
  *
- * Since: REPLACEME
+ * Since: 2.2.0
  **/
 HB_EXTERN hb_bool_t
 hb_ot_var_find_axis_info (hb_face_t             *face,
diff --git a/src/hb-ot-var.h b/src/hb-ot-var.h
index 779be10..b9d5e40 100644
--- a/src/hb-ot-var.h
+++ b/src/hb-ot-var.h
@@ -63,7 +63,7 @@
  * hb_ot_var_axis_flags_t:
  * @HB_OT_VAR_AXIS_FLAG_HIDDEN: The axis should not be exposed directly in user interfaces.
  *
- * Since: REPLACEME
+ * Since: 2.2.0
  */
 typedef enum { /*< flags >*/
   HB_OT_VAR_AXIS_FLAG_HIDDEN	= 0x00000001u,
@@ -74,7 +74,7 @@
 /**
  * hb_ot_var_axis_info_t:
  *
- * Since: REPLACEME
+ * Since: 2.2.0
  */
 typedef struct hb_ot_var_axis_info_t
 {
diff --git a/src/hb-ot-vorg-table.hh b/src/hb-ot-vorg-table.hh
index 5a00bfc..effb17d 100644
--- a/src/hb-ot-vorg-table.hh
+++ b/src/hb-ot-vorg-table.hh
@@ -57,7 +57,7 @@
 
 struct VORG
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_VORG;
+  enum { tableTag = HB_OT_TAG_VORG };
 
   inline bool has_data (void) const { return version.to_int (); }
 
@@ -93,7 +93,7 @@
       unsigned int  size = VertOriginMetric::static_size * subset_metrics.len;
       VertOriginMetric  *metrics = c.allocate_size<VertOriginMetric> (size);
       if (likely (metrics != nullptr))
-        memcpy (metrics, &subset_metrics[0], size);
+        memcpy (metrics, &subset_metrics[0u], size);
       else
         success = false;
     }
diff --git a/src/hb-ot.h b/src/hb-ot.h
index c168175..db78469 100644
--- a/src/hb-ot.h
+++ b/src/hb-ot.h
@@ -31,6 +31,7 @@
 #include "hb.h"
 
 #include "hb-ot-color.h"
+#include "hb-ot-deprecated.h"
 #include "hb-ot-font.h"
 #include "hb-ot-layout.h"
 #include "hb-ot-math.h"
diff --git a/src/hb-set-digest.hh b/src/hb-set-digest.hh
index 4e99df0..1daefad 100644
--- a/src/hb-set-digest.hh
+++ b/src/hb-set-digest.hh
@@ -50,13 +50,13 @@
 {
   enum { mask_bytes = sizeof (mask_t) };
   enum { mask_bits = sizeof (mask_t) * 8 };
-  static const unsigned int num_bits = 0
-				     + (mask_bytes >= 1 ? 3 : 0)
-				     + (mask_bytes >= 2 ? 1 : 0)
-				     + (mask_bytes >= 4 ? 1 : 0)
-				     + (mask_bytes >= 8 ? 1 : 0)
-				     + (mask_bytes >= 16? 1 : 0)
-				     + 0;
+  enum { num_bits = 0
+		  + (mask_bytes >= 1 ? 3 : 0)
+		  + (mask_bytes >= 2 ? 1 : 0)
+		  + (mask_bytes >= 4 ? 1 : 0)
+		  + (mask_bytes >= 8 ? 1 : 0)
+		  + (mask_bytes >= 16? 1 : 0)
+		  + 0 };
 
   static_assert ((shift < sizeof (hb_codepoint_t) * 8), "");
   static_assert ((shift + num_bits <= sizeof (hb_codepoint_t) * 8), "");
diff --git a/src/hb-set.hh b/src/hb-set.hh
index 8b7a0f3..f1fccd8 100644
--- a/src/hb-set.hh
+++ b/src/hb-set.hh
@@ -375,8 +375,8 @@
     if (!resize (count))
       return;
     population = other->population;
-    memcpy (pages, other->pages, count * pages.item_size);
-    memcpy (page_map, other->page_map, count * page_map.item_size);
+    memcpy ((void *) pages, (const void *) other->pages, count * pages.item_size);
+    memcpy ((void *) page_map, (const void *) other->page_map, count * page_map.item_size);
   }
 
   inline bool is_equal (const hb_set_t *other) const
@@ -660,7 +660,7 @@
     unsigned int count = pages.len;
     for (int i = count - 1; i >= 0; i++)
       if (!page_at (i).is_empty ())
-        return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_max ();
+        return page_map[(unsigned) i].major * page_t::PAGE_BITS + page_at (i).get_max ();
     return INVALID;
   }
 
@@ -678,7 +678,7 @@
       pages[map.index].init0 ();
       memmove (page_map + i + 1,
 	       page_map + i,
-	       (page_map.len - 1 - i) * sizeof (page_map[0]));
+	       (page_map.len - 1 - i) * page_map.item_size);
       page_map[i] = map;
     }
     return &pages[page_map[i].index];
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index cc6c9e1..22e9192 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -80,7 +80,7 @@
       return false;
     }
   retry:
-    hb_serialize_context_t serializer (buf, buf_size);
+    hb_serialize_context_t serializer ((void *) buf, buf_size);
     hb_subset_context_t c (plan, &serializer);
     result = table->subset (&c);
     if (serializer.ran_out_of_room)
diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc
index 1fae643..e98e41f 100644
--- a/src/hb-uniscribe.cc
+++ b/src/hb-uniscribe.cc
@@ -695,7 +695,7 @@
       {
         active_feature_t *feature = active_features.find (&event->feature);
 	if (feature)
-	  active_features.remove (feature - active_features);
+	  active_features.remove (feature - active_features.arrayZ ());
       }
     }
 
@@ -886,8 +886,8 @@
 				     &items[i].a,
 				     script_tags[i],
 				     language_tag,
-				     range_char_counts,
-				     range_properties,
+				     range_char_counts.arrayZ (),
+				     range_properties.arrayZ (),
 				     range_properties.len,
 				     pchars + chars_offset,
 				     item_chars_len,
@@ -927,8 +927,8 @@
 				     &items[i].a,
 				     script_tags[i],
 				     language_tag,
-				     range_char_counts,
-				     range_properties,
+				     range_char_counts.arrayZ (),
+				     range_properties.arrayZ (),
 				     range_properties.len,
 				     pchars + chars_offset,
 				     log_clusters + chars_offset,
diff --git a/src/hb-vector.hh b/src/hb-vector.hh
index 787512f..313c24c 100644
--- a/src/hb-vector.hh
+++ b/src/hb-vector.hh
@@ -101,8 +101,8 @@
   inline hb_sorted_array_t<const Type> as_sorted_array (void) const
   { return hb_sorted_array (arrayZ(), len); }
 
-  template <typename T> inline operator  T * (void) { return arrayZ(); }
-  template <typename T> inline operator const T * (void) const { return arrayZ(); }
+  template <typename T> explicit_operator inline operator  T * (void) { return arrayZ(); }
+  template <typename T> explicit_operator inline operator const T * (void) const { return arrayZ(); }
 
   inline Type * operator  + (unsigned int i) { return arrayZ() + i; }
   inline const Type * operator  + (unsigned int i) const { return arrayZ() + i; }
diff --git a/src/hb-version.h b/src/hb-version.h
index fb9f8f3..7c4a8ad 100644
--- a/src/hb-version.h
+++ b/src/hb-version.h
@@ -37,10 +37,10 @@
 
 
 #define HB_VERSION_MAJOR 2
-#define HB_VERSION_MINOR 1
-#define HB_VERSION_MICRO 3
+#define HB_VERSION_MINOR 2
+#define HB_VERSION_MICRO 0
 
-#define HB_VERSION_STRING "2.1.3"
+#define HB_VERSION_STRING "2.2.0"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
 	((major)*10000+(minor)*100+(micro) <= \
diff --git a/test/shaping/data/in-house/tests/macos.tests b/test/shaping/data/in-house/tests/macos.tests
index 8bce253..859992c 100644
--- a/test/shaping/data/in-house/tests/macos.tests
+++ b/test/shaping/data/in-house/tests/macos.tests
@@ -1,31 +1,35 @@
-# 10.12.6
-/System/Library/Fonts/Helvetica.dfont@c7bec2785a4c402b7809b5e35337c3d24c18e281:--shaper ot --font-funcs ot:U+006D,U+0300:[m=0+1706|gravecmb=0@-284,10+0]
-/System/Library/Fonts/LucidaGrande.ttc@d89a9d7e57767bfe3b5a4cfd22bb1e9dbe03a062:--shaper ot --font-funcs ot:U+006D,U+0300:[mgrave=0+1912]
-/System/Library/Fonts/Times.dfont@39c954614d3f3317b28564db06d5b7b7a6ff0e39:--shaper ot --font-funcs ot:U+0066,U+0069:[fi=0+1139]
-/Library/Fonts/Khmer MN.ttc@5f5b1072df99b7355d3066ea85fe82969d13c94a:--shaper ot --font-funcs ot:U+17A2,U+1780,U+17D2,U+179F,U+179A,U+1781,U+17D2,U+1798,U+17C2,U+179A:[km_qa=0+1025|km_ka=1+1025|km_sa.sub=1+517|km_ro=4+593|km_vs_ae=5+605|km_kha=5+1025|km_mo.sub=5+0|km_ro=9+593]
-/Library/Fonts/Tamil MN.ttc@37a2020c3f86ebcc45e02c1de5fdf81e2676989d:--shaper ot --font-funcs ot:U+0BA4,U+0BCA,U+0B95,U+0BC1,U+0B95,U+0BCD,U+0B95,U+0BAA,U+0BCD,U+0BAA,U+0B9F,U+0BCD,U+0B9F,U+0BC1:[tgm_e=0+1702|tgc_ta=0+1598|tgm_aa=0+1149|tgc_ku=2+1962|tgc_k=4+1592|tgc_ka=6+1592|tgc_p=7+1370|tgc_pa=9+1370|tgc_tt=10+1596|tgc_ttu=12+1833]
-/System/Library/Fonts/Times.dfont@39c954614d3f3317b28564db06d5b7b7a6ff0e39:--shaper ot --font-funcs ot:U+0041,U+0066,U+0300,U+0066,U+0069,U+005A:[A=0+1479|f=1+682|gravecmb=1@-480,588+0|fi=3+1139|Z=5+1251]
-/System/Library/Fonts/LucidaGrande.ttc@d89a9d7e57767bfe3b5a4cfd22bb1e9dbe03a062:--shaper ot --font-funcs ot:U+05E1,U+05B0:[shevahebrew=0@-7,0+0|samekhhebrew=0+1361]
-/Library/Fonts/Apple Chancery.ttf@5fc49ae9bce39e2105864323183b68ea34c9e562:--shaper ot --font-funcs ot:U+0054,U+0068,U+0020,U+0074,U+0068,U+0020,U+006C,U+006C,U+0020,U+0074,U+0065,U+0020,U+0074,U+006F,U+0020,U+0074,U+0072,U+0020,U+0066,U+0072,U+0020,U+0066,U+0075,U+0020,U+0066,U+006A:[T_h=0+2308|space=2+569|t_h=3+1687|space=5+569|l_l=6+1108|space=8+569|t_e=9+1408|space=11+569|t_o=12+1531|space=14+569|t_r=15+1385|space=17+569|f_r=18+1432|space=20+569|f_u=21+1733|space=23+569|f_j=24+1098]
-/System/Library/Fonts/GeezaPro.ttc@f43ee7151c2e9f1dddfbc26cfc148609eb5c5820:--shaper ot --font-funcs ot:U+0627,U+0644,U+0623,U+064E,U+0628,U+0652,U+062C,U+064E,U+062F,U+0650,U+064A,U+064E,U+0651,U+0629,U+0640,U+0627,U+0644,U+0639,U+064E,U+0631,U+064E,U+0628,U+0650,U+064A,U+064E,U+0651,U+0629:[u0629.final.tehMarbuta=26+713|u064e_u0651.shaddaFatha=23@0,-200+0|u064a.medial.yeh=23+656|u0650.kasra=21@80,290+80|u0628.initial.beh=21@-80,0+576|u064e.fatha=19@200,-570+200|u0631.final.reh=19@-200,0+702|u064e.fatha=17@200,-200+200|u0639.medial.ain=17@-200,0+738|u0644.initial.lam=16+515|u0627.final.alef=15+647|u0640.tatweel=14+449|u0629.final.tehMarbuta=13+713|u064e_u0651.shaddaFatha=10@0,-200+0|u064a.initial.yeh=10+656|u0650.kasra=8@80,570+80|u062f.final.dal=8@-80,0+822|u064e.fatha=6@290,-160+290|u062c.medial.jeem=6@-290,0+1069|u0652.sukun=4@0,-200+0|u0628.initial.beh=4+656|u064e.fatha=1@-252,120+-252|u0644_u0623.isolated.lamHamzaOnAlef=1@120,0+1282|u0627.alef=0+647]
-/System/Library/Fonts/GeezaPro.ttc@f43ee7151c2e9f1dddfbc26cfc148609eb5c5820:--shaper ot --font-funcs ot:U+0628,U+064A,U+064E,U+0651,U+0629:[u0629.final.tehMarbuta=4+713|u064e_u0651.shaddaFatha=1@0,-200+0|u064a.medial.yeh=1+656|u0628.initial.beh=0+656]
-/System/Library/Fonts/GeezaPro.ttc@f43ee7151c2e9f1dddfbc26cfc148609eb5c5820:--shaper ot --font-funcs ot:U+0631,U+0628:[u0628.beh=1+1415|u0631.reh=0@-202,0+700]
-/System/Library/Fonts/GeezaPro.ttc@f43ee7151c2e9f1dddfbc26cfc148609eb5c5820:--shaper ot --font-funcs ot:U+0628,U+064F:[u064f.damma=0@250,-250+250|u0628.beh=0@-250,0+1165]
-/System/Library/Fonts/SFNSDisplay.ttf@92787c30716672737e9059bc367c15d04fbc1ced:--shaper ot --font-funcs ot:U+0056,U+0041,U+0056,U+0041:[gid265=0+1227|gid4=1@-65,0+1162|gid265=2@-65,0+1162|gid4=3@-65,0+1227]
-/System/Library/Fonts/Apple Color Emoji.ttc@d2fe8a134483aa48a43a9d1e4b7204d37a4abdf5:--remove-default-ignorables --shaper ot --font-funcs ot:U+1F468,U+200D,U+1F469,U+200D,U+1F467,U+200D,U+1F466:[u1F46A.MWGB=0+800]
+# 10.12.6 https://gist.github.com/ebraminio/1704341fa16b06979e605aafd88198cf
+/System/Library/Fonts/Helvetica.dfont@c7bec2785a4c402b7809b5e35337c3d24c18e281:--font-funcs ot:U+006D,U+0300:[m=0+1706|gravecmb=0@-284,10+0]
+/System/Library/Fonts/LucidaGrande.ttc@d89a9d7e57767bfe3b5a4cfd22bb1e9dbe03a062:--font-funcs ot:U+006D,U+0300:[mgrave=0+1912]
+/System/Library/Fonts/Times.dfont@39c954614d3f3317b28564db06d5b7b7a6ff0e39:--font-funcs ot:U+0066,U+0069:[fi=0+1139]
+/Library/Fonts/Khmer MN.ttc@5f5b1072df99b7355d3066ea85fe82969d13c94a:--font-funcs ot:U+17A2,U+1780,U+17D2,U+179F,U+179A,U+1781,U+17D2,U+1798,U+17C2,U+179A:[km_qa=0+1025|km_ka=1+1025|km_sa.sub=1+517|km_ro=4+593|km_vs_ae=5+605|km_kha=5+1025|km_mo.sub=5+0|km_ro=9+593]
+/Library/Fonts/Tamil MN.ttc@37a2020c3f86ebcc45e02c1de5fdf81e2676989d:--font-funcs ot:U+0BA4,U+0BCA,U+0B95,U+0BC1,U+0B95,U+0BCD,U+0B95,U+0BAA,U+0BCD,U+0BAA,U+0B9F,U+0BCD,U+0B9F,U+0BC1:[tgm_e=0+1702|tgc_ta=0+1598|tgm_aa=0+1149|tgc_ku=2+1962|tgc_k=4+1592|tgc_ka=6+1592|tgc_p=7+1370|tgc_pa=9+1370|tgc_tt=10+1596|tgc_ttu=12+1833]
+/System/Library/Fonts/Times.dfont@39c954614d3f3317b28564db06d5b7b7a6ff0e39:--font-funcs ot:U+0041,U+0066,U+0300,U+0066,U+0069,U+005A:[A=0+1479|f=1+682|gravecmb=1@-480,588+0|fi=3+1139|Z=5+1251]
+/System/Library/Fonts/LucidaGrande.ttc@d89a9d7e57767bfe3b5a4cfd22bb1e9dbe03a062:--font-funcs ot:U+05E1,U+05B0:[shevahebrew=0@-7,0+0|samekhhebrew=0+1361]
+/Library/Fonts/Apple Chancery.ttf@5fc49ae9bce39e2105864323183b68ea34c9e562:--font-funcs ot:U+0054,U+0068,U+0020,U+0074,U+0068,U+0020,U+006C,U+006C,U+0020,U+0074,U+0065,U+0020,U+0074,U+006F,U+0020,U+0074,U+0072,U+0020,U+0066,U+0072,U+0020,U+0066,U+0075,U+0020,U+0066,U+006A:[T_h=0+2308|space=2+569|t_h=3+1687|space=5+569|l_l=6+1108|space=8+569|t_e=9+1408|space=11+569|t_o=12+1531|space=14+569|t_r=15+1385|space=17+569|f_r=18+1432|space=20+569|f_u=21+1733|space=23+569|f_j=24+1098]
+/Library/Fonts/Apple Chancery.ttf@5fc49ae9bce39e2105864323183b68ea34c9e562:--font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[T=0+1497|e=1@-62,0+699|space=2+569|A=3+1431|V=4@-37,0+1377|space=5+569|T=6+1510|r=7@-50,0+803|space=8+569|V=9+1376|a=10@-37,0+1014|space=11+569|r=12+853|T=13+1560|space=14+569|e=15+761|T=16+1560|space=17+569|T=18+1515|d=19@-45,0+1006]
+/System/Library/Fonts/GeezaPro.ttc@f43ee7151c2e9f1dddfbc26cfc148609eb5c5820:--font-funcs ot:U+0627,U+0644,U+0623,U+064E,U+0628,U+0652,U+062C,U+064E,U+062F,U+0650,U+064A,U+064E,U+0651,U+0629,U+0640,U+0627,U+0644,U+0639,U+064E,U+0631,U+064E,U+0628,U+0650,U+064A,U+064E,U+0651,U+0629:[u0629.final.tehMarbuta=26+713|u064e_u0651.shaddaFatha=23@0,-200+0|u064a.medial.yeh=23+656|u0650.kasra=21@80,290+80|u0628.initial.beh=21@-80,0+576|u064e.fatha=19@200,-570+200|u0631.final.reh=19@-200,0+702|u064e.fatha=17@200,-200+200|u0639.medial.ain=17@-200,0+738|u0644.initial.lam=16+515|u0627.final.alef=15+647|u0640.tatweel=14+449|u0629.final.tehMarbuta=13+713|u064e_u0651.shaddaFatha=10@0,-200+0|u064a.initial.yeh=10+656|u0650.kasra=8@80,570+80|u062f.final.dal=8@-80,0+822|u064e.fatha=6@290,-160+290|u062c.medial.jeem=6@-290,0+1069|u0652.sukun=4@0,-200+0|u0628.initial.beh=4+656|u064e.fatha=1@-252,120+-252|u0644_u0623.isolated.lamHamzaOnAlef=1@120,0+1282|u0627.alef=0+647]
+/System/Library/Fonts/GeezaPro.ttc@f43ee7151c2e9f1dddfbc26cfc148609eb5c5820:--font-funcs ot:U+0628,U+064A,U+064E,U+0651,U+0629:[u0629.final.tehMarbuta=4+713|u064e_u0651.shaddaFatha=1@0,-200+0|u064a.medial.yeh=1+656|u0628.initial.beh=0+656]
+/System/Library/Fonts/GeezaPro.ttc@f43ee7151c2e9f1dddfbc26cfc148609eb5c5820:--font-funcs ot:U+0631,U+0628:[u0628.beh=1+1415|u0631.reh=0@-202,0+700]
+/System/Library/Fonts/GeezaPro.ttc@f43ee7151c2e9f1dddfbc26cfc148609eb5c5820:--font-funcs ot:U+0628,U+064F:[u064f.damma=0@250,-250+250|u0628.beh=0@-250,0+1165]
+/System/Library/Fonts/SFNSDisplay.ttf@92787c30716672737e9059bc367c15d04fbc1ced:--font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid225=0+1105|gid584=1@-105,0+979|gid3=2+490|gid4=3+1227|gid265=4@-65,0+1227|gid3=5+490|gid225=6+1130|gid728=7@-80,0+569|gid3=8+490|gid265=9+1227|gid505=10@-65,0+997|gid3=11+490|gid728=12+609|gid225=13@-40,0+1170|gid3=14+490|gid584=15+1004|gid225=16@-80,0+1130|gid3=17+490|gid225=18+1105|gid576=19@-105,0+1068]
+/System/Library/Fonts/SFNSDisplay.ttf@92787c30716672737e9059bc367c15d04fbc1ced:--font-ptem 9 --font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid225=0@46,0+1197|gid584=1@-59,0+1071|gid3=2@46,0+582|gid4=3@46,0+1319|gid265=4@-19,0+1319|gid3=5@46,0+582|gid225=6@46,0+1222|gid728=7@-34,0+661|gid3=8@46,0+582|gid265=9@46,0+1319|gid505=10@-19,0+1089|gid3=11@46,0+582|gid728=12@46,0+701|gid225=13@6,0+1262|gid3=14@46,0+582|gid584=15@46,0+1096|gid225=16@-34,0+1222|gid3=17@46,0+582|gid225=18@46,0+1197|gid576=19@-59,0+1160]
+/System/Library/Fonts/Apple Color Emoji.ttc@d2fe8a134483aa48a43a9d1e4b7204d37a4abdf5:--remove-default-ignorables --font-funcs ot:U+1F468,U+200D,U+1F469,U+200D,U+1F467,U+200D,U+1F466:[u1F46A.MWGB=0+800]
 
-# 10.13.6
-/System/Library/Fonts/Helvetica.ttc@8a928f9866299d2455f41360202b7a3b48503a5e:--shaper ot --font-funcs ot:U+006D,U+0300:[m=0+1706|gravecmb=0@-284,10+0]
-/System/Library/Fonts/LucidaGrande.ttc@63ba1b1de4709bd832ca76bd62368dd99fc34269:--shaper ot --font-funcs ot:U+006D,U+0300:[mgrave=0+1912]
-/System/Library/Fonts/Times.ttc@896098b6979306ad84355025459f7c68b029139c:--shaper ot --font-funcs ot:U+0066,U+0069:[fi=0+1139]
-/Library/Fonts/Khmer MN.ttc@782ba6cf3fca0512ab348dfe08345a2d5dc5bf2c:--shaper ot --font-funcs ot:U+17A2,U+1780,U+17D2,U+179F,U+179A,U+1781,U+17D2,U+1798,U+17C2,U+179A:[km_qa=0+1025|km_ka=1+1025|km_sa.sub=1+517|km_ro=4+593|km_vs_ae=5+605|km_kha=5+1025|km_mo.sub=5+0|km_ro=9+593]
-/Library/Fonts/Tamil MN.ttc@3de37f3f8f3cb6015b093fbd6e9d323daaf6fb1d:--shaper ot --font-funcs ot:U+0BA4,U+0BCA,U+0B95,U+0BC1,U+0B95,U+0BCD,U+0B95,U+0BAA,U+0BCD,U+0BAA,U+0B9F,U+0BCD,U+0B9F,U+0BC1:[tgm_e=0+1702|tgc_ta=0+1598|tgm_aa=0+1149|tgc_ku=2+1962|tgc_k=4+1592|tgc_ka=6+1592|tgc_p=7+1370|tgc_pa=9+1370|tgc_tt=10+1596|tgc_ttu=12+1833]
-/System/Library/Fonts/Times.ttc@896098b6979306ad84355025459f7c68b029139c:--shaper ot --font-funcs ot:U+0041,U+0066,U+0300,U+0066,U+0069,U+005A:[A=0+1479|f=1+682|gravecmb=1@-480,588+0|fi=3+1139|Z=5+1251]
-/System/Library/Fonts/LucidaGrande.ttc@63ba1b1de4709bd832ca76bd62368dd99fc34269:--shaper ot --font-funcs ot:U+05E1,U+05B0:[shevahebrew=0@-7,0+0|samekhhebrew=0+1361]
-/Library/Fonts/Apple Chancery.ttf@4ec49cba0d4e68d025ada0498c4df1b2f9fd57ac:--shaper ot --font-funcs ot:U+0054,U+0068,U+0020,U+0074,U+0068,U+0020,U+006C,U+006C,U+0020,U+0074,U+0065,U+0020,U+0074,U+006F,U+0020,U+0074,U+0072,U+0020,U+0066,U+0072,U+0020,U+0066,U+0075,U+0020,U+0066,U+006A:[T_h=0+2308|space=2+569|t_h=3+1687|space=5+569|l_l=6+1108|space=8+569|t_e=9+1408|space=11+569|t_o=12+1531|space=14+569|t_r=15+1385|space=17+569|f_r=18+1432|space=20+569|f_u=21+1733|space=23+569|f_j=24+1098]
-/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--shaper ot --font-funcs ot:U+0627,U+0644,U+0623,U+064E,U+0628,U+0652,U+062C,U+064E,U+062F,U+0650,U+064A,U+064E,U+0651,U+0629,U+0640,U+0627,U+0644,U+0639,U+064E,U+0631,U+064E,U+0628,U+0650,U+064A,U+064E,U+0651,U+0629:[u0629.final.tehMarbuta=26+713|u064e_u0651.shaddaFatha=23@0,-200+0|u064a.medial.yeh=23+656|u0650.kasra=21@80,290+80|u0628.initial.beh=21@-80,0+576|u064e.fatha=19@200,-570+200|u0631.final.reh=19@-200,0+702|u064e.fatha=17@200,-200+200|u0639.medial.ain=17@-200,0+738|u0644.initial.lam=16+515|u0627.final.alef=15+647|u0640.tatweel=14+449|u0629.final.tehMarbuta=13+713|u064e_u0651.shaddaFatha=10@0,-200+0|u064a.initial.yeh=10+656|u0650.kasra=8@80,570+80|u062f.final.dal=8@-80,0+822|u064e.fatha=6@290,-160+290|u062c.medial.jeem=6@-290,0+1069|u0652.sukun=4@0,-200+0|u0628.initial.beh=4+656|u064e.fatha=1@-252,120+-252|u0644_u0623.isolated.lamHamzaOnAlef=1@120,0+1282|u0627.alef=0+647]
-/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--shaper ot --font-funcs ot:U+0628,U+064A,U+064E,U+0651,U+0629:[u0629.final.tehMarbuta=4+713|u064e_u0651.shaddaFatha=1@0,-200+0|u064a.medial.yeh=1+656|u0628.initial.beh=0+656]
-/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--shaper ot --font-funcs ot:U+0631,U+0628:[u0628.beh=1+1415|u0631.reh=0@-202,0+700]
-/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--shaper ot --font-funcs ot:U+0628,U+064F:[u064f.damma=0@250,-250+250|u0628.beh=0@-250,0+1165]
-/System/Library/Fonts/SFNSDisplay.ttf@c8948f464ff822a5f9bbf2e12d0e4e32268815aa:--shaper ot --font-funcs ot:U+0056,U+0041,U+0056,U+0041:[gid332=0+1227|gid4=1@-65,0+1162|gid332=2@-65,0+1162|gid4=3@-65,0+1227]
-/System/Library/Fonts/Apple Color Emoji.ttc@2e09b1f3d42c3821cc6c4ac5b6ce16237ab0d496:--remove-default-ignorables --shaper ot --font-funcs ot:U+1F468,U+200D,U+1F469,U+200D,U+1F467,U+200D,U+1F466:[u1F46A.MWGB=0+800]
+# 10.13.6 https://gist.github.com/ebraminio/d432e831b3f7ebe30245dde5775e1c7e
+/System/Library/Fonts/Helvetica.ttc@8a928f9866299d2455f41360202b7a3b48503a5e:--font-funcs ot:U+006D,U+0300:[m=0+1706|gravecmb=0@-284,10+0]
+/System/Library/Fonts/LucidaGrande.ttc@63ba1b1de4709bd832ca76bd62368dd99fc34269:--font-funcs ot:U+006D,U+0300:[mgrave=0+1912]
+/System/Library/Fonts/Times.ttc@896098b6979306ad84355025459f7c68b029139c:--font-funcs ot:U+0066,U+0069:[fi=0+1139]
+/Library/Fonts/Khmer MN.ttc@782ba6cf3fca0512ab348dfe08345a2d5dc5bf2c:--font-funcs ot:U+17A2,U+1780,U+17D2,U+179F,U+179A,U+1781,U+17D2,U+1798,U+17C2,U+179A:[km_qa=0+1025|km_ka=1+1025|km_sa.sub=1+517|km_ro=4+593|km_vs_ae=5+605|km_kha=5+1025|km_mo.sub=5+0|km_ro=9+593]
+/Library/Fonts/Tamil MN.ttc@3de37f3f8f3cb6015b093fbd6e9d323daaf6fb1d:--font-funcs ot:U+0BA4,U+0BCA,U+0B95,U+0BC1,U+0B95,U+0BCD,U+0B95,U+0BAA,U+0BCD,U+0BAA,U+0B9F,U+0BCD,U+0B9F,U+0BC1:[tgm_e=0+1702|tgc_ta=0+1598|tgm_aa=0+1149|tgc_ku=2+1962|tgc_k=4+1592|tgc_ka=6+1592|tgc_p=7+1370|tgc_pa=9+1370|tgc_tt=10+1596|tgc_ttu=12+1833]
+/System/Library/Fonts/Times.ttc@896098b6979306ad84355025459f7c68b029139c:--font-funcs ot:U+0041,U+0066,U+0300,U+0066,U+0069,U+005A:[A=0+1479|f=1+682|gravecmb=1@-480,588+0|fi=3+1139|Z=5+1251]
+/System/Library/Fonts/LucidaGrande.ttc@63ba1b1de4709bd832ca76bd62368dd99fc34269:--font-funcs ot:U+05E1,U+05B0:[shevahebrew=0@-7,0+0|samekhhebrew=0+1361]
+/Library/Fonts/Apple Chancery.ttf@4ec49cba0d4e68d025ada0498c4df1b2f9fd57ac:--font-funcs ot:U+0054,U+0068,U+0020,U+0074,U+0068,U+0020,U+006C,U+006C,U+0020,U+0074,U+0065,U+0020,U+0074,U+006F,U+0020,U+0074,U+0072,U+0020,U+0066,U+0072,U+0020,U+0066,U+0075,U+0020,U+0066,U+006A:[T_h=0+2308|space=2+569|t_h=3+1687|space=5+569|l_l=6+1108|space=8+569|t_e=9+1408|space=11+569|t_o=12+1531|space=14+569|t_r=15+1385|space=17+569|f_r=18+1432|space=20+569|f_u=21+1733|space=23+569|f_j=24+1098]
+/Library/Fonts/Apple Chancery.ttf@4ec49cba0d4e68d025ada0498c4df1b2f9fd57ac:--font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[T=0+1497|e=1@-62,0+699|space=2+569|A=3+1431|V=4@-37,0+1377|space=5+569|T=6+1510|r=7@-50,0+803|space=8+569|V=9+1376|a=10@-37,0+1014|space=11+569|r=12+853|T=13+1560|space=14+569|e=15+761|T=16+1560|space=17+569|T=18+1515|d=19@-45,0+1006]
+/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--font-funcs ot:U+0627,U+0644,U+0623,U+064E,U+0628,U+0652,U+062C,U+064E,U+062F,U+0650,U+064A,U+064E,U+0651,U+0629,U+0640,U+0627,U+0644,U+0639,U+064E,U+0631,U+064E,U+0628,U+0650,U+064A,U+064E,U+0651,U+0629:[u0629.final.tehMarbuta=26+713|u064e_u0651.shaddaFatha=23@0,-200+0|u064a.medial.yeh=23+656|u0650.kasra=21@80,290+80|u0628.initial.beh=21@-80,0+576|u064e.fatha=19@200,-570+200|u0631.final.reh=19@-200,0+702|u064e.fatha=17@200,-200+200|u0639.medial.ain=17@-200,0+738|u0644.initial.lam=16+515|u0627.final.alef=15+647|u0640.tatweel=14+449|u0629.final.tehMarbuta=13+713|u064e_u0651.shaddaFatha=10@0,-200+0|u064a.initial.yeh=10+656|u0650.kasra=8@80,570+80|u062f.final.dal=8@-80,0+822|u064e.fatha=6@290,-160+290|u062c.medial.jeem=6@-290,0+1069|u0652.sukun=4@0,-200+0|u0628.initial.beh=4+656|u064e.fatha=1@-252,120+-252|u0644_u0623.isolated.lamHamzaOnAlef=1@120,0+1282|u0627.alef=0+647]
+/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--font-funcs ot:U+0628,U+064A,U+064E,U+0651,U+0629:[u0629.final.tehMarbuta=4+713|u064e_u0651.shaddaFatha=1@0,-200+0|u064a.medial.yeh=1+656|u0628.initial.beh=0+656]
+/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--font-funcs ot:U+0631,U+0628:[u0628.beh=1+1415|u0631.reh=0@-202,0+700]
+/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--font-funcs ot:U+0628,U+064F:[u064f.damma=0@250,-250+250|u0628.beh=0@-250,0+1165]
+/System/Library/Fonts/SFNSDisplay.ttf@c8948f464ff822a5f9bbf2e12d0e4e32268815aa:--font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid282=0+1055|gid658=1@-135,0+914|gid3=2+420|gid4=3+1227|gid332=4@-65,0+1227|gid3=5+420|gid282=6+1075|gid813=7@-115,0+516|gid3=8+420|gid332=9+1217|gid572=10@-75,0+953|gid3=11+420|gid813=12+546|gid282=13@-85,0+1105|gid3=14+420|gid658=15+914|gid282=16@-135,0+1055|gid3=17+420|gid282=18+1055|gid649=19@-135,0+999]
+/System/Library/Fonts/SFNSDisplay.ttf@c8948f464ff822a5f9bbf2e12d0e4e32268815aa:--font-ptem 9 --font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid282=0@46,0+1147|gid658=1@-89,0+1006|gid3=2@46,0+512|gid4=3@46,0+1319|gid332=4@-19,0+1319|gid3=5@46,0+512|gid282=6@46,0+1167|gid813=7@-69,0+608|gid3=8@46,0+512|gid332=9@46,0+1309|gid572=10@-29,0+1045|gid3=11@46,0+512|gid813=12@46,0+638|gid282=13@-39,0+1197|gid3=14@46,0+512|gid658=15@46,0+1006|gid282=16@-89,0+1147|gid3=17@46,0+512|gid282=18@46,0+1147|gid649=19@-89,0+1091]
+/System/Library/Fonts/Apple Color Emoji.ttc@2e09b1f3d42c3821cc6c4ac5b6ce16237ab0d496:--remove-default-ignorables --font-funcs ot:U+1F468,U+200D,U+1F469,U+200D,U+1F467,U+200D,U+1F466:[u1F46A.MWGB=0+800]
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestGVAR-Composite-0.ttf b/test/shaping/data/text-rendering-tests/fonts/TestGVAR-Composite-0.ttf
new file mode 100644
index 0000000..07e6882
--- /dev/null
+++ b/test/shaping/data/text-rendering-tests/fonts/TestGVAR-Composite-0.ttf
Binary files differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestGVAR-Composite-Missing.ttf b/test/shaping/data/text-rendering-tests/fonts/TestGVAR-Composite-Missing.ttf
new file mode 100644
index 0000000..58dd961
--- /dev/null
+++ b/test/shaping/data/text-rendering-tests/fonts/TestGVAR-Composite-Missing.ttf
Binary files differ