Bug 1422898 - Update Harfbuzz to 1.7.2. r=jfkthame
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 05 Dec 2017 07:44:54 -0500
changeset 395090 d5e064a4bca13180d70734ac83543c3a29b47a4f
parent 395089 e56181d42ce2da739b668c33cd92622b5c4fa6f8
child 395091 bff73e215867998059245be66d70c404af4174ff
push id33030
push usercsabou@mozilla.com
push dateTue, 05 Dec 2017 22:09:20 +0000
treeherdermozilla-central@a426845468e7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1422898
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1422898 - Update Harfbuzz to 1.7.2. r=jfkthame
gfx/harfbuzz/NEWS
gfx/harfbuzz/README
gfx/harfbuzz/README-mozilla
gfx/harfbuzz/configure.ac
gfx/harfbuzz/harfbuzz.doap
gfx/harfbuzz/src/Makefile.am
gfx/harfbuzz/src/gen-use-table.py
gfx/harfbuzz/src/harfbuzz-icu.pc
gfx/harfbuzz/src/harfbuzz.pc
gfx/harfbuzz/src/hb-buffer-private.hh
gfx/harfbuzz/src/hb-buffer.cc
gfx/harfbuzz/src/hb-coretext.cc
gfx/harfbuzz/src/hb-coretext.h
gfx/harfbuzz/src/hb-debug.hh
gfx/harfbuzz/src/hb-open-file-private.hh
gfx/harfbuzz/src/hb-open-type-private.hh
gfx/harfbuzz/src/hb-ot-cbdt-table.hh
gfx/harfbuzz/src/hb-ot-cmap-table.hh
gfx/harfbuzz/src/hb-ot-font.cc
gfx/harfbuzz/src/hb-ot-glyf-table.hh
gfx/harfbuzz/src/hb-ot-head-table.hh
gfx/harfbuzz/src/hb-ot-hhea-table.hh
gfx/harfbuzz/src/hb-ot-hmtx-table.hh
gfx/harfbuzz/src/hb-ot-kern-table.hh
gfx/harfbuzz/src/hb-ot-layout-common-private.hh
gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh
gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
gfx/harfbuzz/src/hb-ot-layout-private.hh
gfx/harfbuzz/src/hb-ot-layout.cc
gfx/harfbuzz/src/hb-ot-math-table.hh
gfx/harfbuzz/src/hb-ot-maxp-table.hh
gfx/harfbuzz/src/hb-ot-name-table.hh
gfx/harfbuzz/src/hb-ot-os2-table.hh
gfx/harfbuzz/src/hb-ot-post-table.hh
gfx/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh
gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc
gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh
gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc
gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl
gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc
gfx/harfbuzz/src/hb-ot-shape-fallback.cc
gfx/harfbuzz/src/hb-ot-shape.cc
gfx/harfbuzz/src/hb-ot-var-avar-table.hh
gfx/harfbuzz/src/hb-ot-var-fvar-table.hh
gfx/harfbuzz/src/hb-ot-var-hvar-table.hh
gfx/harfbuzz/src/hb-ot-var-mvar-table.hh
gfx/harfbuzz/src/hb-private.hh
gfx/harfbuzz/src/hb-set-private.hh
gfx/harfbuzz/src/hb-string-array.hh
gfx/harfbuzz/src/hb-unicode-private.hh
gfx/harfbuzz/src/hb-version.h
gfx/harfbuzz/src/main.cc
gfx/harfbuzz/src/sample.py
--- a/gfx/harfbuzz/NEWS
+++ b/gfx/harfbuzz/NEWS
@@ -1,8 +1,18 @@
+Overview of changes leading to 1.7.2
+Monday, December 4, 2017
+====================================
+
+- Optimize hb_set_add_range().
+- Misc fixes.
+- New API:
+hb_coretext_font_create()
+
+
 Overview of changes leading to 1.7.1
 Tuesday, November 14, 2017
 ====================================
 
 - Fix atexit object destruction regression.
 - Fix minor integer-overflow.
 
 
@@ -28,26 +38,26 @@ Thursday, October 26th, 2017
 
 
 Overview of changes leading to 1.6.2
 Monday, October 23nd, 2017
 ====================================
 
 - Yesterday's release had a bad crasher; don't use it.  That's what
   happens when one works on Sunday...
-  https://github.com/behdad/harfbuzz/issues/578
+  https://github.com/harfbuzz/harfbuzz/issues/578
 - Build fixes for FreeBSD and Chrome Android.
 
 
 Overview of changes leading to 1.6.1
 Sunday, October 22nd, 2017
 ====================================
 
 - Don't skip over COMBINING GRAPHEME JOINER when ligating, etc.
-  To be refined: https://github.com/behdad/harfbuzz/issues/554
+  To be refined: https://github.com/harfbuzz/harfbuzz/issues/554
 - Faster hb_set_t implementation.
 - Don't use deprecated ICU API.
 - Fix undefined-behavior in Myanmar shaper, introduced in 1.6.0
 - Deprecated API:
   hb_set_invert()
 
 
 Overview of changes leading to 1.6.0
@@ -438,34 +448,34 @@ Overview of changes leading to 1.2.1
 Tuesday, February 23, 2016
 ====================================
 
 - CoreText: Fix bug with wrong scale if font scale was changed later.
   https://github.com/libass/libass/issues/212
 - CoreText: Drastically speed up font initialization.
 - CoreText: Fix tiny leak.
 - Group ZWJ/ZWNJ with previous syllable under cluster-level=0.
-  https://github.com/behdad/harfbuzz/issues/217
+  https://github.com/harfbuzz/harfbuzz/issues/217
 - Add test/shaping/README.md about how to add tests to the suite.
 
 
 Overview of changes leading to 1.2.0
 Friday, February 19, 2016
 ====================================
 
 - Fix various issues (hangs mostly) in case of memory allocation failure.
 - Change mark zeroing types of most shapers from BY_UNICODE_LATE to
   BY_GDEF_LATE.  This seems to be what Uniscribe does.
 - Change mark zeroing of USE shaper from NONE to BY_GDEF_EARLY.  That's
   what Windows does.
 - Allow GPOS cursive connection on marks, and fix the interaction with
   mark attachment.  This work resulted in some changes to how mark
   attachments work.  See:
-  https://github.com/behdad/harfbuzz/issues/211
-  https://github.com/behdad/harfbuzz/commit/86c68c7a2c971efe8e35b1f1bd99401dc8b688d2
+  https://github.com/harfbuzz/harfbuzz/issues/211
+  https://github.com/harfbuzz/harfbuzz/commit/86c68c7a2c971efe8e35b1f1bd99401dc8b688d2
 - Graphite2 shaper: improved negative advance handling (eg. Nastaliq).
 - Add nmake-based build system for Windows.
 - Minor speedup.
 - Misc. improvements.
 
 
 Overview of changes leading to 1.1.3
 Monday, January 11, 2016
@@ -496,17 +506,17 @@ Monday, January 11, 2016
     Actual message protocol to be fleshed out later.
 
 
 Overview of changes leading to 1.1.2
 Wednesday, November 26, 2015
 ====================================
 
 - Fix badly-broken fallback shaper that affected terminology.
-  https://github.com/behdad/harfbuzz/issues/187
+  https://github.com/harfbuzz/harfbuzz/issues/187
 - Fix y_scaling in Graphite shaper.
 - API changes:
   * An unset glyph_h_origin() function in font-funcs now (sensibly)
     implies horizontal origin at 0,0.  Ie, the nil callback returns
     true instead of false.  As such, implementations that have a
     glyph_h_origin() that simply returns true, can remove that function
     with HarfBuzz >= 1.1.2.  This results in a tiny speedup.
 
@@ -518,21 +528,21 @@ Wednesday, November 24, 2015
 - Build fixes, specially for hb-coretext.
 
 
 Overview of changes leading to 1.1.0
 Wednesday, November 18, 2015
 ====================================
 
 - Implement 'stch' stretch feature for Syriac Abbreviation Mark.
-  https://github.com/behdad/harfbuzz/issues/141
+  https://github.com/harfbuzz/harfbuzz/issues/141
 - Disable use of decompose_compatibility() callback.
 - Implement "shaping" of various Unicode space characters, even
   if the font does not support them.
-  https://github.com/behdad/harfbuzz/issues/153
+  https://github.com/harfbuzz/harfbuzz/issues/153
 - If font does not support U+2011 NO-BREAK HYPHEN, fallback to
   U+2010 HYPHEN.
 - Changes resulting from libFuzzer continuous fuzzing:
   * Reject font tables that need more than 8 edits,
   * Bound buffer growth during shaping to 32x,
   * Fix assertions and other issues at OOM / buffer max-growth.
 - Misc fixes and optimizations.
 - API changes:
@@ -545,25 +555,25 @@ Thursday, October 15, 2015
 ====================================
 
 - Reduce max nesting level in OT lookups from 8 to 6.
   Should not affect any real font as far as I know.
 - Fix memory access issue in ot-font.
 - Revert default load-flags of fonts created using hb_ft_font_create()
   back to FT_LOAD_DEFAULT|FT_LOAD_NO_HINTING.  This was changed in
   last release (1.0.5), but caused major issues, so revert.
-  https://github.com/behdad/harfbuzz/issues/143
+  https://github.com/harfbuzz/harfbuzz/issues/143
 
 
 Overview of changes leading to 1.0.5
 Tuesday, October 13, 2015
 ====================================
 
 - Fix multiple memory access bugs discovered using libFuzzer.
-  https://github.com/behdad/harfbuzz/issues/139
+  https://github.com/harfbuzz/harfbuzz/issues/139
   Everyone should upgrade to this version as soon as possible.
   We now have continuous fuzzing set up, to avoid issues like
   these creeping in again.
 - Misc fixes.
 
 - New API:
   * hb_font_set_parent().
   * hb_ft_font_[sg]et_load_flags()
--- a/gfx/harfbuzz/README
+++ b/gfx/harfbuzz/README
@@ -1,13 +1,15 @@
-[![Build Status](https://travis-ci.org/behdad/harfbuzz.svg)](https://travis-ci.org/behdad/harfbuzz)
-[![Build Status](https://ci.appveyor.com/api/projects/status/4oaq58ns2h0m2soa?svg=true)](https://ci.appveyor.com/project/behdad/harfbuzz)
-[![CircleCI](https://circleci.com/gh/behdad/harfbuzz.svg?style=svg)](https://circleci.com/gh/behdad/harfbuzz)
-[![Coverage Status](https://img.shields.io/coveralls/behdad/harfbuzz.svg)](https://coveralls.io/r/behdad/harfbuzz)
+[![Build Status](https://travis-ci.org/harfbuzz/harfbuzz.svg)](https://travis-ci.org/harfbuzz/harfbuzz)
+[![Build Status](https://ci.appveyor.com/api/projects/status/4oaq58ns2h0m2soa?svg=true)](https://ci.appveyor.com/project/harfbuzz/harfbuzz)
+[![CircleCI](https://circleci.com/gh/harfbuzz/harfbuzz.svg?style=svg)](https://circleci.com/gh/harfbuzz/harfbuzz)
+[![Coverage Status](https://img.shields.io/coveralls/harfbuzz/harfbuzz.svg)](https://coveralls.io/r/harfbuzz/harfbuzz)
 [ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
 
 This is HarfBuzz, a text shaping library.
 
 For bug reports, mailing list, and other information please visit:
 
   http://harfbuzz.org/
 
 For license information, see the file COPYING.
+
+Documentation: https://harfbuzz.github.io
--- a/gfx/harfbuzz/README-mozilla
+++ b/gfx/harfbuzz/README-mozilla
@@ -1,14 +1,14 @@
-gfx/harfbuzz status as of 2017-11-14:
+gfx/harfbuzz status as of 2017-12-04:
 
 This directory contains the HarfBuzz source from the 'master' branch of
 https://github.com/behdad/harfbuzz.
 
-Current version: 1.7.1
+Current version: 1.7.2
 
 UPDATING:
 
 Note that gfx/harfbuzz/src/hb-version.h is not present in the upstream Git
 repository. It is created at build time by the HarfBuzz build system;
 but as we don't use that build system in mozilla, it is necessary to refresh
 this file when updating HarfBuzz, and check it into the mozilla tree.
 
--- a/gfx/harfbuzz/configure.ac
+++ b/gfx/harfbuzz/configure.ac
@@ -1,12 +1,12 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [1.7.1],
-        [https://github.com/behdad/harfbuzz/issues/new],
+        [1.7.2],
+        [https://github.com/harfbuzz/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
 
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
 AC_CONFIG_HEADERS([config.h])
 
 AM_INIT_AUTOMAKE([1.11.1 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability])
--- a/gfx/harfbuzz/harfbuzz.doap
+++ b/gfx/harfbuzz/harfbuzz.doap
@@ -8,17 +8,17 @@
 
   <homepage
   rdf:resource="http://harfbuzz.org/" />
   <mailing-list
   rdf:resource="http://lists.freedesktop.org/mailman/listinfo/harfbuzz" />
   <!--download-page
   rdf:resource=""/-->
   <bug-database
-  rdf:resource="https://github.com/behdad/harfbuzz/issues" />
+  rdf:resource="https://github.com/harfbuzz/harfbuzz/issues" />
 
   <maintainer>
     <foaf:Person>
       <foaf:name>Behdad Esfahbod</foaf:name>
       <foaf:mbox rdf:resource="mailto:harfbuzz@behdad.org" />
     </foaf:Person>
   </maintainer>
 </Project>
--- a/gfx/harfbuzz/src/Makefile.am
+++ b/gfx/harfbuzz/src/Makefile.am
@@ -94,16 +94,19 @@ HBSOURCES += $(HB_CORETEXT_sources)
 HBHEADERS += $(HB_CORETEXT_headers)
 endif
 
 if HAVE_UCDN
 SUBDIRS += hb-ucdn
 HBCFLAGS += -I$(srcdir)/hb-ucdn
 HBLIBS   += hb-ucdn/libhb-ucdn.la
 HBSOURCES += $(HB_UCDN_sources)
+hb-ucdn/libhb-ucdn.la: ucdn
+ucdn:
+	@$(MAKE) $(AM_MAKEFLAGS) -C hb-ucdn
 endif
 DIST_SUBDIRS += hb-ucdn
 
 
 # Put the library together
 
 HBLIBS += $(HBNONPCLIBS)
 
@@ -130,19 +133,22 @@ nodist_pkginclude_HEADERS = $(HBNODISTHE
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = harfbuzz.pc
 EXTRA_DIST += harfbuzz.pc.in
 
 FUZZING_CPPFLAGS= \
 	-DHB_NDEBUG \
 	-DHB_MAX_NESTING_LEVEL=3 \
 	-DHB_SANITIZE_MAX_EDITS=3 \
-	-DHB_BUFFER_MAX_EXPANSION_FACTOR=3 \
+	-DHB_BUFFER_MAX_LEN_FACTOR=3 \
 	-DHB_BUFFER_MAX_LEN_MIN=8 \
 	-DHB_BUFFER_MAX_LEN_DEFAULT=128 \
+	-DHB_BUFFER_MAX_OPS_FACTOR=8 \
+	-DHB_BUFFER_MAX_OPS_MIN=64 \
+	-DHB_BUFFER_MAX_OPS_DEFAULT=1024 \
 	$(NULL)
 EXTRA_LTLIBRARIES = libharfbuzz-fuzzing.la
 libharfbuzz_fuzzing_la_LINK = $(libharfbuzz_la_LINK)
 libharfbuzz_fuzzing_la_SOURCES = $(libharfbuzz_la_SOURCES)
 libharfbuzz_fuzzing_la_CPPFLAGS = $(libharfbuzz_la_CPPFLAGS) $(FUZZING_CPPFLAGS)
 libharfbuzz_fuzzing_la_LDFLAGS = $(libharfbuzz_la_LDFLAGS)
 libharfbuzz_fuzzing_la_LIBADD = $(libharfbuzz_la_LIBADD)
 EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_la_DEPENDENCIES)
--- a/gfx/harfbuzz/src/gen-use-table.py
+++ b/gfx/harfbuzz/src/gen-use-table.py
@@ -39,16 +39,17 @@ for i, f in enumerate (files):
 			data[i][u] = t
 		values[i][t] = values[i].get (t, 0) + end - start + 1
 
 defaults = ('Other', 'Not_Applicable', 'Cn', 'No_Block')
 
 # TODO Characters that are not in Unicode Indic files, but used in USE
 data[0][0x034F] = defaults[0]
 data[0][0x2060] = defaults[0]
+data[0][0x20F0] = defaults[0]
 for u in range (0xFE00, 0xFE0F + 1):
 	data[0][u] = defaults[0]
 
 # Merge data into one dict:
 for i,v in enumerate (defaults):
 	values[i][v] = values[i].get (v, 0) + 1
 combined = {}
 for i,d in enumerate (data):
@@ -295,19 +296,25 @@ def map_to_use(data):
 		# have UIPC
 		if U == 0x17DD: UISC = Vowel_Dependent
 		if 0x1CE2 <= U <= 0x1CE8: UISC = Cantillation_Mark
 
 		# TODO: U+1CED should only be allowed after some of
 		# the nasalization marks, maybe only for U+1CE9..U+1CF1.
 		if U == 0x1CED: UISC = Tone_Mark
 
-		# TODO: https://github.com/behdad/harfbuzz/issues/525
+		# TODO: https://github.com/harfbuzz/harfbuzz/issues/525
 		if U == 0x1A7F: UISC = Consonant_Final; UIPC = Bottom
 
+		# TODO: https://github.com/harfbuzz/harfbuzz/pull/609
+		if U == 0x20F0: UISC = Cantillation_Mark; UIPC = Top
+
+		# TODO: https://github.com/harfbuzz/harfbuzz/pull/626
+		if U == 0xA8B4: UISC = Consonant_Medial
+
 		values = [k for k,v in items if v(U,UISC,UGC)]
 		assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values)
 		USE = values[0]
 
 		# Resolve Indic_Positional_Category
 
 		# TODO: Not in Unicode 8.0 yet, but in spec.
 		if U == 0x1B6C: UIPC = Bottom
--- a/gfx/harfbuzz/src/harfbuzz-icu.pc
+++ b/gfx/harfbuzz/src/harfbuzz-icu.pc
@@ -1,13 +1,13 @@
 prefix=/usr/local
 exec_prefix=/usr/local
 libdir=/usr/local/lib
 includedir=/usr/local/include
 
 Name: harfbuzz
 Description: HarfBuzz text shaping library ICU integration
-Version: 1.7.1
+Version: 1.7.2
 
 Requires: harfbuzz
 Requires.private: icu-uc
 Libs: -L${libdir} -lharfbuzz-icu
 Cflags: -I${includedir}/harfbuzz
--- a/gfx/harfbuzz/src/harfbuzz.pc
+++ b/gfx/harfbuzz/src/harfbuzz.pc
@@ -1,13 +1,13 @@
 prefix=/usr/local
 exec_prefix=/usr/local
 libdir=/usr/local/lib
 includedir=/usr/local/include
 
 Name: harfbuzz
 Description: HarfBuzz text shaping library
-Version: 1.7.1
+Version: 1.7.2
 
 Libs: -L${libdir} -lharfbuzz
 Libs.private: -lm    
 Requires.private: glib-2.0 >= 2.19.1 
 Cflags: -I${includedir}/harfbuzz
--- a/gfx/harfbuzz/src/hb-buffer-private.hh
+++ b/gfx/harfbuzz/src/hb-buffer-private.hh
@@ -30,26 +30,36 @@
 #ifndef HB_BUFFER_PRIVATE_HH
 #define HB_BUFFER_PRIVATE_HH
 
 #include "hb-private.hh"
 #include "hb-object-private.hh"
 #include "hb-unicode-private.hh"
 
 
-#ifndef HB_BUFFER_MAX_EXPANSION_FACTOR
-#define HB_BUFFER_MAX_EXPANSION_FACTOR 32
+#ifndef HB_BUFFER_MAX_LEN_FACTOR
+#define HB_BUFFER_MAX_LEN_FACTOR 32
 #endif
 #ifndef HB_BUFFER_MAX_LEN_MIN
 #define HB_BUFFER_MAX_LEN_MIN 8192
 #endif
 #ifndef HB_BUFFER_MAX_LEN_DEFAULT
 #define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
 #endif
 
+#ifndef HB_BUFFER_MAX_OPS_FACTOR
+#define HB_BUFFER_MAX_OPS_FACTOR 64
+#endif
+#ifndef HB_BUFFER_MAX_OPS_MIN
+#define HB_BUFFER_MAX_OPS_MIN 1024
+#endif
+#ifndef HB_BUFFER_MAX_OPS_DEFAULT
+#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */
+#endif
+
 static_assert ((sizeof (hb_glyph_info_t) == 20), "");
 static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
 
 HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
 HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
 HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
 
 enum hb_buffer_scratch_flags_t {
@@ -79,16 +89,17 @@ struct hb_buffer_t {
 
   /* Information about how the text in the buffer should be treated */
   hb_unicode_funcs_t *unicode; /* Unicode functions */
   hb_buffer_flags_t flags; /* BOT / EOT / etc. */
   hb_buffer_cluster_level_t cluster_level;
   hb_codepoint_t replacement; /* U+FFFD or something else. */
   hb_buffer_scratch_flags_t scratch_flags; /* Have space-flallback, etc. */
   unsigned int max_len; /* Maximum allowed len. */
+  int max_ops; /* Maximum allowed operations. */
 
   /* Buffer contents */
   hb_buffer_content_type_t content_type;
   hb_segment_properties_t props; /* Script, language, direction */
 
   bool in_error; /* Allocation failed */
   bool have_output; /* Whether we have an output buffer going on */
   bool have_positions; /* Whether we have positions */
@@ -97,27 +108,16 @@ struct hb_buffer_t {
   unsigned int len; /* Length of ->info and ->pos arrays */
   unsigned int out_len; /* Length of ->out array if have_output */
 
   unsigned int allocated; /* Length of allocated arrays */
   hb_glyph_info_t     *info;
   hb_glyph_info_t     *out_info;
   hb_glyph_position_t *pos;
 
-  inline hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
-  inline hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
-
-  inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
-  inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
-
-  inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; }
-  inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; }
-
-  inline bool has_separate_output (void) const { return info != out_info; }
-
   unsigned int serial;
 
   /* Text before / after the main buffer contents.
    * Always in Unicode, and ordered outward.
    * Index 0 is for "pre-context", 1 for "post-context". */
   static const unsigned int CONTEXT_LENGTH = 5;
   hb_codepoint_t context[2][CONTEXT_LENGTH];
   unsigned int context_len[2];
@@ -127,16 +127,20 @@ struct hb_buffer_t {
   void *message_data;
   hb_destroy_func_t message_destroy;
 
   /* Internal debugging. */
   /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
 #ifndef HB_NDEBUG
   uint8_t allocated_var_bits;
 #endif
+
+
+  /* Methods */
+
   inline void allocate_var (unsigned int start, unsigned int count)
   {
 #ifndef HB_NDEBUG
     unsigned int end = start + count;
     assert (end <= 8);
     unsigned int bits = (1u<<end) - (1u<<start);
     assert (0 == (allocated_var_bits & bits));
     allocated_var_bits |= bits;
@@ -163,18 +167,27 @@ struct hb_buffer_t {
   }
   inline void deallocate_var_all (void)
   {
 #ifndef HB_NDEBUG
     allocated_var_bits = 0;
 #endif
   }
 
+  inline hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
+  inline hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
 
-  /* Methods */
+  inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
+  inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
+
+  inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; }
+  inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; }
+
+  inline bool has_separate_output (void) const { return info != out_info; }
+
 
   HB_INTERNAL void reset (void);
   HB_INTERNAL void clear (void);
 
   inline unsigned int backtrack_len (void) const
   { return have_output? out_len : idx; }
   inline unsigned int lookahead_len (void) const
   { return len - idx; }
--- a/gfx/harfbuzz/src/hb-buffer.cc
+++ b/gfx/harfbuzz/src/hb-buffer.cc
@@ -717,16 +717,17 @@ hb_buffer_t *
 hb_buffer_create (void)
 {
   hb_buffer_t *buffer;
 
   if (!(buffer = hb_object_create<hb_buffer_t> ()))
     return hb_buffer_get_empty ();
 
   buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
+  buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
 
   buffer->reset ();
 
   return buffer;
 }
 
 /**
  * hb_buffer_get_empty:
@@ -744,16 +745,17 @@ hb_buffer_get_empty (void)
     HB_OBJECT_HEADER_STATIC,
 
     const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
     HB_BUFFER_FLAG_DEFAULT,
     HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
     HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
     HB_BUFFER_SCRATCH_FLAG_DEFAULT,
     HB_BUFFER_MAX_LEN_DEFAULT,
+    HB_BUFFER_MAX_OPS_DEFAULT,
 
     HB_BUFFER_CONTENT_TYPE_INVALID,
     HB_SEGMENT_PROPERTIES_DEFAULT,
     true, /* in_error */
     true, /* have_output */
     true  /* have_positions */
 
     /* Zero is good enough for everything else. */
--- a/gfx/harfbuzz/src/hb-coretext.cc
+++ b/gfx/harfbuzz/src/hb-coretext.cc
@@ -76,31 +76,22 @@ reference_table  (hb_face_t *face HB_UNU
 }
 
 static void
 _hb_cg_font_release (void *data)
 {
   CGFontRelease ((CGFontRef) data);
 }
 
-hb_face_t *
-hb_coretext_face_create (CGFontRef cg_font)
-{
-  return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
-}
 
 HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face)
 HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font,
 	fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size (font->ptem)) <= .5
 )
 
-/*
- * shaper face data
- */
-
 static CTFontDescriptorRef
 get_last_resort_font_desc (void)
 {
   // TODO Handle allocation failures?
   CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0);
   CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault,
 					   (const void **) &last_resort,
 					   1,
@@ -262,31 +253,33 @@ hb_coretext_shaper_face_data_t *
 }
 
 void
 _hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
 {
   CFRelease ((CGFontRef) data);
 }
 
+hb_face_t *
+hb_coretext_face_create (CGFontRef cg_font)
+{
+  return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
+}
+
 /*
  * Since: 0.9.10
  */
 CGFontRef
 hb_coretext_face_get_cg_font (hb_face_t *face)
 {
   if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
   return (CGFontRef) HB_SHAPER_DATA_GET (face);
 }
 
 
-/*
- * shaper font data
- */
-
 hb_coretext_shaper_font_data_t *
 _hb_coretext_shaper_font_data_create (hb_font_t *font)
 {
   hb_face_t *face = font->face;
   if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
   CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
 
   CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size (font->ptem));
@@ -301,16 +294,45 @@ hb_coretext_shaper_font_data_t *
 }
 
 void
 _hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
 {
   CFRelease ((CTFontRef) data);
 }
 
+/*
+ * Since: 1.7.2
+ */
+hb_font_t *
+hb_coretext_font_create (CTFontRef ct_font)
+{
+  CGFontRef cg_font = CTFontCopyGraphicsFont (ct_font, 0);
+  hb_face_t *face = hb_coretext_face_create (cg_font);
+  CFRelease (cg_font);
+  hb_font_t *font = hb_font_create (face);
+  hb_face_destroy (face);
+
+  if (unlikely (hb_object_is_inert (font)))
+    return font;
+
+  /* Let there be dragons here... */
+  HB_SHAPER_DATA_GET (font) = (hb_coretext_shaper_font_data_t *) CFRetain (ct_font);
+
+  return font;
+}
+
+CTFontRef
+hb_coretext_font_get_ct_font (hb_font_t *font)
+{
+  if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return nullptr;
+  return (CTFontRef) HB_SHAPER_DATA_GET (font);
+}
+
+
 
 /*
  * shaper shape_plan data
  */
 
 struct hb_coretext_shaper_shape_plan_data_t {};
 
 hb_coretext_shaper_shape_plan_data_t *
@@ -323,23 +345,16 @@ hb_coretext_shaper_shape_plan_data_t *
   return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
 _hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED)
 {
 }
 
-CTFontRef
-hb_coretext_font_get_ct_font (hb_font_t *font)
-{
-  if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return nullptr;
-  return (CTFontRef)HB_SHAPER_DATA_GET (font);
-}
-
 
 /*
  * shaper
  */
 
 struct feature_record_t {
   unsigned int feature;
   unsigned int setting;
@@ -995,17 +1010,17 @@ resize_and_retry:
 	 *
 	 * Looks like if we really want to be sure here we have to modify the
 	 * font to change the name table, similar to what we do in the uniscribe
 	 * backend.
 	 *
 	 * However, even that wouldn't work if we were passed in the CGFont to
 	 * construct a hb_face to begin with.
 	 *
-	 * See: http://github.com/behdad/harfbuzz/pull/36
+	 * See: http://github.com/harfbuzz/harfbuzz/pull/36
 	 *
 	 * Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
 	 */
 	bool matched = false;
 	for (unsigned int i = 0; i < range_records.len; i++)
 	  if (range_records[i].font && CFEqual (run_ct_font, range_records[i].font))
 	  {
 	    matched = true;
--- a/gfx/harfbuzz/src/hb-coretext.h
+++ b/gfx/harfbuzz/src/hb-coretext.h
@@ -43,16 +43,19 @@ HB_BEGIN_DECLS
 #define HB_CORETEXT_TAG_MORT HB_TAG('m','o','r','t')
 #define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x')
 #define HB_CORETEXT_TAG_KERX HB_TAG('k','e','r','x')
 
 
 HB_EXTERN hb_face_t *
 hb_coretext_face_create (CGFontRef cg_font);
 
+HB_EXTERN hb_font_t *
+hb_coretext_font_create (CTFontRef ct_font);
+
 
 HB_EXTERN CGFontRef
 hb_coretext_face_get_cg_font (hb_face_t *face);
 
 HB_EXTERN CTFontRef
 hb_coretext_font_get_ct_font (hb_font_t *font);
 
 
--- a/gfx/harfbuzz/src/hb-debug.hh
+++ b/gfx/harfbuzz/src/hb-debug.hh
@@ -216,22 +216,24 @@ static inline void _hb_warn_no_return (b
   }
 }
 template <>
 /*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
 {}
 
 template <int max_level, typename ret_t>
 struct hb_auto_trace_t {
+
   explicit inline hb_auto_trace_t (unsigned int *plevel_,
 				   const char *what_,
 				   const void *obj_,
 				   const char *func,
 				   const char *message,
-				   ...) : plevel (plevel_), what (what_), obj (obj_), returned (false)
+				   ...) HB_PRINTF_FUNC(6, 7)
+				   : plevel (plevel_), what (what_), obj (obj_), returned (false)
   {
     if (plevel) ++*plevel;
 
     va_list ap;
     va_start (ap, message);
     _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
     va_end (ap);
   }
@@ -265,17 +267,17 @@ struct hb_auto_trace_t {
   const char *what;
   const void *obj;
   bool returned;
 };
 template <typename ret_t> /* Make sure we don't use hb_auto_trace_t when not tracing. */
 struct hb_auto_trace_t<0, ret_t>;
 
 /* For disabled tracing; optimize out everything.
- * https://github.com/behdad/harfbuzz/pull/605 */
+ * https://github.com/harfbuzz/harfbuzz/pull/605 */
 template <typename ret_t>
 struct hb_no_trace_t {
   inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
 };
 
 #define return_trace(RET) return trace.ret (RET, __LINE__)
 
 
@@ -338,53 +340,53 @@ struct hb_no_trace_t {
 
 #ifndef HB_DEBUG_CLOSURE
 #define HB_DEBUG_CLOSURE (HB_DEBUG+0)
 #endif
 #if HB_DEBUG_CLOSURE
 #define TRACE_CLOSURE(this) \
 	hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
-	 "")
+	 " ")
 #else
 #define TRACE_CLOSURE(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
 #endif
 
 #ifndef HB_DEBUG_COLLECT_GLYPHS
 #define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
 #endif
 #if HB_DEBUG_COLLECT_GLYPHS
 #define TRACE_COLLECT_GLYPHS(this) \
 	hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
-	 "")
+	 " ")
 #else
 #define TRACE_COLLECT_GLYPHS(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
 #endif
 
 #ifndef HB_DEBUG_SANITIZE
 #define HB_DEBUG_SANITIZE (HB_DEBUG+0)
 #endif
 #if HB_DEBUG_SANITIZE
 #define TRACE_SANITIZE(this) \
 	hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
-	 "");
+	 " ");
 #else
 #define TRACE_SANITIZE(this) hb_no_trace_t<bool> trace
 #endif
 
 #ifndef HB_DEBUG_SERIALIZE
 #define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
 #endif
 #if HB_DEBUG_SERIALIZE
 #define TRACE_SERIALIZE(this) \
 	hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \
 	(&c->debug_depth, "SERIALIZE", c, HB_FUNC, \
-	 "");
+	 " ");
 #else
 #define TRACE_SERIALIZE(this) hb_no_trace_t<bool> trace
 #endif
 
 #ifndef HB_DEBUG_WOULD_APPLY
 #define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
 #endif
 #if HB_DEBUG_WOULD_APPLY
--- a/gfx/harfbuzz/src/hb-open-file-private.hh
+++ b/gfx/harfbuzz/src/hb-open-file-private.hh
@@ -59,19 +59,19 @@ typedef struct TableRecord
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   Tag		tag;		/* 4-byte identifier. */
   CheckSum	checkSum;	/* CheckSum for this table. */
-  ULONG		offset;		/* Offset from beginning of TrueType font
+  UINT32		offset;		/* Offset from beginning of TrueType font
 				 * file. */
-  ULONG		length;		/* Length of this table. */
+  UINT32		length;		/* Length of this table. */
   public:
   DEFINE_SIZE_STATIC (16);
 } OpenTypeTable;
 
 typedef struct OffsetTable
 {
   friend struct OpenTypeFontFile;
 
@@ -149,17 +149,17 @@ struct TTCHeaderVersion1
     TRACE_SANITIZE (this);
     return_trace (table.sanitize (c, this));
   }
 
   protected:
   Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
   FixedVersion<>version;	/* Version of the TTC Header (1.0),
 				 * 0x00010000u */
-  ArrayOf<LOffsetTo<OffsetTable>, ULONG>
+  ArrayOf<LOffsetTo<OffsetTable>, UINT32>
 		table;		/* Array of offsets to the OffsetTable for each font
 				 * from the beginning of the file */
   public:
   DEFINE_SIZE_ARRAY (12, table);
 };
 
 struct TTCHeader
 {
--- a/gfx/harfbuzz/src/hb-open-type-private.hh
+++ b/gfx/harfbuzz/src/hb-open-type-private.hh
@@ -630,42 +630,41 @@ struct IntType
     return_trace (likely (c->check_struct (this)));
   }
   protected:
   BEInt<Type, Size> v;
   public:
   DEFINE_SIZE_STATIC (Size);
 };
 
-typedef IntType<int8_t,   1> CHAR;	/* 8-bit signed integer. */
-typedef IntType<uint8_t,  1> BYTE;	/* 8-bit unsigned integer. */
+typedef IntType<uint8_t,  1> UINT8;	/* 8-bit unsigned integer. */
 typedef IntType<int8_t,   1> INT8;	/* 8-bit signed integer. */
-typedef IntType<uint16_t, 2> USHORT;	/* 16-bit unsigned integer. */
-typedef IntType<int16_t,  2> SHORT;	/* 16-bit signed integer. */
-typedef IntType<uint32_t, 4> ULONG;	/* 32-bit unsigned integer. */
-typedef IntType<int32_t,  4> LONG;	/* 32-bit signed integer. */
+typedef IntType<uint16_t, 2> UINT16;	/* 16-bit unsigned integer. */
+typedef IntType<int16_t,  2> INT16;	/* 16-bit signed integer. */
+typedef IntType<uint32_t, 4> UINT32;	/* 32-bit unsigned integer. */
+typedef IntType<int32_t,  4> INT32;	/* 32-bit signed integer. */
 typedef IntType<uint32_t, 3> UINT24;	/* 24-bit unsigned integer. */
 
-/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
-typedef SHORT FWORD;
+/* 16-bit signed integer (INT16) that describes a quantity in FUnits. */
+typedef INT16 FWORD;
 
-/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
-typedef USHORT UFWORD;
+/* 16-bit unsigned integer (UINT16) that describes a quantity in FUnits. */
+typedef UINT16 UFWORD;
 
 /* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
-struct F2DOT14 : SHORT
+struct F2DOT14 : INT16
 {
   //inline float to_float (void) const { return ???; }
   //inline void set_float (float f) { v.set (f * ???); }
   public:
   DEFINE_SIZE_STATIC (2);
 };
 
 /* 32-bit signed fixed-point number (16.16). */
-struct Fixed: LONG
+struct Fixed: INT32
 {
   //inline float to_float (void) const { return ???; }
   //inline void set_float (float f) { v.set (f * ???); }
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 /* Date represented in number of seconds since 12:00 midnight, January 1,
@@ -673,81 +672,84 @@ struct Fixed: LONG
 struct LONGDATETIME
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this)));
   }
   protected:
-  LONG major;
-  ULONG minor;
+  INT32 major;
+  UINT32 minor;
   public:
   DEFINE_SIZE_STATIC (8);
 };
 
 /* Array of four uint8s (length = 32 bits) used to identify a script, language
  * system, feature, or baseline */
-struct Tag : ULONG
+struct Tag : UINT32
 {
   /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
   inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); }
   inline operator char* (void) { return reinterpret_cast<char *> (&this->v); }
   public:
   DEFINE_SIZE_STATIC (4);
 };
 DEFINE_NULL_DATA (Tag, "    ");
 
 /* Glyph index number, same as uint16 (length = 16 bits) */
-typedef USHORT GlyphID;
+typedef UINT16 GlyphID;
 
 /* Script/language-system/feature index */
-struct Index : USHORT {
+struct Index : UINT16 {
   static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
 };
 DEFINE_NULL_DATA (Index, "\xff\xff");
 
 /* Offset, Null offset = 0 */
-template <typename Type=USHORT>
+template <typename Type>
 struct Offset : Type
 {
   inline bool is_null (void) const { return 0 == *this; }
   public:
   DEFINE_SIZE_STATIC (sizeof(Type));
 };
 
+typedef Offset<UINT16> Offset16;
+typedef Offset<UINT32> Offset32;
+
 
 /* CheckSum */
-struct CheckSum : ULONG
+struct CheckSum : UINT32
 {
   /* This is reference implementation from the spec. */
-  static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length)
+  static inline uint32_t CalcTableChecksum (const UINT32 *Table, uint32_t Length)
   {
     uint32_t Sum = 0L;
-    const ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size;
+    const UINT32 *EndPtr = Table+((Length+3) & ~3) / UINT32::static_size;
 
     while (Table < EndPtr)
       Sum += *Table++;
     return Sum;
   }
 
   /* Note: data should be 4byte aligned and have 4byte padding at the end. */
   inline void set_for_data (const void *data, unsigned int length)
-  { set (CalcTableChecksum ((const ULONG *) data, length)); }
+  { set (CalcTableChecksum ((const UINT32 *) data, length)); }
 
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 
 /*
  * Version Numbers
  */
 
-template <typename FixedType=USHORT>
+template <typename FixedType=UINT16>
 struct FixedVersion
 {
   inline uint32_t to_int (void) const { return (major << (sizeof(FixedType) * 8)) + minor; }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -761,17 +763,17 @@ struct FixedVersion
 
 
 
 /*
  * Template subclasses of Offset that do the dereferencing.
  * Use: (base+offset)
  */
 
-template <typename Type, typename OffsetType=USHORT>
+template <typename Type, typename OffsetType=UINT16>
 struct OffsetTo : Offset<OffsetType>
 {
   inline const Type& operator () (const void *base) const
   {
     unsigned int offset = *this;
     if (unlikely (!offset)) return Null(Type);
     return StructAtOffset<Type> (base, offset);
   }
@@ -806,29 +808,29 @@ struct OffsetTo : Offset<OffsetType>
   }
 
   /* Set the offset to Null */
   inline bool neuter (hb_sanitize_context_t *c) const {
     return c->try_set (this, 0);
   }
   DEFINE_SIZE_STATIC (sizeof(OffsetType));
 };
-template <typename Type> struct LOffsetTo : OffsetTo<Type, ULONG> {};
+template <typename Type> struct LOffsetTo : OffsetTo<Type, UINT32> {};
 template <typename Base, typename OffsetType, typename Type>
 static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
 template <typename Base, typename OffsetType, typename Type>
 static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
 
 
 /*
  * Array Types
  */
 
 /* An array with a number of elements. */
-template <typename Type, typename LenType=USHORT>
+template <typename Type, typename LenType=UINT16>
 struct ArrayOf
 {
   const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
   {
     unsigned int count = len;
     if (unlikely (start_offset > count))
       count = 0;
     else
@@ -928,20 +930,20 @@ struct ArrayOf
   }
 
   public:
   LenType len;
   Type array[VAR];
   public:
   DEFINE_SIZE_ARRAY (sizeof (LenType), array);
 };
-template <typename Type> struct LArrayOf : ArrayOf<Type, ULONG> {};
+template <typename Type> struct LArrayOf : ArrayOf<Type, UINT32> {};
 
 /* Array of Offset's */
-template <typename Type, typename OffsetType=USHORT>
+template <typename Type, typename OffsetType=UINT16>
 struct OffsetArrayOf : ArrayOf<OffsetTo<Type, OffsetType> > {};
 
 /* Array of offsets relative to the beginning of the array itself. */
 template <typename Type>
 struct OffsetListOf : OffsetArrayOf<Type>
 {
   inline const Type& operator [] (unsigned int i) const
   {
@@ -959,17 +961,17 @@ struct OffsetListOf : OffsetArrayOf<Type
   {
     TRACE_SANITIZE (this);
     return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data));
   }
 };
 
 
 /* An array starting at second element. */
-template <typename Type, typename LenType=USHORT>
+template <typename Type, typename LenType=UINT16>
 struct HeadlessArrayOf
 {
   inline const Type& operator [] (unsigned int i) const
   {
     if (unlikely (i >= len || !i)) return Null(Type);
     return array[i-1];
   }
   inline unsigned int get_size (void) const
@@ -1021,17 +1023,17 @@ struct HeadlessArrayOf
   public:
   DEFINE_SIZE_ARRAY (sizeof (LenType), array);
 };
 
 
 /*
  * An array with sorted elements.  Supports binary searching.
  */
-template <typename Type, typename LenType=USHORT>
+template <typename Type, typename LenType=UINT16>
 struct SortedArrayOf : ArrayOf<Type, LenType>
 {
   template <typename SearchType>
   inline int bsearch (const SearchType &x) const
   {
     /* Hand-coded bsearch here since this is in the hot inner loop. */
     const Type *array = this->array;
     int min = 0, max = (int) this->len - 1;
@@ -1060,20 +1062,20 @@ struct BinSearchHeader
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   protected:
-  USHORT	len;
-  USHORT	searchRangeZ;
-  USHORT	entrySelectorZ;
-  USHORT	rangeShiftZ;
+  UINT16	len;
+  UINT16	searchRangeZ;
+  UINT16	entrySelectorZ;
+  UINT16	rangeShiftZ;
 
   public:
   DEFINE_SIZE_STATIC (8);
 };
 
 template <typename Type>
 struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader> {};
 
--- a/gfx/harfbuzz/src/hb-ot-cbdt-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-cbdt-table.hh
@@ -42,54 +42,54 @@ struct SmallGlyphMetrics
   inline void get_extents (hb_glyph_extents_t *extents) const
   {
     extents->x_bearing = bearingX;
     extents->y_bearing = bearingY;
     extents->width = width;
     extents->height = -height;
   }
 
-  BYTE height;
-  BYTE width;
-  CHAR bearingX;
-  CHAR bearingY;
-  BYTE advance;
+  UINT8 height;
+  UINT8 width;
+  INT8 bearingX;
+  INT8 bearingY;
+  UINT8 advance;
 
   DEFINE_SIZE_STATIC(5);
 };
 
 struct BigGlyphMetrics : SmallGlyphMetrics
 {
-  CHAR vertBearingX;
-  CHAR vertBearingY;
-  BYTE vertAdvance;
+  INT8 vertBearingX;
+  INT8 vertBearingY;
+  UINT8 vertAdvance;
 
   DEFINE_SIZE_STATIC(8);
 };
 
 struct SBitLineMetrics
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  CHAR ascender;
-  CHAR decender;
-  BYTE widthMax;
-  CHAR caretSlopeNumerator;
-  CHAR caretSlopeDenominator;
-  CHAR caretOffset;
-  CHAR minOriginSB;
-  CHAR minAdvanceSB;
-  CHAR maxBeforeBL;
-  CHAR minAfterBL;
-  CHAR padding1;
-  CHAR padding2;
+  INT8 ascender;
+  INT8 decender;
+  UINT8 widthMax;
+  INT8 caretSlopeNumerator;
+  INT8 caretSlopeDenominator;
+  INT8 caretOffset;
+  INT8 minOriginSB;
+  INT8 minAdvanceSB;
+  INT8 maxBeforeBL;
+  INT8 minAfterBL;
+  INT8 padding1;
+  INT8 padding2;
 
   DEFINE_SIZE_STATIC(12);
 };
 
 
 /*
  * Index Subtables.
  */
@@ -97,19 +97,19 @@ struct SBitLineMetrics
 struct IndexSubtableHeader
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  USHORT indexFormat;
-  USHORT imageFormat;
-  ULONG imageDataOffset;
+  UINT16 indexFormat;
+  UINT16 imageFormat;
+  UINT32 imageDataOffset;
 
   DEFINE_SIZE_STATIC(8);
 };
 
 template <typename OffsetType>
 struct IndexSubtableFormat1Or3
 {
   inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
@@ -132,18 +132,18 @@ struct IndexSubtableFormat1Or3
   }
 
   IndexSubtableHeader header;
   Offset<OffsetType> offsetArrayZ[VAR];
 
   DEFINE_SIZE_ARRAY(8, offsetArrayZ);
 };
 
-struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<ULONG> {};
-struct IndexSubtableFormat3 : IndexSubtableFormat1Or3<USHORT> {};
+struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<UINT32> {};
+struct IndexSubtableFormat3 : IndexSubtableFormat1Or3<UINT16> {};
 
 struct IndexSubtable
 {
   inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
   {
     TRACE_SANITIZE (this);
     if (!u.header.sanitize (c)) return_trace (false);
     switch (u.header.indexFormat) {
@@ -209,18 +209,18 @@ struct IndexSubtableRecord
     if (gid < firstGlyphIndex || gid > lastGlyphIndex)
     {
       return false;
     }
     return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
 						   offset, length, format);
   }
 
-  USHORT firstGlyphIndex;
-  USHORT lastGlyphIndex;
+  UINT16 firstGlyphIndex;
+  UINT16 lastGlyphIndex;
   LOffsetTo<IndexSubtable> offsetToSubtable;
 
   DEFINE_SIZE_STATIC(8);
 };
 
 struct IndexSubtableArray
 {
   inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
@@ -271,66 +271,68 @@ struct BitmapSizeTable
 
   const IndexSubtableRecord *find_table (hb_codepoint_t glyph, const void *base) const
   {
     return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables);
   }
 
   protected:
   LOffsetTo<IndexSubtableArray> indexSubtableArrayOffset;
-  ULONG indexTablesSize;
-  ULONG numberOfIndexSubtables;
-  ULONG colorRef;
+  UINT32 indexTablesSize;
+  UINT32 numberOfIndexSubtables;
+  UINT32 colorRef;
   SBitLineMetrics horizontal;
   SBitLineMetrics vertical;
-  USHORT startGlyphIndex;
-  USHORT endGlyphIndex;
-  BYTE ppemX;
-  BYTE ppemY;
-  BYTE bitDepth;
-  CHAR flags;
+  UINT16 startGlyphIndex;
+  UINT16 endGlyphIndex;
+  UINT8 ppemX;
+  UINT8 ppemY;
+  UINT8 bitDepth;
+  INT8 flags;
 
-public:
+  public:
   DEFINE_SIZE_STATIC(48);
 };
 
 
 /*
  * Glyph Bitmap Data Formats.
  */
 
 struct GlyphBitmapDataFormat17
 {
   SmallGlyphMetrics glyphMetrics;
-  ULONG dataLen;
-  BYTE dataZ[VAR];
+  UINT32 dataLen;
+  UINT8 dataZ[VAR];
 
   DEFINE_SIZE_ARRAY(9, dataZ);
 };
 
 
 /*
  * CBLC -- Color Bitmap Location Table
  */
 
 #define HB_OT_TAG_CBLC HB_TAG('C','B','L','C')
 
 struct CBLC
 {
+  friend struct CBDT;
+
   static const hb_tag_t tableTag = HB_OT_TAG_CBLC;
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  likely (version.major == 2 || version.major == 3) &&
 		  sizeTables.sanitize (c, this));
   }
 
-  public:
+  protected:
   const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
 					 unsigned int *x_ppem, unsigned int *y_ppem) const
   {
     /* TODO: Make it possible to select strike. */
 
     unsigned int count = sizeTables.len;
     for (uint32_t i = 0; i < count; ++i)
     {
@@ -366,19 +368,104 @@ struct CBDT
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  likely (version.major == 2 || version.major == 3));
   }
 
+  struct accelerator_t
+  {
+    inline void init (hb_face_t *face)
+    {
+      upem = face->get_upem();
+
+      cblc_blob = Sanitizer<CBLC>::sanitize (face->reference_table (HB_OT_TAG_CBLC));
+      cbdt_blob = Sanitizer<CBDT>::sanitize (face->reference_table (HB_OT_TAG_CBDT));
+      cbdt_len = hb_blob_get_length (cbdt_blob);
+
+      if (hb_blob_get_length (cblc_blob) == 0) {
+	cblc = nullptr;
+	cbdt = nullptr;
+	return;  /* Not a bitmap font. */
+      }
+      cblc = Sanitizer<CBLC>::lock_instance (cblc_blob);
+      cbdt = Sanitizer<CBDT>::lock_instance (cbdt_blob);
+
+    }
+
+    inline void fini (void)
+    {
+      hb_blob_destroy (this->cblc_blob);
+      hb_blob_destroy (this->cbdt_blob);
+    }
+
+    inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+    {
+      unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */
+
+      if (!cblc)
+	return false;  // Not a color bitmap font.
+
+      const IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem);
+      if (!subtable_record || !x_ppem || !y_ppem)
+	return false;
+
+      if (subtable_record->get_extents (extents))
+	return true;
+
+      unsigned int image_offset = 0, image_length = 0, image_format = 0;
+      if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format))
+	return false;
+
+      {
+	if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
+	  return false;
+
+	switch (image_format)
+	{
+	  case 17: {
+	    if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
+	      return false;
+
+	    const GlyphBitmapDataFormat17& glyphFormat17 =
+		StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
+	    glyphFormat17.glyphMetrics.get_extents (extents);
+	  }
+	  break;
+	  default:
+	    // TODO: Support other image formats.
+	    return false;
+	}
+      }
+
+      /* Convert to the font units. */
+      extents->x_bearing *= upem / (float) x_ppem;
+      extents->y_bearing *= upem / (float) y_ppem;
+      extents->width *= upem / (float) x_ppem;
+      extents->height *= upem / (float) y_ppem;
+
+      return true;
+    }
+
+    private:
+    hb_blob_t *cblc_blob;
+    hb_blob_t *cbdt_blob;
+    const CBLC *cblc;
+    const CBDT *cbdt;
+
+    unsigned int cbdt_len;
+    unsigned int upem;
+  };
+
+
   protected:
   FixedVersion<>version;
-  BYTE dataZ[VAR];
+  UINT8 dataZ[VAR];
 
   public:
   DEFINE_SIZE_ARRAY(4, dataZ);
 };
 
 } /* namespace OT */
 
 #endif /* HB_OT_CBDT_TABLE_HH */
--- a/gfx/harfbuzz/src/hb-ot-cmap-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-cmap-table.hh
@@ -53,20 +53,20 @@ struct CmapSubtableFormat0
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   protected:
-  USHORT	format;		/* Format number is set to 0. */
-  USHORT	lengthZ;	/* Byte length of this subtable. */
-  USHORT	languageZ;	/* Ignore. */
-  BYTE		glyphIdArray[256];/* An array that maps character
+  UINT16	format;		/* Format number is set to 0. */
+  UINT16	lengthZ;	/* Byte length of this subtable. */
+  UINT16	languageZ;	/* Ignore. */
+  UINT8		glyphIdArray[256];/* An array that maps character
 				 * code to glyph index values. */
   public:
   DEFINE_SIZE_STATIC (6 + 256);
 };
 
 struct CmapSubtableFormat4
 {
   struct accelerator_t
@@ -83,18 +83,18 @@ struct CmapSubtableFormat4
     }
 
     static inline bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
     {
       const accelerator_t *thiz = (const accelerator_t *) obj;
 
       /* Custom two-array bsearch. */
       int min = 0, max = (int) thiz->segCount - 1;
-      const USHORT *startCount = thiz->startCount;
-      const USHORT *endCount = thiz->endCount;
+      const UINT16 *startCount = thiz->startCount;
+      const UINT16 *endCount = thiz->endCount;
       unsigned int i;
       while (min <= max)
       {
 	int mid = (min + max) / 2;
 	if (codepoint < startCount[mid])
 	  max = mid - 1;
 	else if (codepoint > endCount[mid])
 	  min = mid + 1;
@@ -122,21 +122,21 @@ struct CmapSubtableFormat4
 	  return false;
 	gid += thiz->idDelta[i];
       }
 
       *glyph = gid & 0xFFFFu;
       return true;
     }
 
-    const USHORT *endCount;
-    const USHORT *startCount;
-    const USHORT *idDelta;
-    const USHORT *idRangeOffset;
-    const USHORT *glyphIdArray;
+    const UINT16 *endCount;
+    const UINT16 *startCount;
+    const UINT16 *idDelta;
+    const UINT16 *idRangeOffset;
+    const UINT16 *glyphIdArray;
     unsigned int segCount;
     unsigned int glyphIdArrayLength;
   };
 
   inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
   {
     accelerator_t accel;
     accel.init (this);
@@ -160,34 +160,34 @@ struct CmapSubtableFormat4
       if (!c->try_set (&length, new_length))
 	return_trace (false);
     }
 
     return_trace (16 + 4 * (unsigned int) segCountX2 <= length);
   }
 
   protected:
-  USHORT	format;		/* Format number is set to 4. */
-  USHORT	length;		/* This is the length in bytes of the
+  UINT16	format;		/* Format number is set to 4. */
+  UINT16	length;		/* This is the length in bytes of the
 				 * subtable. */
-  USHORT	languageZ;	/* Ignore. */
-  USHORT	segCountX2;	/* 2 x segCount. */
-  USHORT	searchRangeZ;	/* 2 * (2**floor(log2(segCount))) */
-  USHORT	entrySelectorZ;	/* log2(searchRange/2) */
-  USHORT	rangeShiftZ;	/* 2 x segCount - searchRange */
+  UINT16	languageZ;	/* Ignore. */
+  UINT16	segCountX2;	/* 2 x segCount. */
+  UINT16	searchRangeZ;	/* 2 * (2**floor(log2(segCount))) */
+  UINT16	entrySelectorZ;	/* log2(searchRange/2) */
+  UINT16	rangeShiftZ;	/* 2 x segCount - searchRange */
 
-  USHORT	values[VAR];
+  UINT16	values[VAR];
 #if 0
-  USHORT	endCount[segCount];	/* End characterCode for each segment,
+  UINT16	endCount[segCount];	/* End characterCode for each segment,
 					 * last=0xFFFFu. */
-  USHORT	reservedPad;		/* Set to 0. */
-  USHORT	startCount[segCount];	/* Start character code for each segment. */
-  SHORT		idDelta[segCount];	/* Delta for all character codes in segment. */
-  USHORT	idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
-  USHORT	glyphIdArray[VAR];	/* Glyph index array (arbitrary length) */
+  UINT16	reservedPad;		/* Set to 0. */
+  UINT16	startCount[segCount];	/* Start character code for each segment. */
+  INT16		idDelta[segCount];	/* Delta for all character codes in segment. */
+  UINT16	idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
+  UINT16	glyphIdArray[VAR];	/* Glyph index array (arbitrary length) */
 #endif
 
   public:
   DEFINE_SIZE_ARRAY (14, values);
 };
 
 struct CmapSubtableLongGroup
 {
@@ -203,19 +203,19 @@ struct CmapSubtableLongGroup
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   private:
-  ULONG		startCharCode;	/* First character code in this group. */
-  ULONG		endCharCode;	/* Last character code in this group. */
-  ULONG		glyphID;	/* Glyph index; interpretation depends on
+  UINT32		startCharCode;	/* First character code in this group. */
+  UINT32		endCharCode;	/* Last character code in this group. */
+  UINT32		glyphID;	/* Glyph index; interpretation depends on
 				 * subtable format. */
   public:
   DEFINE_SIZE_STATIC (12);
 };
 
 template <typename UINT>
 struct CmapSubtableTrimmed
 {
@@ -242,18 +242,18 @@ struct CmapSubtableTrimmed
   UINT		startCharCode;	/* First character code covered. */
   ArrayOf<GlyphID, UINT>
 		glyphIdArray;	/* Array of glyph index values for character
 				 * codes in the range. */
   public:
   DEFINE_SIZE_ARRAY (5 * sizeof (UINT), glyphIdArray);
 };
 
-struct CmapSubtableFormat6  : CmapSubtableTrimmed<USHORT> {};
-struct CmapSubtableFormat10 : CmapSubtableTrimmed<ULONG > {};
+struct CmapSubtableFormat6  : CmapSubtableTrimmed<UINT16> {};
+struct CmapSubtableFormat10 : CmapSubtableTrimmed<UINT32 > {};
 
 template <typename T>
 struct CmapSubtableLongSegmented
 {
   inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
   {
     int i = groups.bsearch (codepoint);
     if (i == -1)
@@ -264,21 +264,21 @@ struct CmapSubtableLongSegmented
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && groups.sanitize (c));
   }
 
   protected:
-  USHORT	format;		/* Subtable format; set to 12. */
-  USHORT	reservedZ;	/* Reserved; set to 0. */
-  ULONG		lengthZ;	/* Byte length of this subtable. */
-  ULONG		languageZ;	/* Ignore. */
-  SortedArrayOf<CmapSubtableLongGroup, ULONG>
+  UINT16	format;		/* Subtable format; set to 12. */
+  UINT16	reservedZ;	/* Reserved; set to 0. */
+  UINT32		lengthZ;	/* Byte length of this subtable. */
+  UINT32		languageZ;	/* Ignore. */
+  SortedArrayOf<CmapSubtableLongGroup, UINT32>
 		groups;		/* Groupings. */
   public:
   DEFINE_SIZE_ARRAY (16, groups);
 };
 
 struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
 {
   static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
@@ -311,23 +311,23 @@ struct UnicodeValueRange
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   UINT24	startUnicodeValue;	/* First value in this range. */
-  BYTE		additionalCount;	/* Number of additional values in this
+  UINT8		additionalCount;	/* Number of additional values in this
 					 * range. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
-typedef SortedArrayOf<UnicodeValueRange, ULONG> DefaultUVS;
+typedef SortedArrayOf<UnicodeValueRange, UINT32> DefaultUVS;
 
 struct UVSMapping
 {
   inline int cmp (const hb_codepoint_t &codepoint) const
   {
     return unicodeValue.cmp (codepoint);
   }
 
@@ -338,17 +338,17 @@ struct UVSMapping
   }
 
   UINT24	unicodeValue;	/* Base Unicode value of the UVS */
   GlyphID	glyphID;	/* Glyph ID of the UVS */
   public:
   DEFINE_SIZE_STATIC (5);
 };
 
-typedef SortedArrayOf<UVSMapping, ULONG> NonDefaultUVS;
+typedef SortedArrayOf<UVSMapping, UINT32> NonDefaultUVS;
 
 struct VariationSelectorRecord
 {
   inline glyph_variant_t get_glyph (hb_codepoint_t codepoint,
 				    hb_codepoint_t *glyph,
 				    const void *base) const
   {
     int i;
@@ -400,19 +400,19 @@ struct CmapSubtableFormat14
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  record.sanitize (c, this));
   }
 
   protected:
-  USHORT	format;		/* Format number is set to 14. */
-  ULONG		lengthZ;	/* Byte length of this subtable. */
-  SortedArrayOf<VariationSelectorRecord, ULONG>
+  UINT16	format;		/* Format number is set to 14. */
+  UINT32		lengthZ;	/* Byte length of this subtable. */
+  SortedArrayOf<VariationSelectorRecord, UINT32>
 		record;		/* Variation selector records; sorted
 				 * in increasing order of `varSelector'. */
   public:
   DEFINE_SIZE_ARRAY (10, record);
 };
 
 struct CmapSubtable
 {
@@ -446,17 +446,17 @@ struct CmapSubtable
     case 13: return_trace (u.format13.sanitize (c));
     case 14: return_trace (u.format14.sanitize (c));
     default:return_trace (true);
     }
   }
 
   public:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   CmapSubtableFormat0	format0;
   CmapSubtableFormat4	format4;
   CmapSubtableFormat6	format6;
   CmapSubtableFormat10	format10;
   CmapSubtableFormat12	format12;
   CmapSubtableFormat13	format13;
   CmapSubtableFormat14	format14;
   } u;
@@ -479,28 +479,168 @@ struct EncodingRecord
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  subtable.sanitize (c, base));
   }
 
-  USHORT	platformID;	/* Platform ID. */
-  USHORT	encodingID;	/* Platform-specific encoding ID. */
+  UINT16	platformID;	/* Platform ID. */
+  UINT16	encodingID;	/* Platform-specific encoding ID. */
   LOffsetTo<CmapSubtable>
 		subtable;	/* Byte offset from beginning of table to the subtable for this encoding. */
   public:
   DEFINE_SIZE_STATIC (8);
 };
 
 struct cmap
 {
   static const hb_tag_t tableTag	= HB_OT_TAG_cmap;
 
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+		  likely (version == 0) &&
+		  encodingRecord.sanitize (c, this));
+  }
+
+  struct accelerator_t
+  {
+    inline void init (hb_face_t *face)
+    {
+      this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap));
+      const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
+      const OT::CmapSubtable *subtable = nullptr;
+      const OT::CmapSubtableFormat14 *subtable_uvs = nullptr;
+
+      bool symbol = false;
+      /* 32-bit subtables. */
+      if (!subtable) subtable = cmap->find_subtable (3, 10);
+      if (!subtable) subtable = cmap->find_subtable (0, 6);
+      if (!subtable) subtable = cmap->find_subtable (0, 4);
+      /* 16-bit subtables. */
+      if (!subtable) subtable = cmap->find_subtable (3, 1);
+      if (!subtable) subtable = cmap->find_subtable (0, 3);
+      if (!subtable) subtable = cmap->find_subtable (0, 2);
+      if (!subtable) subtable = cmap->find_subtable (0, 1);
+      if (!subtable) subtable = cmap->find_subtable (0, 0);
+      if (!subtable)
+      {
+	subtable = cmap->find_subtable (3, 0);
+	if (subtable) symbol = true;
+      }
+      /* Meh. */
+      if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
+
+      /* UVS subtable. */
+      if (!subtable_uvs)
+      {
+	const OT::CmapSubtable *st = cmap->find_subtable (0, 5);
+	if (st && st->u.format == 14)
+	  subtable_uvs = &st->u.format14;
+      }
+      /* Meh. */
+      if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtableFormat14);
+
+      this->uvs_table = subtable_uvs;
+
+      this->get_glyph_data = subtable;
+      if (unlikely (symbol))
+	this->get_glyph_func = get_glyph_from_symbol<OT::CmapSubtable>;
+      else
+	switch (subtable->u.format) {
+	/* Accelerate format 4 and format 12. */
+	default: this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;		break;
+	case 12: this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>;	break;
+	case  4:
+	  {
+	    this->format4_accel.init (&subtable->u.format4);
+	    this->get_glyph_data = &this->format4_accel;
+	    this->get_glyph_func = this->format4_accel.get_glyph_func;
+	  }
+	  break;
+	}
+    }
+
+    inline void fini (void)
+    {
+      hb_blob_destroy (this->blob);
+    }
+
+    inline bool get_nominal_glyph (hb_codepoint_t  unicode,
+				   hb_codepoint_t *glyph) const
+    {
+      return this->get_glyph_func (this->get_glyph_data, unicode, glyph);
+    }
+
+    inline bool get_variation_glyph (hb_codepoint_t  unicode,
+				     hb_codepoint_t  variation_selector,
+				     hb_codepoint_t *glyph) const
+    {
+      switch (this->uvs_table->get_glyph_variant (unicode,
+						  variation_selector,
+						  glyph))
+      {
+	case OT::GLYPH_VARIANT_NOT_FOUND:		return false;
+	case OT::GLYPH_VARIANT_FOUND:		return true;
+	case OT::GLYPH_VARIANT_USE_DEFAULT:	break;
+      }
+
+      return get_nominal_glyph (unicode, glyph);
+    }
+
+    protected:
+    typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
+					      hb_codepoint_t codepoint,
+					      hb_codepoint_t *glyph);
+
+    template <typename Type>
+    static inline bool get_glyph_from (const void *obj,
+				       hb_codepoint_t codepoint,
+				       hb_codepoint_t *glyph)
+    {
+      const Type *typed_obj = (const Type *) obj;
+      return typed_obj->get_glyph (codepoint, glyph);
+    }
+
+    template <typename Type>
+    static inline bool get_glyph_from_symbol (const void *obj,
+					      hb_codepoint_t codepoint,
+					      hb_codepoint_t *glyph)
+    {
+      const Type *typed_obj = (const Type *) obj;
+      if (likely (typed_obj->get_glyph (codepoint, glyph)))
+	return true;
+
+      if (codepoint <= 0x00FFu)
+      {
+	/* For symbol-encoded OpenType fonts, we duplicate the
+	 * U+F000..F0FF range at U+0000..U+00FF.  That's what
+	 * Windows seems to do, and that's hinted about at:
+	 * http://www.microsoft.com/typography/otspec/recom.htm
+	 * under "Non-Standard (Symbol) Fonts". */
+	return typed_obj->get_glyph (0xF000u + codepoint, glyph);
+      }
+
+      return false;
+    }
+
+    private:
+    hb_cmap_get_glyph_func_t get_glyph_func;
+    const void *get_glyph_data;
+    OT::CmapSubtableFormat4::accelerator_t format4_accel;
+
+    const OT::CmapSubtableFormat14 *uvs_table;
+    hb_blob_t *blob;
+  };
+
+  protected:
+
   inline const CmapSubtable *find_subtable (unsigned int platform_id,
 					    unsigned int encoding_id) const
   {
     EncodingRecord key;
     key.platformID.set (platform_id);
     key.encodingID.set (encoding_id);
 
     /* Note: We can use bsearch, but since it has no performance
@@ -508,25 +648,18 @@ struct cmap
      * unsorted subtable list. */
     int result = encodingRecord./*bsearch*/lsearch (key);
     if (result == -1 || !encodingRecord[result].subtable)
       return nullptr;
 
     return &(this+encodingRecord[result].subtable);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  likely (version == 0) &&
-		  encodingRecord.sanitize (c, this));
-  }
-
-  USHORT		version;	/* Table version number (0). */
+  protected:
+  UINT16		version;	/* Table version number (0). */
   SortedArrayOf<EncodingRecord>
 			encodingRecord;	/* Encoding tables. */
   public:
   DEFINE_SIZE_ARRAY (4, encodingRecord);
 };
 
 
 } /* namespace OT */
--- a/gfx/harfbuzz/src/hb-ot-font.cc
+++ b/gfx/harfbuzz/src/hb-ot-font.cc
@@ -28,491 +28,44 @@
 
 #include "hb-ot.h"
 
 #include "hb-font-private.hh"
 
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-cbdt-table.hh"
 #include "hb-ot-glyf-table.hh"
-#include "hb-ot-head-table.hh"
-#include "hb-ot-hhea-table.hh"
 #include "hb-ot-hmtx-table.hh"
 #include "hb-ot-kern-table.hh"
-#include "hb-ot-os2-table.hh"
 #include "hb-ot-post-table.hh"
-#include "hb-ot-var-hvar-table.hh"
-
-
-struct hb_ot_face_metrics_accelerator_t
-{
-  unsigned int num_metrics;
-  unsigned int num_advances;
-  unsigned int default_advance;
-  unsigned short ascender;
-  unsigned short descender;
-  unsigned short line_gap;
-  bool has_font_extents;
-
-  const OT::hmtxvmtx *table;
-  hb_blob_t *blob;
-
-  const OT::HVARVVAR *var;
-  hb_blob_t *var_blob;
-
-  inline void init (hb_face_t *face,
-		    hb_tag_t _hea_tag,
-		    hb_tag_t _mtx_tag,
-		    hb_tag_t _var_tag,
-		    hb_tag_t os2_tag,
-		    unsigned int default_advance = 0)
-  {
-    this->default_advance = default_advance ? default_advance : face->get_upem ();
-
-    bool got_font_extents = false;
-    if (os2_tag)
-    {
-      hb_blob_t *os2_blob = OT::Sanitizer<OT::os2>::sanitize (face->reference_table (os2_tag));
-      const OT::os2 *os2 = OT::Sanitizer<OT::os2>::lock_instance (os2_blob);
-#define USE_TYPO_METRICS (1u<<7)
-      if (0 != (os2->fsSelection & USE_TYPO_METRICS))
-      {
-	this->ascender = os2->sTypoAscender;
-	this->descender = os2->sTypoDescender;
-	this->line_gap = os2->sTypoLineGap;
-	got_font_extents = (this->ascender | this->descender) != 0;
-      }
-      hb_blob_destroy (os2_blob);
-    }
-
-    hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag));
-    const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob);
-    this->num_advances = _hea->numberOfLongMetrics;
-    if (!got_font_extents)
-    {
-      this->ascender = _hea->ascender;
-      this->descender = _hea->descender;
-      this->line_gap = _hea->lineGap;
-      got_font_extents = (this->ascender | this->descender) != 0;
-    }
-    hb_blob_destroy (_hea_blob);
-
-    this->has_font_extents = got_font_extents;
-
-    this->blob = OT::Sanitizer<OT::hmtxvmtx>::sanitize (face->reference_table (_mtx_tag));
-
-    /* Cap num_metrics() and num_advances() based on table length. */
-    unsigned int len = hb_blob_get_length (this->blob);
-    if (unlikely (this->num_advances * 4 > len))
-      this->num_advances = len / 4;
-    this->num_metrics = this->num_advances + (len - 4 * this->num_advances) / 2;
-
-    /* We MUST set num_metrics to zero if num_advances is zero.
-     * Our get_advance() depends on that. */
-    if (unlikely (!this->num_advances))
-    {
-      this->num_metrics = this->num_advances = 0;
-      hb_blob_destroy (this->blob);
-      this->blob = hb_blob_get_empty ();
-    }
-    this->table = OT::Sanitizer<OT::hmtxvmtx>::lock_instance (this->blob);
-
-    this->var_blob = OT::Sanitizer<OT::HVARVVAR>::sanitize (face->reference_table (_var_tag));
-    this->var = OT::Sanitizer<OT::HVARVVAR>::lock_instance (this->var_blob);
-  }
-
-  inline void fini (void)
-  {
-    hb_blob_destroy (this->blob);
-    hb_blob_destroy (this->var_blob);
-  }
-
-  inline unsigned int get_advance (hb_codepoint_t  glyph,
-				   hb_font_t      *font) const
-  {
-    if (unlikely (glyph >= this->num_metrics))
-    {
-      /* If this->num_metrics is zero, it means we don't have the metrics table
-       * for this direction: return default advance.  Otherwise, it means that the
-       * glyph index is out of bound: return zero. */
-      if (this->num_metrics)
-	return 0;
-      else
-	return this->default_advance;
-    }
-
-    return this->table->longMetric[MIN (glyph, (uint32_t) this->num_advances - 1)].advance
-	 + this->var->get_advance_var (glyph, font->coords, font->num_coords); // TODO Optimize?!
-  }
-};
-
-struct hb_ot_face_glyf_accelerator_t
-{
-  bool short_offset;
-  unsigned int num_glyphs;
-  const OT::loca *loca;
-  const OT::glyf *glyf;
-  hb_blob_t *loca_blob;
-  hb_blob_t *glyf_blob;
-  unsigned int glyf_len;
-
-  inline void init (hb_face_t *face)
-  {
-    hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (face->reference_table (HB_OT_TAG_head));
-    const OT::head *head = OT::Sanitizer<OT::head>::lock_instance (head_blob);
-    if ((unsigned int) head->indexToLocFormat > 1 || head->glyphDataFormat != 0)
-    {
-      /* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
-      hb_blob_destroy (head_blob);
-      return;
-    }
-    this->short_offset = 0 == head->indexToLocFormat;
-    hb_blob_destroy (head_blob);
-
-    this->loca_blob = OT::Sanitizer<OT::loca>::sanitize (face->reference_table (HB_OT_TAG_loca));
-    this->loca = OT::Sanitizer<OT::loca>::lock_instance (this->loca_blob);
-    this->glyf_blob = OT::Sanitizer<OT::glyf>::sanitize (face->reference_table (HB_OT_TAG_glyf));
-    this->glyf = OT::Sanitizer<OT::glyf>::lock_instance (this->glyf_blob);
-
-    this->num_glyphs = MAX (1u, hb_blob_get_length (this->loca_blob) / (this->short_offset ? 2 : 4)) - 1;
-    this->glyf_len = hb_blob_get_length (this->glyf_blob);
-  }
-
-  inline void fini (void)
-  {
-    hb_blob_destroy (this->loca_blob);
-    hb_blob_destroy (this->glyf_blob);
-  }
-
-  inline bool get_extents (hb_codepoint_t glyph,
-			   hb_glyph_extents_t *extents) const
-  {
-    if (unlikely (glyph >= this->num_glyphs))
-      return false;
-
-    unsigned int start_offset, end_offset;
-    if (this->short_offset)
-    {
-      start_offset = 2 * this->loca->u.shortsZ[glyph];
-      end_offset   = 2 * this->loca->u.shortsZ[glyph + 1];
-    }
-    else
-    {
-      start_offset = this->loca->u.longsZ[glyph];
-      end_offset   = this->loca->u.longsZ[glyph + 1];
-    }
-
-    if (start_offset > end_offset || end_offset > this->glyf_len)
-      return false;
-
-    if (end_offset - start_offset < OT::glyfGlyphHeader::static_size)
-      return true; /* Empty glyph; zero extents. */
-
-    const OT::glyfGlyphHeader &glyph_header = OT::StructAtOffset<OT::glyfGlyphHeader> (this->glyf, start_offset);
-
-    extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax);
-    extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax);
-    extents->width     = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing;
-    extents->height    = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing;
-
-    return true;
-  }
-};
-
-struct hb_ot_face_cbdt_accelerator_t
-{
-  hb_blob_t *cblc_blob;
-  hb_blob_t *cbdt_blob;
-  const OT::CBLC *cblc;
-  const OT::CBDT *cbdt;
-
-  unsigned int cbdt_len;
-  unsigned int upem;
-
-  inline void init (hb_face_t *face)
-  {
-    upem = face->get_upem();
-
-    cblc_blob = OT::Sanitizer<OT::CBLC>::sanitize (face->reference_table (HB_OT_TAG_CBLC));
-    cbdt_blob = OT::Sanitizer<OT::CBDT>::sanitize (face->reference_table (HB_OT_TAG_CBDT));
-    cbdt_len = hb_blob_get_length (cbdt_blob);
-
-    if (hb_blob_get_length (cblc_blob) == 0) {
-      cblc = nullptr;
-      cbdt = nullptr;
-      return;  /* Not a bitmap font. */
-    }
-    cblc = OT::Sanitizer<OT::CBLC>::lock_instance (cblc_blob);
-    cbdt = OT::Sanitizer<OT::CBDT>::lock_instance (cbdt_blob);
-
-  }
-
-  inline void fini (void)
-  {
-    hb_blob_destroy (this->cblc_blob);
-    hb_blob_destroy (this->cbdt_blob);
-  }
-
-  inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
-  {
-    unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */
-
-    if (!cblc)
-      return false;  // Not a color bitmap font.
 
-    const OT::IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem);
-    if (!subtable_record || !x_ppem || !y_ppem)
-      return false;
-
-    if (subtable_record->get_extents (extents))
-      return true;
-
-    unsigned int image_offset = 0, image_length = 0, image_format = 0;
-    if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format))
-      return false;
-
-    {
-      /* TODO Move the following into CBDT struct when adding more formats. */
-
-      if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
-	return false;
-
-      switch (image_format)
-      {
-	case 17: {
-	  if (unlikely (image_length < OT::GlyphBitmapDataFormat17::min_size))
-	    return false;
-
-	  const OT::GlyphBitmapDataFormat17& glyphFormat17 =
-	      OT::StructAtOffset<OT::GlyphBitmapDataFormat17> (this->cbdt, image_offset);
-	  glyphFormat17.glyphMetrics.get_extents (extents);
-	}
-	break;
-	default:
-	  // TODO: Support other image formats.
-	  return false;
-      }
-    }
-
-    /* Convert to the font units. */
-    extents->x_bearing *= upem / (float) x_ppem;
-    extents->y_bearing *= upem / (float) y_ppem;
-    extents->width *= upem / (float) x_ppem;
-    extents->height *= upem / (float) y_ppem;
-
-    return true;
-  }
-};
-
-struct hb_ot_face_post_accelerator_t
-{
-  hb_blob_t *post_blob;
-  OT::post::accelerator_t accel;
-
-  inline void init (hb_face_t *face)
-  {
-    hb_blob_t *blob = this->post_blob = OT::Sanitizer<OT::post>::sanitize (face->reference_table (HB_OT_TAG_post));
-    accel.init (OT::Sanitizer<OT::post>::lock_instance (blob), hb_blob_get_length (blob));
-  }
-
-  inline void fini (void)
-  {
-    accel.fini ();
-    hb_blob_destroy (this->post_blob);
-  }
-
-  inline bool get_glyph_name (hb_codepoint_t glyph,
-			      char *name, unsigned int size) const
-  {
-    return this->accel.get_glyph_name (glyph, name, size);
-  }
-
-  inline bool get_glyph_from_name (const char *name, int len,
-				   hb_codepoint_t *glyph) const
-  {
-    if (unlikely (!len))
-      return false;
-
-    return this->accel.get_glyph_from_name (name, len, glyph);
-  }
-};
-
-struct hb_ot_face_kern_accelerator_t
-{
-  hb_blob_t *kern_blob;
-  OT::kern::accelerator_t accel;
-
-  inline void init (hb_face_t *face)
-  {
-    hb_blob_t *blob = this->kern_blob = OT::Sanitizer<OT::kern>::sanitize (face->reference_table (HB_OT_TAG_kern));
-    accel.init (OT::Sanitizer<OT::kern>::lock_instance (blob), hb_blob_get_length (blob));
-  }
-
-  inline void fini (void)
-  {
-    accel.fini ();
-    hb_blob_destroy (this->kern_blob);
-  }
-
-  inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
-  { return accel.get_h_kerning (left, right); }
-};
-
-typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
-					  hb_codepoint_t codepoint,
-					  hb_codepoint_t *glyph);
-
-template <typename Type>
-static inline bool get_glyph_from (const void *obj,
-				   hb_codepoint_t codepoint,
-				   hb_codepoint_t *glyph)
-{
-  const Type *typed_obj = (const Type *) obj;
-  return typed_obj->get_glyph (codepoint, glyph);
-}
-
-template <typename Type>
-static inline bool get_glyph_from_symbol (const void *obj,
-					  hb_codepoint_t codepoint,
-					  hb_codepoint_t *glyph)
-{
-  const Type *typed_obj = (const Type *) obj;
-  if (likely (typed_obj->get_glyph (codepoint, glyph)))
-    return true;
-
-  if (codepoint <= 0x00FFu)
-  {
-    /* For symbol-encoded OpenType fonts, we duplicate the
-     * U+F000..F0FF range at U+0000..U+00FF.  That's what
-     * Windows seems to do, and that's hinted about at:
-     * http://www.microsoft.com/typography/otspec/recom.htm
-     * under "Non-Standard (Symbol) Fonts". */
-    return typed_obj->get_glyph (0xF000u + codepoint, glyph);
-  }
-
-  return false;
-}
-
-struct hb_ot_face_cmap_accelerator_t
-{
-  hb_cmap_get_glyph_func_t get_glyph_func;
-  const void *get_glyph_data;
-  OT::CmapSubtableFormat4::accelerator_t format4_accel;
-
-  const OT::CmapSubtableFormat14 *uvs_table;
-  hb_blob_t *blob;
-
-  inline void init (hb_face_t *face)
-  {
-    this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap));
-    const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
-    const OT::CmapSubtable *subtable = nullptr;
-    const OT::CmapSubtableFormat14 *subtable_uvs = nullptr;
-
-    bool symbol = false;
-    /* 32-bit subtables. */
-    if (!subtable) subtable = cmap->find_subtable (3, 10);
-    if (!subtable) subtable = cmap->find_subtable (0, 6);
-    if (!subtable) subtable = cmap->find_subtable (0, 4);
-    /* 16-bit subtables. */
-    if (!subtable) subtable = cmap->find_subtable (3, 1);
-    if (!subtable) subtable = cmap->find_subtable (0, 3);
-    if (!subtable) subtable = cmap->find_subtable (0, 2);
-    if (!subtable) subtable = cmap->find_subtable (0, 1);
-    if (!subtable) subtable = cmap->find_subtable (0, 0);
-    if (!subtable)
-    {
-      subtable = cmap->find_subtable (3, 0);
-      if (subtable) symbol = true;
-    }
-    /* Meh. */
-    if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
-
-    /* UVS subtable. */
-    if (!subtable_uvs)
-    {
-      const OT::CmapSubtable *st = cmap->find_subtable (0, 5);
-      if (st && st->u.format == 14)
-        subtable_uvs = &st->u.format14;
-    }
-    /* Meh. */
-    if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtableFormat14);
-
-    this->uvs_table = subtable_uvs;
-
-    this->get_glyph_data = subtable;
-    if (unlikely (symbol))
-      this->get_glyph_func = get_glyph_from_symbol<OT::CmapSubtable>;
-    else
-      switch (subtable->u.format) {
-      /* Accelerate format 4 and format 12. */
-      default: this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;		break;
-      case 12: this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>;	break;
-      case  4:
-	{
-	  this->format4_accel.init (&subtable->u.format4);
-	  this->get_glyph_data = &this->format4_accel;
-	  this->get_glyph_func = this->format4_accel.get_glyph_func;
-	}
-	break;
-      }
-  }
-
-  inline void fini (void)
-  {
-    hb_blob_destroy (this->blob);
-  }
-
-  inline bool get_nominal_glyph (hb_codepoint_t  unicode,
-				 hb_codepoint_t *glyph) const
-  {
-    return this->get_glyph_func (this->get_glyph_data, unicode, glyph);
-  }
-
-  inline bool get_variation_glyph (hb_codepoint_t  unicode,
-				   hb_codepoint_t  variation_selector,
-				   hb_codepoint_t *glyph) const
-  {
-    switch (this->uvs_table->get_glyph_variant (unicode,
-						variation_selector,
-						glyph))
-    {
-      case OT::GLYPH_VARIANT_NOT_FOUND:		return false;
-      case OT::GLYPH_VARIANT_FOUND:		return true;
-      case OT::GLYPH_VARIANT_USE_DEFAULT:	break;
-    }
-
-    return get_nominal_glyph (unicode, glyph);
-  }
-};
 
 struct hb_ot_font_t
 {
-  hb_ot_face_cmap_accelerator_t cmap;
-  hb_ot_face_metrics_accelerator_t h_metrics;
-  hb_ot_face_metrics_accelerator_t v_metrics;
-  OT::hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf;
-  OT::hb_lazy_loader_t<hb_ot_face_cbdt_accelerator_t> cbdt;
-  OT::hb_lazy_loader_t<hb_ot_face_post_accelerator_t> post;
-  OT::hb_lazy_loader_t<hb_ot_face_kern_accelerator_t> kern;
+  OT::cmap::accelerator_t cmap;
+  OT::hmtx::accelerator_t h_metrics;
+  OT::vmtx::accelerator_t v_metrics;
+  OT::hb_lazy_loader_t<OT::glyf::accelerator_t> glyf;
+  OT::hb_lazy_loader_t<OT::CBDT::accelerator_t> cbdt;
+  OT::hb_lazy_loader_t<OT::post::accelerator_t> post;
+  OT::hb_lazy_loader_t<OT::kern::accelerator_t> kern;
 };
 
 
 static hb_ot_font_t *
 _hb_ot_font_create (hb_face_t *face)
 {
   hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
 
   if (unlikely (!ot_font))
     return nullptr;
 
   ot_font->cmap.init (face);
-  ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_HVAR, HB_OT_TAG_os2);
-  ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_OT_TAG_VVAR, HB_TAG_NONE,
-			   ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
+  ot_font->h_metrics.init (face);
+  ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
   ot_font->glyf.init (face);
   ot_font->cbdt.init (face);
   ot_font->post.init (face);
   ot_font->kern.init (face);
 
   return ot_font;
 }
 
@@ -683,17 +236,17 @@ retry:
     hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
     hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, nullptr, nullptr);
     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, nullptr, nullptr);
     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
     //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
     hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, nullptr, nullptr);
     //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, nullptr, nullptr);
     hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr); TODO
+    //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
     hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
     hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr);
 
     hb_font_funcs_make_immutable (funcs);
 
     if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, nullptr, funcs)) {
       hb_font_funcs_destroy (funcs);
       goto retry;
--- a/gfx/harfbuzz/src/hb-ot-glyf-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-glyf-table.hh
@@ -23,44 +23,44 @@
  *
  * Google Author(s): Behdad Esfahbod
  */
 
 #ifndef HB_OT_GLYF_TABLE_HH
 #define HB_OT_GLYF_TABLE_HH
 
 #include "hb-open-type-private.hh"
+#include "hb-ot-head-table.hh"
 
 
 namespace OT {
 
 
 /*
  * loca -- Index to Location
  */
 
 #define HB_OT_TAG_loca HB_TAG('l','o','c','a')
 
 
 struct loca
 {
+  friend struct glyf;
+
   static const hb_tag_t tableTag = HB_OT_TAG_loca;
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (true);
   }
 
-  public:
-  union {
-    USHORT	shortsZ[VAR];		/* Location offset divided by 2. */
-    ULONG	longsZ[VAR];		/* Location offset. */
-  } u;
-  DEFINE_SIZE_ARRAY (0, u.longsZ);
+  protected:
+  UINT8		dataX[VAR];		/* Location data. */
+  DEFINE_SIZE_ARRAY (0, dataX);
 };
 
 
 /*
  * glyf -- TrueType Glyph Data
  */
 
 #define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
@@ -73,32 +73,108 @@ struct glyf
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     /* We don't check for anything specific here.  The users of the
      * struct do all the hard work... */
     return_trace (true);
   }
 
-  public:
-  BYTE		dataX[VAR];		/* Glyphs data. */
+  struct GlyphHeader
+  {
+    INT16		numberOfContours;	/* If the number of contours is
+					   * greater than or equal to zero,
+					   * this is a simple glyph; if negative,
+					   * this is a composite glyph. */
+    FWORD		xMin;			/* Minimum x for coordinate data. */
+    FWORD		yMin;			/* Minimum y for coordinate data. */
+    FWORD		xMax;			/* Maximum x for coordinate data. */
+    FWORD		yMax;			/* Maximum y for coordinate data. */
+
+    DEFINE_SIZE_STATIC (10);
+  };
+
+  struct accelerator_t
+  {
+    inline void init (hb_face_t *face)
+    {
+      hb_blob_t *head_blob = Sanitizer<head>::sanitize (face->reference_table (HB_OT_TAG_head));
+      const head *head_table = Sanitizer<head>::lock_instance (head_blob);
+      if ((unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
+      {
+	/* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
+	hb_blob_destroy (head_blob);
+	return;
+      }
+      short_offset = 0 == head_table->indexToLocFormat;
+      hb_blob_destroy (head_blob);
+
+      loca_blob = Sanitizer<loca>::sanitize (face->reference_table (HB_OT_TAG_loca));
+      loca_table = Sanitizer<loca>::lock_instance (loca_blob);
+      glyf_blob = Sanitizer<glyf>::sanitize (face->reference_table (HB_OT_TAG_glyf));
+      glyf_table = Sanitizer<glyf>::lock_instance (glyf_blob);
+
+      num_glyphs = MAX (1u, hb_blob_get_length (loca_blob) / (short_offset ? 2 : 4)) - 1;
+      glyf_len = hb_blob_get_length (glyf_blob);
+    }
+
+    inline void fini (void)
+    {
+      hb_blob_destroy (loca_blob);
+      hb_blob_destroy (glyf_blob);
+    }
+
+    inline bool get_extents (hb_codepoint_t glyph,
+			     hb_glyph_extents_t *extents) const
+    {
+      if (unlikely (glyph >= num_glyphs))
+	return false;
+
+      unsigned int start_offset, end_offset;
+      if (short_offset)
+      {
+        const UINT16 *offsets = (const UINT16 *) loca_table->dataX;
+	start_offset = 2 * offsets[glyph];
+	end_offset   = 2 * offsets[glyph + 1];
+      }
+      else
+      {
+        const UINT32 *offsets = (const UINT32 *) loca_table->dataX;
+	start_offset = offsets[glyph];
+	end_offset   = offsets[glyph + 1];
+      }
+
+      if (start_offset > end_offset || end_offset > glyf_len)
+	return false;
+
+      if (end_offset - start_offset < GlyphHeader::static_size)
+	return true; /* Empty glyph; zero extents. */
+
+      const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset);
+
+      extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax);
+      extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax);
+      extents->width     = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing;
+      extents->height    = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing;
+
+      return true;
+    }
+
+    private:
+    bool short_offset;
+    unsigned int num_glyphs;
+    const loca *loca_table;
+    const glyf *glyf_table;
+    hb_blob_t *loca_blob;
+    hb_blob_t *glyf_blob;
+    unsigned int glyf_len;
+  };
+
+  protected:
+  UINT8		dataX[VAR];		/* Glyphs data. */
 
   DEFINE_SIZE_ARRAY (0, dataX);
 };
 
-struct glyfGlyphHeader
-{
-  SHORT		numberOfContours;	/* If the number of contours is
-					 * greater than or equal to zero,
-					 * this is a simple glyph; if negative,
-					 * this is a composite glyph. */
-  FWORD		xMin;			/* Minimum x for coordinate data. */
-  FWORD		yMin;			/* Minimum y for coordinate data. */
-  FWORD		xMax;			/* Maximum x for coordinate data. */
-  FWORD		yMax;			/* Maximum y for coordinate data. */
-
-  DEFINE_SIZE_STATIC (10);
-};
-
 } /* namespace OT */
 
 
 #endif /* HB_OT_GLYF_TABLE_HH */
--- a/gfx/harfbuzz/src/hb-ot-head-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-head-table.hh
@@ -59,21 +59,21 @@ struct head
 		  version.major == 1 &&
 		  magicNumber == 0x5F0F3CF5u);
   }
 
   protected:
   FixedVersion<>version;		/* Version of the head table--currently
 					 * 0x00010000u for version 1.0. */
   FixedVersion<>fontRevision;		/* Set by font manufacturer. */
-  ULONG		checkSumAdjustment;	/* To compute: set it to 0, sum the
-					 * entire font as ULONG, then store
+  UINT32		checkSumAdjustment;	/* To compute: set it to 0, sum the
+					 * entire font as UINT32, then store
 					 * 0xB1B0AFBAu - sum. */
-  ULONG		magicNumber;		/* Set to 0x5F0F3CF5u. */
-  USHORT	flags;			/* Bit 0: Baseline for font at y=0;
+  UINT32		magicNumber;		/* Set to 0x5F0F3CF5u. */
+  UINT16	flags;			/* Bit 0: Baseline for font at y=0;
 					 * Bit 1: Left sidebearing point at x=0;
 					 * Bit 2: Instructions may depend on point size;
 					 * Bit 3: Force ppem to integer values for all
 					 *   internal scaler math; may use fractional
 					 *   ppem sizes if this bit is clear;
 					 * Bit 4: Instructions may alter advance width
 					 *   (the advance widths might not scale linearly);
 
@@ -109,45 +109,45 @@ struct head
 					 * Bit 14: Last Resort font. If set, indicates that
 					 * the glyphs encoded in the cmap subtables are simply
 					 * generic symbolic representations of code point
 					 * ranges and don’t truly represent support for those
 					 * code points. If unset, indicates that the glyphs
 					 * encoded in the cmap subtables represent proper
 					 * support for those code points.
 					 * Bit 15: Reserved, set to 0. */
-  USHORT	unitsPerEm;		/* Valid range is from 16 to 16384. This value
+  UINT16	unitsPerEm;		/* Valid range is from 16 to 16384. This value
 					 * should be a power of 2 for fonts that have
 					 * TrueType outlines. */
   LONGDATETIME	created;		/* Number of seconds since 12:00 midnight,
 					   January 1, 1904. 64-bit integer */
   LONGDATETIME	modified;		/* Number of seconds since 12:00 midnight,
 					   January 1, 1904. 64-bit integer */
-  SHORT		xMin;			/* For all glyph bounding boxes. */
-  SHORT		yMin;			/* For all glyph bounding boxes. */
-  SHORT		xMax;			/* For all glyph bounding boxes. */
-  SHORT		yMax;			/* For all glyph bounding boxes. */
-  USHORT	macStyle;		/* Bit 0: Bold (if set to 1);
+  INT16		xMin;			/* For all glyph bounding boxes. */
+  INT16		yMin;			/* For all glyph bounding boxes. */
+  INT16		xMax;			/* For all glyph bounding boxes. */
+  INT16		yMax;			/* For all glyph bounding boxes. */
+  UINT16	macStyle;		/* Bit 0: Bold (if set to 1);
 					 * Bit 1: Italic (if set to 1)
 					 * Bit 2: Underline (if set to 1)
 					 * Bit 3: Outline (if set to 1)
 					 * Bit 4: Shadow (if set to 1)
 					 * Bit 5: Condensed (if set to 1)
 					 * Bit 6: Extended (if set to 1)
 					 * Bits 7-15: Reserved (set to 0). */
-  USHORT	lowestRecPPEM;		/* Smallest readable size in pixels. */
-  SHORT		fontDirectionHint;	/* Deprecated (Set to 2).
+  UINT16	lowestRecPPEM;		/* Smallest readable size in pixels. */
+  INT16		fontDirectionHint;	/* Deprecated (Set to 2).
 					 * 0: Fully mixed directional glyphs;
 					 * 1: Only strongly left to right;
 					 * 2: Like 1 but also contains neutrals;
 					 * -1: Only strongly right to left;
 					 * -2: Like -1 but also contains neutrals. */
   public:
-  SHORT		indexToLocFormat;	/* 0 for short offsets, 1 for long. */
-  SHORT		glyphDataFormat;	/* 0 for current format. */
+  INT16		indexToLocFormat;	/* 0 for short offsets, 1 for long. */
+  INT16		glyphDataFormat;	/* 0 for current format. */
 
   DEFINE_SIZE_STATIC (54);
 };
 
 
 } /* namespace OT */
 
 
--- a/gfx/harfbuzz/src/hb-ot-hhea-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-hhea-table.hh
@@ -39,21 +39,16 @@ namespace OT {
  */
 
 #define HB_OT_TAG_hhea HB_TAG('h','h','e','a')
 #define HB_OT_TAG_vhea HB_TAG('v','h','e','a')
 
 
 struct _hea
 {
-  static const hb_tag_t tableTag = HB_TAG('_','h','e','a');
-
-  static const hb_tag_t hheaTag	= HB_OT_TAG_hhea;
-  static const hb_tag_t vheaTag	= HB_OT_TAG_vhea;
-
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && likely (version.major == 1));
   }
 
   public:
   FixedVersion<>version;		/* 0x00010000u for version 1.0. */
@@ -64,31 +59,31 @@ struct _hea
 					 * metrics table. */
   FWORD		minLeadingBearing;	/* Minimum left/top sidebearing value in
 					 * metrics table. */
   FWORD		minTrailingBearing;	/* Minimum right/bottom sidebearing value;
 					 * calculated as Min(aw - lsb -
 					 * (xMax - xMin)) for horizontal. */
   FWORD		maxExtent;		/* horizontal: Max(lsb + (xMax - xMin)),
 					 * vertical: minLeadingBearing+(yMax-yMin). */
-  SHORT		caretSlopeRise;		/* Used to calculate the slope of the
+  INT16		caretSlopeRise;		/* Used to calculate the slope of the
 					 * cursor (rise/run); 1 for vertical caret,
 					 * 0 for horizontal.*/
-  SHORT		caretSlopeRun;		/* 0 for vertical caret, 1 for horizontal. */
-  SHORT		caretOffset;		/* The amount by which a slanted
+  INT16		caretSlopeRun;		/* 0 for vertical caret, 1 for horizontal. */
+  INT16		caretOffset;		/* The amount by which a slanted
 					 * highlight on a glyph needs
 					 * to be shifted to produce the
 					 * best appearance. Set to 0 for
 					 * non-slanted fonts. */
-  SHORT		reserved1;		/* Set to 0. */
-  SHORT		reserved2;		/* Set to 0. */
-  SHORT		reserved3;		/* Set to 0. */
-  SHORT		reserved4;		/* Set to 0. */
-  SHORT		metricDataFormat;	/* 0 for current format. */
-  USHORT	numberOfLongMetrics;	/* Number of LongMetric entries in metric
+  INT16		reserved1;		/* Set to 0. */
+  INT16		reserved2;		/* Set to 0. */
+  INT16		reserved3;		/* Set to 0. */
+  INT16		reserved4;		/* Set to 0. */
+  INT16		metricDataFormat;	/* 0 for current format. */
+  UINT16	numberOfLongMetrics;	/* Number of LongMetric entries in metric
 					 * table. */
   public:
   DEFINE_SIZE_STATIC (36);
 };
 
 struct hhea : _hea {
   static const hb_tag_t tableTag	= HB_OT_TAG_hhea;
 };
--- a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
@@ -23,16 +23,19 @@
  *
  * Google Author(s): Behdad Esfahbod
  */
 
 #ifndef HB_OT_HMTX_TABLE_HH
 #define HB_OT_HMTX_TABLE_HH
 
 #include "hb-open-type-private.hh"
+#include "hb-ot-hhea-table.hh"
+#include "hb-ot-os2-table.hh"
+#include "hb-ot-var-hvar-table.hh"
 
 
 namespace OT {
 
 
 /*
  * hmtx -- The Horizontal Metrics Table
  * vmtx -- The Vertical Metrics Table
@@ -45,30 +48,128 @@ namespace OT {
 struct LongMetric
 {
   UFWORD	advance; /* Advance width/height. */
   FWORD		lsb; /* Leading (left/top) side bearing. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
+template <typename T>
 struct hmtxvmtx
 {
-  static const hb_tag_t hmtxTag	= HB_OT_TAG_hmtx;
-  static const hb_tag_t vmtxTag	= HB_OT_TAG_vmtx;
-
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     /* We don't check for anything specific here.  The users of the
      * struct do all the hard work... */
     return_trace (true);
   }
 
-  public:
+  struct accelerator_t
+  {
+    inline void init (hb_face_t *face,
+		      unsigned int default_advance_ = 0)
+    {
+      default_advance = default_advance_ ? default_advance_ : face->get_upem ();
+
+      bool got_font_extents = false;
+      if (T::os2Tag)
+      {
+	hb_blob_t *os2_blob = Sanitizer<os2>::sanitize (face->reference_table (T::os2Tag));
+	const os2 *os2_table = Sanitizer<os2>::lock_instance (os2_blob);
+#define USE_TYPO_METRICS (1u<<7)
+	if (0 != (os2_table->fsSelection & USE_TYPO_METRICS))
+	{
+	  ascender = os2_table->sTypoAscender;
+	  descender = os2_table->sTypoDescender;
+	  line_gap = os2_table->sTypoLineGap;
+	  got_font_extents = (ascender | descender) != 0;
+	}
+	hb_blob_destroy (os2_blob);
+      }
+
+      hb_blob_t *_hea_blob = Sanitizer<_hea>::sanitize (face->reference_table (T::headerTag));
+      const _hea *_hea_table = Sanitizer<_hea>::lock_instance (_hea_blob);
+      num_advances = _hea_table->numberOfLongMetrics;
+      if (!got_font_extents)
+      {
+	ascender = _hea_table->ascender;
+	descender = _hea_table->descender;
+	line_gap = _hea_table->lineGap;
+	got_font_extents = (ascender | descender) != 0;
+      }
+      hb_blob_destroy (_hea_blob);
+
+      has_font_extents = got_font_extents;
+
+      blob = Sanitizer<hmtxvmtx>::sanitize (face->reference_table (T::tableTag));
+
+      /* Cap num_metrics() and num_advances() based on table length. */
+      unsigned int len = hb_blob_get_length (blob);
+      if (unlikely (num_advances * 4 > len))
+	num_advances = len / 4;
+      num_metrics = num_advances + (len - 4 * num_advances) / 2;
+
+      /* We MUST set num_metrics to zero if num_advances is zero.
+       * Our get_advance() depends on that. */
+      if (unlikely (!num_advances))
+      {
+	num_metrics = num_advances = 0;
+	hb_blob_destroy (blob);
+	blob = hb_blob_get_empty ();
+      }
+      table = Sanitizer<hmtxvmtx>::lock_instance (blob);
+
+      var_blob = Sanitizer<HVARVVAR>::sanitize (face->reference_table (T::variationsTag));
+      var_table = Sanitizer<HVARVVAR>::lock_instance (var_blob);
+    }
+
+    inline void fini (void)
+    {
+      hb_blob_destroy (blob);
+      hb_blob_destroy (var_blob);
+    }
+
+    inline unsigned int get_advance (hb_codepoint_t  glyph,
+				     hb_font_t      *font) const
+    {
+      if (unlikely (glyph >= num_metrics))
+      {
+	/* If num_metrics is zero, it means we don't have the metrics table
+	 * for this direction: return default advance.  Otherwise, it means that the
+	 * glyph index is out of bound: return zero. */
+	if (num_metrics)
+	  return 0;
+	else
+	  return default_advance;
+      }
+
+      return table->longMetric[MIN (glyph, (uint32_t) num_advances - 1)].advance
+	   + var_table->get_advance_var (glyph, font->coords, font->num_coords); // TODO Optimize?!
+    }
+
+    public:
+    bool has_font_extents;
+    unsigned short ascender;
+    unsigned short descender;
+    unsigned short line_gap;
+
+    private:
+    unsigned int num_metrics;
+    unsigned int num_advances;
+    unsigned int default_advance;
+
+    const hmtxvmtx *table;
+    hb_blob_t *blob;
+    const HVARVVAR *var_table;
+    hb_blob_t *var_blob;
+  };
+
+  protected:
   LongMetric	longMetric[VAR];	/* Paired advance width and leading
 					 * bearing values for each glyph. The
 					 * value numOfHMetrics comes from
 					 * the 'hhea' table. If the font is
 					 * monospaced, only one entry need
 					 * be in the array, but that entry is
 					 * required. The last entry applies to
 					 * all subsequent glyphs. */
@@ -84,19 +185,25 @@ struct hmtxvmtx
 					 * run is allowed and it must be at
 					 * the end. This allows a monospaced
 					 * font to vary the side bearing
 					 * values for each glyph. */
   public:
   DEFINE_SIZE_ARRAY2 (0, longMetric, leadingBearingX);
 };
 
-struct hmtx : hmtxvmtx {
+struct hmtx : hmtxvmtx<hmtx> {
   static const hb_tag_t tableTag	= HB_OT_TAG_hmtx;
+  static const hb_tag_t headerTag	= HB_OT_TAG_hhea;
+  static const hb_tag_t variationsTag	= HB_OT_TAG_HVAR;
+  static const hb_tag_t os2Tag		= HB_OT_TAG_os2;
 };
-struct vmtx : hmtxvmtx {
+struct vmtx : hmtxvmtx<vmtx> {
   static const hb_tag_t tableTag	= HB_OT_TAG_vmtx;
+  static const hb_tag_t headerTag	= HB_OT_TAG_vhea;
+  static const hb_tag_t variationsTag	= HB_OT_TAG_VVAR;
+  static const hb_tag_t os2Tag		= HB_TAG_NONE;
 };
 
 } /* namespace OT */
 
 
 #endif /* HB_OT_HMTX_TABLE_HH */
--- a/gfx/harfbuzz/src/hb-ot-kern-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-kern-table.hh
@@ -99,18 +99,18 @@ struct KernClassTable
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (firstGlyph.sanitize (c) && classes.sanitize (c));
   }
 
   protected:
-  USHORT		firstGlyph;	/* First glyph in class range. */
-  ArrayOf<USHORT>	classes;	/* Glyph classes. */
+  UINT16		firstGlyph;	/* First glyph in class range. */
+  ArrayOf<UINT16>	classes;	/* Glyph classes. */
   public:
   DEFINE_SIZE_ARRAY (4, classes);
 };
 
 struct KernSubTableFormat2
 {
   inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
   {
@@ -131,17 +131,17 @@ struct KernSubTableFormat2
     TRACE_SANITIZE (this);
     return_trace (rowWidth.sanitize (c) &&
 		  leftClassTable.sanitize (c, this) &&
 		  rightClassTable.sanitize (c, this) &&
 		  array.sanitize (c, this));
   }
 
   protected:
-  USHORT	rowWidth;	/* The width, in bytes, of a row in the table. */
+  UINT16	rowWidth;	/* The width, in bytes, of a row in the table. */
   OffsetTo<KernClassTable>
 		leftClassTable;	/* Offset from beginning of this subtable to
 				 * left-hand class table. */
   OffsetTo<KernClassTable>
 		rightClassTable;/* Offset from beginning of this subtable to
 				 * right-hand class table. */
   OffsetTo<FWORD>
 		array;		/* Offset from beginning of this subtable to
@@ -270,29 +270,29 @@ struct KernOT : KernTable<KernOT>
 
       COVERAGE_VARIATION_FLAG	= 0x00u, /* Not supported. */
 
       COVERAGE_CHECK_FLAGS	= 0x07u,
       COVERAGE_CHECK_HORIZONTAL	= 0x01u
     };
 
     protected:
-    USHORT	versionZ;	/* Unused. */
-    USHORT	length;		/* Length of the subtable (including this header). */
-    BYTE	format;		/* Subtable format. */
-    BYTE	coverage;	/* Coverage bits. */
+    UINT16	versionZ;	/* Unused. */
+    UINT16	length;		/* Length of the subtable (including this header). */
+    UINT8	format;		/* Subtable format. */
+    UINT8	coverage;	/* Coverage bits. */
     KernSubTable subtable;	/* Subtable data. */
     public:
     DEFINE_SIZE_MIN (6);
   };
 
   protected:
-  USHORT	version;	/* Version--0x0000u */
-  USHORT	nTables;	/* Number of subtables in the kerning table. */
-  BYTE		data[VAR];
+  UINT16	version;	/* Version--0x0000u */
+  UINT16	nTables;	/* Number of subtables in the kerning table. */
+  UINT8		data[VAR];
   public:
   DEFINE_SIZE_ARRAY (4, data);
 };
 
 struct KernAAT : KernTable<KernAAT>
 {
   friend struct KernTable<KernAAT>;
 
@@ -309,30 +309,30 @@ struct KernAAT : KernTable<KernAAT>
 
       COVERAGE_OVERRIDE_FLAG	= 0x00u, /* Not supported. */
 
       COVERAGE_CHECK_FLAGS	= 0xE0u,
       COVERAGE_CHECK_HORIZONTAL	= 0x00u
     };
 
     protected:
-    ULONG	length;		/* Length of the subtable (including this header). */
-    BYTE	coverage;	/* Coverage bits. */
-    BYTE	format;		/* Subtable format. */
-    USHORT	tupleIndex;	/* The tuple index (used for variations fonts).
+    UINT32	length;		/* Length of the subtable (including this header). */
+    UINT8	coverage;	/* Coverage bits. */
+    UINT8	format;		/* Subtable format. */
+    UINT16	tupleIndex;	/* The tuple index (used for variations fonts).
 				 * This value specifies which tuple this subtable covers. */
     KernSubTable subtable;	/* Subtable data. */
     public:
     DEFINE_SIZE_MIN (8);
   };
 
   protected:
-  ULONG		version;	/* Version--0x00010000u */
-  ULONG		nTables;	/* Number of subtables in the kerning table. */
-  BYTE		data[VAR];
+  UINT32		version;	/* Version--0x00010000u */
+  UINT32		nTables;	/* Number of subtables in the kerning table. */
+  UINT8		data[VAR];
   public:
   DEFINE_SIZE_ARRAY (8, data);
 };
 
 struct kern
 {
   static const hb_tag_t tableTag = HB_OT_TAG_kern;
 
@@ -353,34 +353,39 @@ struct kern
     case 0: return_trace (u.ot.sanitize (c));
     case 1: return_trace (u.aat.sanitize (c));
     default:return_trace (true);
     }
   }
 
   struct accelerator_t
   {
-    inline void init (const kern *table_, unsigned int table_length_)
+    inline void init (hb_face_t *face)
     {
-      table = table_;
-      table_length = table_length_;
+      blob = Sanitizer<kern>::sanitize (face->reference_table (HB_OT_TAG_kern));
+      table = Sanitizer<kern>::lock_instance (blob);
+      table_length = hb_blob_get_length (blob);
     }
-    inline void fini (void) {}
+    inline void fini (void)
+    {
+      hb_blob_destroy (blob);
+    }
 
     inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
     { return table->get_h_kerning (left, right, table_length); }
 
     private:
+    hb_blob_t *blob;
     const kern *table;
     unsigned int table_length;
   };
 
   protected:
   union {
-  USHORT		major;
+  UINT16		major;
   KernOT		ot;
   KernAAT		aat;
   } u;
   public:
   DEFINE_SIZE_UNION (2, major);
 };
 
 } /* namespace OT */
--- a/gfx/harfbuzz/src/hb-ot-layout-common-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-common-private.hh
@@ -156,31 +156,31 @@ struct RangeRecord
 
   template <typename set_t>
   inline void add_coverage (set_t *glyphs) const {
     glyphs->add_range (start, end);
   }
 
   GlyphID	start;		/* First GlyphID in the range */
   GlyphID	end;		/* Last GlyphID in the range */
-  USHORT	value;		/* Value */
+  UINT16	value;		/* Value */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 DEFINE_NULL_DATA (RangeRecord, "\000\001");
 
 
 struct IndexArray : ArrayOf<Index>
 {
   inline unsigned int get_indexes (unsigned int start_offset,
 				   unsigned int *_count /* IN/OUT */,
 				   unsigned int *_indexes /* OUT */) const
   {
     if (_count) {
-      const USHORT *arr = this->sub_array (start_offset, _count);
+      const UINT16 *arr = this->sub_array (start_offset, _count);
       unsigned int count = *_count;
       for (unsigned int i = 0; i < count; i++)
 	_indexes[i] = arr[i];
     }
     return this->len;
   }
 };
 
@@ -211,19 +211,19 @@ struct LangSys
 
   inline bool sanitize (hb_sanitize_context_t *c,
 			const Record<LangSys>::sanitize_closure_t * = nullptr) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && featureIndex.sanitize (c));
   }
 
-  Offset<>	lookupOrderZ;	/* = Null (reserved for an offset to a
+  Offset16	lookupOrderZ;	/* = Null (reserved for an offset to a
 				 * reordering table) */
-  USHORT	reqFeatureIndex;/* Index of a feature required for this
+  UINT16	reqFeatureIndex;/* Index of a feature required for this
 				 * language system--if no required features
 				 * = 0xFFFFu */
   IndexArray	featureIndex;	/* Array of indices into the FeatureList */
   public:
   DEFINE_SIZE_ARRAY (6, featureIndex);
 };
 DEFINE_NULL_DATA (LangSys, "\0\0\xFF\xFF");
 
@@ -338,49 +338,49 @@ struct FeatureParamsSize
 	     designSize > rangeEnd ||
 	     subfamilyNameID < 256 ||
 	     subfamilyNameID > 32767)
       return_trace (false);
     else
       return_trace (true);
   }
 
-  USHORT	designSize;	/* Represents the design size in 720/inch
+  UINT16	designSize;	/* Represents the design size in 720/inch
 				 * units (decipoints).  The design size entry
 				 * must be non-zero.  When there is a design
 				 * size but no recommended size range, the
 				 * rest of the array will consist of zeros. */
-  USHORT	subfamilyID;	/* Has no independent meaning, but serves
+  UINT16	subfamilyID;	/* Has no independent meaning, but serves
 				 * as an identifier that associates fonts
 				 * in a subfamily. All fonts which share a
 				 * Preferred or Font Family name and which
 				 * differ only by size range shall have the
 				 * same subfamily value, and no fonts which
 				 * differ in weight or style shall have the
 				 * same subfamily value. If this value is
 				 * zero, the remaining fields in the array
 				 * will be ignored. */
-  USHORT	subfamilyNameID;/* If the preceding value is non-zero, this
+  UINT16	subfamilyNameID;/* If the preceding value is non-zero, this
 				 * value must be set in the range 256 - 32767
 				 * (inclusive). It records the value of a
 				 * field in the name table, which must
 				 * contain English-language strings encoded
 				 * in Windows Unicode and Macintosh Roman,
 				 * and may contain additional strings
 				 * localized to other scripts and languages.
 				 * Each of these strings is the name an
 				 * application should use, in combination
 				 * with the family name, to represent the
 				 * subfamily in a menu.  Applications will
 				 * choose the appropriate version based on
 				 * their selection criteria. */
-  USHORT	rangeStart;	/* Large end of the recommended usage range
+  UINT16	rangeStart;	/* Large end of the recommended usage range
 				 * (inclusive), stored in 720/inch units
 				 * (decipoints). */
-  USHORT	rangeEnd;	/* Small end of the recommended usage range
+  UINT16	rangeEnd;	/* Small end of the recommended usage range
 				   (exclusive), stored in 720/inch units
 				 * (decipoints). */
   public:
   DEFINE_SIZE_STATIC (10);
 };
 
 /* http://www.microsoft.com/typography/otspec/features_pt.htm#ssxx */
 struct FeatureParamsStylisticSet
@@ -388,22 +388,22 @@ struct FeatureParamsStylisticSet
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     /* Right now minorVersion is at zero.  Which means, any table supports
      * the uiNameID field. */
     return_trace (c->check_struct (this));
   }
 
-  USHORT	version;	/* (set to 0): This corresponds to a “minor”
+  UINT16	version;	/* (set to 0): This corresponds to a “minor”
 				 * version number. Additional data may be
 				 * added to the end of this Feature Parameters
 				 * table in the future. */
 
-  USHORT	uiNameID;	/* The 'name' table name ID that specifies a
+  UINT16	uiNameID;	/* The 'name' table name ID that specifies a
 				 * string (or strings, for multiple languages)
 				 * for a user-interface label for this
 				 * feature.  The values of uiLabelNameId and
 				 * sampleTextNameId are expected to be in the
 				 * font-specific name ID range (256-32767),
 				 * though that is not a requirement in this
 				 * Feature Parameters specification. The
 				 * user-interface label for the feature can
@@ -421,35 +421,35 @@ struct FeatureParamsCharacterVariants
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  characters.sanitize (c));
   }
 
-  USHORT	format;			/* Format number is set to 0. */
-  USHORT	featUILableNameID;	/* The ‘name’ table name ID that
+  UINT16	format;			/* Format number is set to 0. */
+  UINT16	featUILableNameID;	/* The ‘name’ table name ID that
 					 * specifies a string (or strings,
 					 * for multiple languages) for a
 					 * user-interface label for this
 					 * feature. (May be nullptr.) */
-  USHORT	featUITooltipTextNameID;/* The ‘name’ table name ID that
+  UINT16	featUITooltipTextNameID;/* The ‘name’ table name ID that
 					 * specifies a string (or strings,
 					 * for multiple languages) that an
 					 * application can use for tooltip
 					 * text for this feature. (May be
 					 * nullptr.) */
-  USHORT	sampleTextNameID;	/* The ‘name’ table name ID that
+  UINT16	sampleTextNameID;	/* The ‘name’ table name ID that
 					 * specifies sample text that
 					 * illustrates the effect of this
 					 * feature. (May be nullptr.) */
-  USHORT	numNamedParameters;	/* Number of named parameters. (May
+  UINT16	numNamedParameters;	/* Number of named parameters. (May
 					 * be zero.) */
-  USHORT	firstParamUILabelNameID;/* The first ‘name’ table name ID
+  UINT16	firstParamUILabelNameID;/* The first ‘name’ table name ID
 					 * used to specify strings for
 					 * user-interface labels for the
 					 * feature parameters. (Must be zero
 					 * if numParameters is zero.) */
   ArrayOf<UINT24>
 		characters;		/* Array of the Unicode Scalar Value
 					 * of the characters for which this
 					 * feature provides glyph variants.
@@ -557,17 +557,17 @@ struct Feature
   IndexArray	 lookupIndex;	/* Array of LookupList indices */
   public:
   DEFINE_SIZE_ARRAY (4, lookupIndex);
 };
 
 typedef RecordListOf<Feature> FeatureList;
 
 
-struct LookupFlag : USHORT
+struct LookupFlag : UINT16
 {
   enum Flags {
     RightToLeft		= 0x0001u,
     IgnoreBaseGlyphs	= 0x0002u,
     IgnoreLigatures	= 0x0004u,
     IgnoreMarks		= 0x0008u,
     IgnoreFlags		= 0x000Eu,
     UseMarkFilteringSet	= 0x0010u,
@@ -603,17 +603,17 @@ struct Lookup
   /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
    * higher 16-bit is mark-filtering-set if the lookup uses one.
    * Not to be confused with glyph_props which is very similar. */
   inline uint32_t get_props (void) const
   {
     unsigned int flag = lookupFlag;
     if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
     {
-      const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
+      const UINT16 &markFilteringSet = StructAfter<UINT16> (subTable);
       flag += (markFilteringSet << 16);
     }
     return flag;
   }
 
   template <typename SubTableType, typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
@@ -635,41 +635,41 @@ struct Lookup
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
     lookupType.set (lookup_type);
     lookupFlag.set (lookup_props & 0xFFFFu);
     if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
     {
-      USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
+      UINT16 &markFilteringSet = StructAfter<UINT16> (subTable);
       markFilteringSet.set (lookup_props >> 16);
     }
     return_trace (true);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     /* Real sanitize of the subtables is done by GSUB/GPOS/... */
     if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
     {
-      const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
+      const UINT16 &markFilteringSet = StructAfter<UINT16> (subTable);
       if (!markFilteringSet.sanitize (c)) return_trace (false);
     }
     return_trace (true);
   }
 
   private:
-  USHORT	lookupType;		/* Different enumerations for GSUB and GPOS */
-  USHORT	lookupFlag;		/* Lookup qualifiers */
-  ArrayOf<Offset<> >
+  UINT16	lookupType;		/* Different enumerations for GSUB and GPOS */
+  UINT16	lookupFlag;		/* Lookup qualifiers */
+  ArrayOf<Offset16>
 		subTable;		/* Array of SubTables */
-  USHORT	markFilteringSetX[VAR];	/* Index (base 0) into GDEF mark glyph sets
+  UINT16	markFilteringSetX[VAR];	/* Index (base 0) into GDEF mark glyph sets
 					 * structure. This field is only present if bit
 					 * UseMarkFilteringSet of lookup flags is set. */
   public:
   DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX);
 };
 
 typedef OffsetListOf<Lookup> LookupList;
 
@@ -732,17 +732,17 @@ struct CoverageFormat1
 
     private:
     const struct CoverageFormat1 *c;
     unsigned int i;
   };
   private:
 
   protected:
-  USHORT	coverageFormat;	/* Format identifier--format = 1 */
+  UINT16	coverageFormat;	/* Format identifier--format = 1 */
   SortedArrayOf<GlyphID>
 		glyphArray;	/* Array of GlyphIDs--in numerical order */
   public:
   DEFINE_SIZE_ARRAY (4, glyphArray);
 };
 
 struct CoverageFormat2
 {
@@ -855,17 +855,17 @@ struct CoverageFormat2
 
     private:
     const struct CoverageFormat2 *c;
     unsigned int i, j, coverage;
   };
   private:
 
   protected:
-  USHORT	coverageFormat;	/* Format identifier--format = 2 */
+  UINT16	coverageFormat;	/* Format identifier--format = 2 */
   SortedArrayOf<RangeRecord>
 		rangeRecord;	/* Array of glyph ranges--ordered by
 				 * Start GlyphID. rangeCount entries
 				 * long */
   public:
   DEFINE_SIZE_ARRAY (4, rangeRecord);
 };
 
@@ -980,17 +980,17 @@ struct Coverage
     union {
     CoverageFormat2::Iter	format2; /* Put this one first since it's larger; helps shut up compiler. */
     CoverageFormat1::Iter	format1;
     } u;
   };
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   CoverageFormat1	format1;
   CoverageFormat2	format2;
   } u;
   public:
   DEFINE_SIZE_UNION (2, format);
 };
 
 
@@ -1042,19 +1042,19 @@ struct ClassDefFormat1
     }
     for (unsigned int i = 0; i < count; i++)
       if (classValue[i] == klass && glyphs->has (startGlyph + i))
         return true;
     return false;
   }
 
   protected:
-  USHORT	classFormat;		/* Format identifier--format = 1 */
+  UINT16	classFormat;		/* Format identifier--format = 1 */
   GlyphID	startGlyph;		/* First GlyphID of the classValueArray */
-  ArrayOf<USHORT>
+  ArrayOf<UINT16>
 		classValue;		/* Array of Class Values--one per GlyphID */
   public:
   DEFINE_SIZE_ARRAY (6, classValue);
 };
 
 struct ClassDefFormat2
 {
   friend struct ClassDef;
@@ -1102,17 +1102,17 @@ struct ClassDefFormat2
     }
     for (unsigned int i = 0; i < count; i++)
       if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
         return true;
     return false;
   }
 
   protected:
-  USHORT	classFormat;	/* Format identifier--format = 2 */
+  UINT16	classFormat;	/* Format identifier--format = 2 */
   SortedArrayOf<RangeRecord>
 		rangeRecord;	/* Array of glyph ranges--ordered by
 				 * Start GlyphID */
   public:
   DEFINE_SIZE_ARRAY (4, rangeRecord);
 };
 
 struct ClassDef
@@ -1150,17 +1150,17 @@ struct ClassDef
     case 1: return u.format1.intersects_class (glyphs, klass);
     case 2: return u.format2.intersects_class (glyphs, klass);
     default:return false;
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   ClassDefFormat1	format1;
   ClassDefFormat2	format2;
   } u;
   public:
   DEFINE_SIZE_UNION (2, format);
 };
 
 
@@ -1235,18 +1235,18 @@ struct VarRegionList
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  c->check_array (axesZ, axesZ[0].static_size,
 				  (unsigned int) axisCount * (unsigned int) regionCount));
   }
 
   protected:
-  USHORT	axisCount;
-  USHORT	regionCount;
+  UINT16	axisCount;
+  UINT16	regionCount;
   VarRegionAxis	axesZ[VAR];
   public:
   DEFINE_SIZE_ARRAY (4, axesZ);
 };
 
 struct VarData
 {
   inline unsigned int get_row_size (void) const
@@ -1260,23 +1260,23 @@ struct VarData
 			  const VarRegionList &regions) const
   {
     if (unlikely (inner >= itemCount))
       return 0.;
 
    unsigned int count = regionIndices.len;
    unsigned int scount = shortCount;
 
-   const BYTE *bytes = &StructAfter<BYTE> (regionIndices);
-   const BYTE *row = bytes + inner * (scount + count);
+   const UINT8 *bytes = &StructAfter<UINT8> (regionIndices);
+   const UINT8 *row = bytes + inner * (scount + count);
 
    float delta = 0.;
    unsigned int i = 0;
 
-   const SHORT *scursor = reinterpret_cast<const SHORT *> (row);
+   const INT16 *scursor = reinterpret_cast<const INT16 *> (row);
    for (; i < scount; i++)
    {
      float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count);
      delta += scalar * *scursor++;
    }
    const INT8 *bcursor = reinterpret_cast<const INT8 *> (scursor);
    for (; i < count; i++)
    {
@@ -1288,25 +1288,25 @@ struct VarData
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  regionIndices.sanitize(c) &&
 		  shortCount <= regionIndices.len &&
-		  c->check_array (&StructAfter<BYTE> (regionIndices),
+		  c->check_array (&StructAfter<UINT8> (regionIndices),
 				  get_row_size (), itemCount));
   }
 
   protected:
-  USHORT		itemCount;
-  USHORT		shortCount;
-  ArrayOf<USHORT>	regionIndices;
-  BYTE			bytesX[VAR];
+  UINT16		itemCount;
+  UINT16		shortCount;
+  ArrayOf<UINT16>	regionIndices;
+  UINT8			bytesX[VAR];
   public:
   DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX);
 };
 
 struct VariationStore
 {
   inline float get_delta (unsigned int outer, unsigned int inner,
 			  int *coords, unsigned int coord_count) const
@@ -1332,19 +1332,19 @@ struct VariationStore
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  format == 1 &&
 		  regions.sanitize (c, this) &&
 		  dataSets.sanitize (c, this));
   }
 
   protected:
-  USHORT				format;
+  UINT16				format;
   LOffsetTo<VarRegionList>		regions;
-  OffsetArrayOf<VarData, ULONG>		dataSets;
+  OffsetArrayOf<VarData, UINT32>		dataSets;
   public:
   DEFINE_SIZE_ARRAY (8, dataSets);
 };
 
 /*
  * Feature Variations
  */
 
@@ -1361,18 +1361,18 @@ struct ConditionFormat1
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   protected:
-  USHORT	format;		/* Format identifier--format = 1 */
-  USHORT	axisIndex;
+  UINT16	format;		/* Format identifier--format = 1 */
+  UINT16	axisIndex;
   F2DOT14	filterRangeMinValue;
   F2DOT14	filterRangeMaxValue;
   public:
   DEFINE_SIZE_STATIC (8);
 };
 
 struct Condition
 {
@@ -1391,17 +1391,17 @@ struct Condition
     switch (u.format) {
     case 1: return_trace (u.format1.sanitize (c));
     default:return_trace (true);
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   ConditionFormat1	format1;
   } u;
   public:
   DEFINE_SIZE_UNION (2, format);
 };
 
 struct ConditionSet
 {
@@ -1416,33 +1416,33 @@ struct ConditionSet
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (conditions.sanitize (c, this));
   }
 
   protected:
-  OffsetArrayOf<Condition, ULONG> conditions;
+  OffsetArrayOf<Condition, UINT32> conditions;
   public:
   DEFINE_SIZE_ARRAY (2, conditions);
 };
 
 struct FeatureTableSubstitutionRecord
 {
   friend struct FeatureTableSubstitution;
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && feature.sanitize (c, base));
   }
 
   protected:
-  USHORT		featureIndex;
+  UINT16		featureIndex;
   LOffsetTo<Feature>	feature;
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
 struct FeatureTableSubstitution
 {
   inline const Feature *find_substitute (unsigned int feature_index) const
@@ -1552,18 +1552,18 @@ struct HintingDevice
   { return get_delta (font->x_ppem, font->x_scale); }
 
   inline hb_position_t get_y_delta (hb_font_t *font) const
   { return get_delta (font->y_ppem, font->y_scale); }
 
   inline unsigned int get_size (void) const
   {
     unsigned int f = deltaFormat;
-    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size;
-    return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f)));
+    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * UINT16::static_size;
+    return UINT16::static_size * (4 + ((endSize - startSize) >> (4 - f)));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
   }
 
@@ -1598,24 +1598,24 @@ struct HintingDevice
 
     if ((unsigned int) delta >= ((mask + 1) >> 1))
       delta -= mask + 1;
 
     return delta;
   }
 
   protected:
-  USHORT	startSize;		/* Smallest size to correct--in ppem */
-  USHORT	endSize;		/* Largest size to correct--in ppem */
-  USHORT	deltaFormat;		/* Format of DeltaValue array data: 1, 2, or 3
+  UINT16	startSize;		/* Smallest size to correct--in ppem */
+  UINT16	endSize;		/* Largest size to correct--in ppem */
+  UINT16	deltaFormat;		/* Format of DeltaValue array data: 1, 2, or 3
 					 * 1	Signed 2-bit value, 8 values per uint16
 					 * 2	Signed 4-bit value, 4 values per uint16
 					 * 3	Signed 8-bit value, 2 values per uint16
 					 */
-  USHORT	deltaValue[VAR];	/* Array of compressed data */
+  UINT16	deltaValue[VAR];	/* Array of compressed data */
   public:
   DEFINE_SIZE_ARRAY (6, deltaValue);
 };
 
 struct VariationDevice
 {
   friend struct Device;
 
@@ -1636,30 +1636,30 @@ struct VariationDevice
   private:
 
   inline float get_delta (hb_font_t *font, const VariationStore &store) const
   {
     return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords);
   }
 
   protected:
-  USHORT	outerIndex;
-  USHORT	innerIndex;
-  USHORT	deltaFormat;	/* Format identifier for this table: 0x0x8000 */
+  UINT16	outerIndex;
+  UINT16	innerIndex;
+  UINT16	deltaFormat;	/* Format identifier for this table: 0x0x8000 */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
 struct DeviceHeader
 {
   protected:
-  USHORT		reserved1;
-  USHORT		reserved2;
+  UINT16		reserved1;
+  UINT16		reserved2;
   public:
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
 struct Device
 {
   inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const
   {
--- a/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh
@@ -36,17 +36,17 @@
 
 namespace OT {
 
 
 /*
  * Attachment List Table
  */
 
-typedef ArrayOf<USHORT> AttachPoint;	/* Array of contour point indices--in
+typedef ArrayOf<UINT16> AttachPoint;	/* Array of contour point indices--in
 					 * increasing numerical order */
 
 struct AttachList
 {
   inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
 					 unsigned int start_offset,
 					 unsigned int *point_count /* IN/OUT */,
 					 unsigned int *point_array /* OUT */) const
@@ -57,17 +57,17 @@ struct AttachList
       if (point_count)
 	*point_count = 0;
       return 0;
     }
 
     const AttachPoint &points = this+attachPoint[index];
 
     if (point_count) {
-      const USHORT *array = points.sub_array (start_offset, point_count);
+      const UINT16 *array = points.sub_array (start_offset, point_count);
       unsigned int count = *point_count;
       for (unsigned int i = 0; i < count; i++)
 	point_array[i] = array[i];
     }
 
     return points.len;
   }
 
@@ -104,18 +104,18 @@ struct CaretValueFormat1
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   protected:
-  USHORT	caretValueFormat;	/* Format identifier--format = 1 */
-  SHORT		coordinate;		/* X or Y value, in design units */
+  UINT16	caretValueFormat;	/* Format identifier--format = 1 */
+  INT16		coordinate;		/* X or Y value, in design units */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 struct CaretValueFormat2
 {
   friend struct CaretValue;
 
@@ -131,18 +131,18 @@ struct CaretValueFormat2
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   protected:
-  USHORT	caretValueFormat;	/* Format identifier--format = 2 */
-  USHORT	caretValuePoint;	/* Contour point index on glyph */
+  UINT16	caretValueFormat;	/* Format identifier--format = 2 */
+  UINT16	caretValuePoint;	/* Contour point index on glyph */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 struct CaretValueFormat3
 {
   friend struct CaretValue;
 
@@ -155,18 +155,18 @@ struct CaretValueFormat3
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
   }
 
   protected:
-  USHORT	caretValueFormat;	/* Format identifier--format = 3 */
-  SHORT		coordinate;		/* X or Y value, in design units */
+  UINT16	caretValueFormat;	/* Format identifier--format = 3 */
+  INT16		coordinate;		/* X or Y value, in design units */
   OffsetTo<Device>
 		deviceTable;		/* Offset to Device table for X or Y
 					 * value--from beginning of CaretValue
 					 * table */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
@@ -194,17 +194,17 @@ struct CaretValue
     case 2: return_trace (u.format2.sanitize (c));
     case 3: return_trace (u.format3.sanitize (c));
     default:return_trace (true);
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   CaretValueFormat1	format1;
   CaretValueFormat2	format2;
   CaretValueFormat3	format3;
   } u;
   public:
   DEFINE_SIZE_UNION (2, format);
 };
 
@@ -289,17 +289,17 @@ struct MarkGlyphSetsFormat1
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   ArrayOf<LOffsetTo<Coverage> >
 		coverage;		/* Array of long offsets to mark set
 					 * coverage tables */
   public:
   DEFINE_SIZE_ARRAY (4, coverage);
 };
 
 struct MarkGlyphSets
@@ -319,17 +319,17 @@ struct MarkGlyphSets
     switch (u.format) {
     case 1: return_trace (u.format1.sanitize (c));
     default:return_trace (true);
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   MarkGlyphSetsFormat1	format1;
   } u;
   public:
   DEFINE_SIZE_UNION (2, format);
 };
 
 
 /*
--- a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
@@ -46,21 +46,21 @@ enum attach_type_t {
   /* Each attachment should be either a mark or a cursive; can't be both. */
   ATTACH_TYPE_MARK	= 0X01,
   ATTACH_TYPE_CURSIVE	= 0X02,
 };
 
 
 /* Shared Tables: ValueRecord, Anchor Table, and MarkArray */
 
-typedef USHORT Value;
+typedef UINT16 Value;
 
 typedef Value ValueRecord[VAR];
 
-struct ValueFormat : USHORT
+struct ValueFormat : UINT16
 {
   enum Flags {
     xPlacement	= 0x0001u,	/* Includes horizontal adjustment for placement */
     yPlacement	= 0x0002u,	/* Includes vertical adjustment for placement */
     xAdvance	= 0x0004u,	/* Includes horizontal adjustment for advance */
     yAdvance	= 0x0008u,	/* Includes vertical adjustment for advance */
     xPlaDevice	= 0x0010u,	/* Includes horizontal Device table for placement */
     yPlaDevice	= 0x0020u,	/* Includes vertical Device table for placement */
@@ -69,24 +69,24 @@ struct ValueFormat : USHORT
     ignored	= 0x0F00u,	/* Was used in TrueType Open for MM fonts */
     reserved	= 0xF000u,	/* For future use */
 
     devices	= 0x00F0u	/* Mask for having any Device table */
   };
 
 /* All fields are options.  Only those available advance the value pointer. */
 #if 0
-  SHORT		xPlacement;		/* Horizontal adjustment for
+  INT16		xPlacement;		/* Horizontal adjustment for
 					 * placement--in design units */
-  SHORT		yPlacement;		/* Vertical adjustment for
+  INT16		yPlacement;		/* Vertical adjustment for
 					 * placement--in design units */
-  SHORT		xAdvance;		/* Horizontal adjustment for
+  INT16		xAdvance;		/* Horizontal adjustment for
 					 * advance--in design units (only used
 					 * for horizontal writing) */
-  SHORT		yAdvance;		/* Vertical adjustment for advance--in
+  INT16		yAdvance;		/* Vertical adjustment for advance--in
 					 * design units (only used for vertical
 					 * writing) */
   Offset	xPlaDevice;		/* Offset to Device table for
 					 * horizontal placement--measured from
 					 * beginning of PosTable (may be NULL) */
   Offset	yPlaDevice;		/* Offset to Device table for vertical
 					 * placement--measured from beginning
 					 * of PosTable (may be NULL) */
@@ -173,18 +173,18 @@ struct ValueFormat : USHORT
     return true;
   }
 
   static inline OffsetTo<Device>& get_device (Value* value)
   { return *CastP<OffsetTo<Device> > (value); }
   static inline const OffsetTo<Device>& get_device (const Value* value)
   { return *CastP<OffsetTo<Device> > (value); }
 
-  static inline const SHORT& get_short (const Value* value)
-  { return *CastP<SHORT> (value); }
+  static inline const INT16& get_short (const Value* value)
+  { return *CastP<INT16> (value); }
 
   public:
 
   inline bool has_device (void) const {
     unsigned int format = *this;
     return (format & devices) != 0;
   }
 
@@ -242,19 +242,19 @@ struct AnchorFormat1
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
-  SHORT		xCoordinate;		/* Horizontal value--in design units */
-  SHORT		yCoordinate;		/* Vertical value--in design units */
+  UINT16	format;			/* Format identifier--format = 1 */
+  INT16		xCoordinate;		/* Horizontal value--in design units */
+  INT16		yCoordinate;		/* Vertical value--in design units */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
 struct AnchorFormat2
 {
   inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id,
 			  hb_position_t *x, hb_position_t *y) const
@@ -273,20 +273,20 @@ struct AnchorFormat2
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 2 */
-  SHORT		xCoordinate;		/* Horizontal value--in design units */
-  SHORT		yCoordinate;		/* Vertical value--in design units */
-  USHORT	anchorPoint;		/* Index to glyph contour point */
+  UINT16	format;			/* Format identifier--format = 2 */
+  INT16		xCoordinate;		/* Horizontal value--in design units */
+  INT16		yCoordinate;		/* Vertical value--in design units */
+  UINT16	anchorPoint;		/* Index to glyph contour point */
   public:
   DEFINE_SIZE_STATIC (8);
 };
 
 struct AnchorFormat3
 {
   inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
 			  hb_position_t *x, hb_position_t *y) const
@@ -303,19 +303,19 @@ struct AnchorFormat3
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 3 */
-  SHORT		xCoordinate;		/* Horizontal value--in design units */
-  SHORT		yCoordinate;		/* Vertical value--in design units */
+  UINT16	format;			/* Format identifier--format = 3 */
+  INT16		xCoordinate;		/* Horizontal value--in design units */
+  INT16		yCoordinate;		/* Vertical value--in design units */
   OffsetTo<Device>
 		xDeviceTable;		/* Offset to Device table for X
 					 * coordinate-- from beginning of
 					 * Anchor table (may be NULL) */
   OffsetTo<Device>
 		yDeviceTable;		/* Offset to Device table for Y
 					 * coordinate-- from beginning of
 					 * Anchor table (may be NULL) */
@@ -346,17 +346,17 @@ struct Anchor
     case 2: return_trace (u.format2.sanitize (c));
     case 3: return_trace (u.format3.sanitize (c));
     default:return_trace (true);
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   AnchorFormat1		format1;
   AnchorFormat2		format2;
   AnchorFormat3		format3;
   } u;
   public:
   DEFINE_SIZE_UNION (2, format);
 };
 
@@ -377,17 +377,17 @@ struct AnchorMatrix
     if (unlikely (_hb_unsigned_int_mul_overflows (rows, cols))) return_trace (false);
     unsigned int count = rows * cols;
     if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false);
     for (unsigned int i = 0; i < count; i++)
       if (!matrixZ[i].sanitize (c, this)) return_trace (false);
     return_trace (true);
   }
 
-  USHORT	rows;			/* Number of rows */
+  UINT16	rows;			/* Number of rows */
   protected:
   OffsetTo<Anchor>
 		matrixZ[VAR];		/* Matrix of offsets to Anchor tables--
 					 * from beginning of AnchorMatrix table */
   public:
   DEFINE_SIZE_ARRAY (2, matrixZ);
 };
 
@@ -398,17 +398,17 @@ struct MarkRecord
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
   }
 
   protected:
-  USHORT	klass;			/* Class defined for this mark */
+  UINT16	klass;			/* Class defined for this mark */
   OffsetTo<Anchor>
 		markAnchor;		/* Offset to Anchor table--from
 					 * beginning of MarkArray table */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 struct MarkArray : ArrayOf<MarkRecord>	/* Array of MarkRecords--in Coverage order */
@@ -487,17 +487,17 @@ struct SinglePosFormat1
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  coverage.sanitize (c, this) &&
 		  valueFormat.sanitize_value (c, this, values));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ValueFormat	valueFormat;		/* Defines the types of data in the
 					 * ValueRecord */
   ValueRecord	values;			/* Defines positioning
 					 * value(s)--applied to all glyphs in
 					 * the Coverage table */
@@ -539,23 +539,23 @@ struct SinglePosFormat2
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  coverage.sanitize (c, this) &&
 		  valueFormat.sanitize_values (c, this, values, valueCount));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 2 */
+  UINT16	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ValueFormat	valueFormat;		/* Defines the types of data in the
 					 * ValueRecord */
-  USHORT	valueCount;		/* Number of ValueRecords */
+  UINT16	valueCount;		/* Number of ValueRecords */
   ValueRecord	values;			/* Array of ValueRecords--positioning
 					 * values applied to glyphs */
   public:
   DEFINE_SIZE_ARRAY (8, values);
 };
 
 struct SinglePos
 {
@@ -568,17 +568,17 @@ struct SinglePos
     case 1: return_trace (c->dispatch (u.format1));
     case 2: return_trace (c->dispatch (u.format2));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   SinglePosFormat1	format1;
   SinglePosFormat2	format2;
   } u;
 };
 
 
 struct PairValueRecord
 {
@@ -599,17 +599,17 @@ struct PairSet
   friend struct PairPosFormat1;
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c,
 			      const ValueFormat *valueFormats) const
   {
     TRACE_COLLECT_GLYPHS (this);
     unsigned int len1 = valueFormats[0].get_len ();
     unsigned int len2 = valueFormats[1].get_len ();
-    unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
+    unsigned int record_size = UINT16::static_size * (1 + len1 + len2);
 
     const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
     unsigned int count = len;
     for (unsigned int i = 0; i < count; i++)
     {
       c->input->add (record->secondGlyph);
       record = &StructAtOffset<PairValueRecord> (record, record_size);
     }
@@ -618,17 +618,17 @@ struct PairSet
   inline bool apply (hb_apply_context_t *c,
 		     const ValueFormat *valueFormats,
 		     unsigned int pos) const
   {
     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 record_size = USHORT::static_size * (1 + len1 + len2);
+    unsigned int record_size = UINT16::static_size * (1 + len1 + len2);
 
     const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
     unsigned int count = len;
 
     /* Hand-coded bsearch. */
     if (unlikely (!count))
       return_trace (false);
     hb_codepoint_t x = buffer->info[pos].codepoint;
@@ -663,27 +663,27 @@ struct PairSet
     unsigned int len1; /* valueFormats[0].get_len() */
     unsigned int stride; /* 1 + len1 + len2 */
   };
 
   inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
   {
     TRACE_SANITIZE (this);
     if (!(c->check_struct (this)
-       && c->check_array (arrayZ, USHORT::static_size * closure->stride, len))) return_trace (false);
+       && c->check_array (arrayZ, UINT16::static_size * closure->stride, len))) return_trace (false);
 
     unsigned int count = len;
     const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
     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));
   }
 
   protected:
-  USHORT	len;			/* Number of PairValueRecords */
-  USHORT	arrayZ[VAR];		/* Array of PairValueRecords--ordered
+  UINT16	len;			/* Number of PairValueRecords */
+  UINT16	arrayZ[VAR];		/* Array of PairValueRecords--ordered
 					 * by GlyphID of the second glyph */
   public:
   DEFINE_SIZE_ARRAY (2, arrayZ);
 };
 
 struct PairPosFormat1
 {
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
@@ -728,17 +728,17 @@ struct PairPosFormat1
       len1,
       1 + len1 + len2
     };
 
     return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ValueFormat	valueFormat[2];		/* [0] 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
 					 * ValueRecord2--for the second glyph
@@ -818,17 +818,17 @@ struct PairPosFormat2
     unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
     unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
     return_trace (c->check_array (values, record_size, count) &&
 		  valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
 		  valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 2 */
+  UINT16	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ValueFormat	valueFormat1;		/* ValueRecord definition--for the
 					 * first glyph of the pair--may be zero
 					 * (0) */
   ValueFormat	valueFormat2;		/* ValueRecord definition--for the
 					 * second glyph of the pair--may be
@@ -836,19 +836,19 @@ struct PairPosFormat2
   OffsetTo<ClassDef>
 		classDef1;		/* Offset to ClassDef table--from
 					 * beginning of PairPos subtable--for
 					 * the first glyph of the pair */
   OffsetTo<ClassDef>
 		classDef2;		/* Offset to ClassDef table--from
 					 * beginning of PairPos subtable--for
 					 * the second glyph of the pair */
-  USHORT	class1Count;		/* Number of classes in ClassDef1
+  UINT16	class1Count;		/* Number of classes in ClassDef1
 					 * table--includes Class0 */
-  USHORT	class2Count;		/* Number of classes in ClassDef2
+  UINT16	class2Count;		/* Number of classes in ClassDef2
 					 * table--includes Class0 */
   ValueRecord	values;			/* Matrix of value pairs:
 					 * class1-major, class2-minor,
 					 * Each entry has value1 and value2 */
   public:
   DEFINE_SIZE_ARRAY (16, values);
 };
 
@@ -863,17 +863,17 @@ struct PairPos
     case 1: return_trace (c->dispatch (u.format1));
     case 2: return_trace (c->dispatch (u.format2));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   PairPosFormat1	format1;
   PairPosFormat2	format2;
   } u;
 };
 
 
 struct EntryExitRecord
 {
@@ -1017,17 +1017,17 @@ struct CursivePosFormat1
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ArrayOf<EntryExitRecord>
 		entryExitRecord;	/* Array of EntryExit records--in
 					 * Coverage Index order */
   public:
   DEFINE_SIZE_ARRAY (6, entryExitRecord);
@@ -1043,17 +1043,17 @@ struct CursivePos
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   CursivePosFormat1	format1;
   } u;
 };
 
 
 typedef AnchorMatrix BaseArray;		/* base-major--
 					 * in order of BaseCoverage Index--,
 					 * mark-minor--
@@ -1108,24 +1108,24 @@ struct MarkBasePosFormat1
     return_trace (c->check_struct (this) &&
 		  markCoverage.sanitize (c, this) &&
 		  baseCoverage.sanitize (c, this) &&
 		  markArray.sanitize (c, this) &&
 		  baseArray.sanitize (c, this, (unsigned int) classCount));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		markCoverage;		/* Offset to MarkCoverage table--from
 					 * beginning of MarkBasePos subtable */
   OffsetTo<Coverage>
 		baseCoverage;		/* Offset to BaseCoverage table--from
 					 * beginning of MarkBasePos subtable */
-  USHORT	classCount;		/* Number of classes defined for marks */
+  UINT16	classCount;		/* Number of classes defined for marks */
   OffsetTo<MarkArray>
 		markArray;		/* Offset to MarkArray table--from
 					 * beginning of MarkBasePos subtable */
   OffsetTo<BaseArray>
 		baseArray;		/* Offset to BaseArray table--from
 					 * beginning of MarkBasePos subtable */
   public:
   DEFINE_SIZE_STATIC (12);
@@ -1141,17 +1141,17 @@ struct MarkBasePos
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   MarkBasePosFormat1	format1;
   } u;
 };
 
 
 typedef AnchorMatrix LigatureAttach;	/* component-major--
 					 * in order of writing direction--,
 					 * mark-minor--
@@ -1225,25 +1225,25 @@ struct MarkLigPosFormat1
     return_trace (c->check_struct (this) &&
 		  markCoverage.sanitize (c, this) &&
 		  ligatureCoverage.sanitize (c, this) &&
 		  markArray.sanitize (c, this) &&
 		  ligatureArray.sanitize (c, this, (unsigned int) classCount));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		markCoverage;		/* Offset to Mark Coverage table--from
 					 * beginning of MarkLigPos subtable */
   OffsetTo<Coverage>
 		ligatureCoverage;	/* Offset to Ligature Coverage
 					 * table--from beginning of MarkLigPos
 					 * subtable */
-  USHORT	classCount;		/* Number of defined mark classes */
+  UINT16	classCount;		/* Number of defined mark classes */
   OffsetTo<MarkArray>
 		markArray;		/* Offset to MarkArray table--from
 					 * beginning of MarkLigPos subtable */
   OffsetTo<LigatureArray>
 		ligatureArray;		/* Offset to LigatureArray table--from
 					 * beginning of MarkLigPos subtable */
   public:
   DEFINE_SIZE_STATIC (12);
@@ -1259,17 +1259,17 @@ struct MarkLigPos
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   MarkLigPosFormat1	format1;
   } u;
 };
 
 
 typedef AnchorMatrix Mark2Array;	/* mark2-major--
 					 * in order of Mark2Coverage Index--,
 					 * mark1-minor--
@@ -1339,26 +1339,26 @@ struct MarkMarkPosFormat1
     return_trace (c->check_struct (this) &&
 		  mark1Coverage.sanitize (c, this) &&
 		  mark2Coverage.sanitize (c, this) &&
 		  mark1Array.sanitize (c, this) &&
 		  mark2Array.sanitize (c, this, (unsigned int) classCount));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		mark1Coverage;		/* Offset to Combining Mark1 Coverage
 					 * table--from beginning of MarkMarkPos
 					 * subtable */
   OffsetTo<Coverage>
 		mark2Coverage;		/* Offset to Combining Mark2 Coverage
 					 * table--from beginning of MarkMarkPos
 					 * subtable */
-  USHORT	classCount;		/* Number of defined mark classes */
+  UINT16	classCount;		/* Number of defined mark classes */
   OffsetTo<MarkArray>
 		mark1Array;		/* Offset to Mark1Array table--from
 					 * beginning of MarkMarkPos subtable */
   OffsetTo<Mark2Array>
 		mark2Array;		/* Offset to Mark2Array table--from
 					 * beginning of MarkMarkPos subtable */
   public:
   DEFINE_SIZE_STATIC (12);
@@ -1374,17 +1374,17 @@ struct MarkMarkPos
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   MarkMarkPosFormat1	format1;
   } u;
 };
 
 
 struct ContextPos : Context {};
 
 struct ChainContextPos : ChainContext {};
@@ -1433,17 +1433,17 @@ struct PosLookupSubTable
     case ChainContext:		return_trace (u.chainContext.dispatch (c));
     case Extension:		return_trace (u.extension.dispatch (c));
     default:			return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT		sub_format;
+  UINT16		sub_format;
   SinglePos		single;
   PairPos		pair;
   CursivePos		cursive;
   MarkBasePos		markBase;
   MarkLigPos		markLig;
   MarkMarkPos		markMark;
   ContextPos		context;
   ChainContextPos	chainContext;
--- a/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
@@ -39,31 +39,31 @@ struct SingleSubstFormat1
 {
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
     Coverage::Iter iter;
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       /* TODO Switch to range-based API to work around malicious fonts.
-       * https://github.com/behdad/harfbuzz/issues/363 */
+       * https://github.com/harfbuzz/harfbuzz/issues/363 */
       hb_codepoint_t glyph_id = iter.get_glyph ();
       if (c->glyphs->has (glyph_id))
 	c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
     }
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     Coverage::Iter iter;
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       /* TODO Switch to range-based API to work around malicious fonts.
-       * https://github.com/behdad/harfbuzz/issues/363 */
+       * https://github.com/harfbuzz/harfbuzz/issues/363 */
       hb_codepoint_t glyph_id = iter.get_glyph ();
       c->input->add (glyph_id);
       c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
     }
   }
 
   inline const Coverage &get_coverage (void) const
   {
@@ -105,51 +105,51 @@ struct SingleSubstFormat1
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
-  SHORT		deltaGlyphID;		/* Add to original GlyphID to get
+  INT16		deltaGlyphID;		/* Add to original GlyphID to get
 					 * substitute GlyphID */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
 struct SingleSubstFormat2
 {
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
     Coverage::Iter iter;
     unsigned int count = substitute.len;
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       if (c->glyphs->has (iter.get_glyph ()))
 	c->glyphs->add (substitute[iter.get_coverage ()]);
     }
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     Coverage::Iter iter;
     unsigned int count = substitute.len;
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       c->input->add (iter.get_glyph ());
       c->output->add (substitute[iter.get_coverage ()]);
     }
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
@@ -190,17 +190,17 @@ struct SingleSubstFormat2
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && substitute.sanitize (c));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 2 */
+  UINT16	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
   ArrayOf<GlyphID>
 		substitute;		/* Array of substitute
 					 * GlyphIDs--ordered by Coverage Index */
   public:
   DEFINE_SIZE_ARRAY (6, substitute);
@@ -244,17 +244,17 @@ struct SingleSubst
     case 1: return_trace (c->dispatch (u.format1));
     case 2: return_trace (c->dispatch (u.format2));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   SingleSubstFormat1	format1;
   SingleSubstFormat2	format2;
   } u;
 };
 
 
 struct Sequence
 {
@@ -282,17 +282,17 @@ struct Sequence
     /* Special-case to make it in-place and not consider this
      * as a "multiplied" substitution. */
     if (unlikely (count == 1))
     {
       c->replace_glyph (substitute.array[0]);
       return_trace (true);
     }
     /* Spec disallows this, but Uniscribe allows it.
-     * https://github.com/behdad/harfbuzz/issues/253 */
+     * https://github.com/harfbuzz/harfbuzz/issues/253 */
     else if (unlikely (count == 0))
     {
       c->buffer->delete_glyph ();
       return_trace (true);
     }
 
     unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
 			 HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
@@ -334,17 +334,17 @@ struct MultipleSubstFormat1
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
     Coverage::Iter iter;
     unsigned int count = sequence.len;
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       if (c->glyphs->has (iter.get_glyph ()))
 	(this+sequence[iter.get_coverage ()]).closure (c);
     }
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
@@ -395,17 +395,17 @@ struct MultipleSubstFormat1
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
   OffsetArrayOf<Sequence>
 		sequence;		/* Array of Sequence tables
 					 * ordered by Coverage Index */
   public:
   DEFINE_SIZE_ARRAY (6, sequence);
@@ -437,17 +437,17 @@ struct MultipleSubst
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   MultipleSubstFormat1	format1;
   } u;
 };
 
 
 typedef ArrayOf<GlyphID> AlternateSet;	/* Array of alternate GlyphIDs--in
 					 * arbitrary order */
 
@@ -456,17 +456,17 @@ struct AlternateSubstFormat1
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
     Coverage::Iter iter;
     unsigned int count = alternateSet.len;
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       if (c->glyphs->has (iter.get_glyph ())) {
 	const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
 	unsigned int count = alt_set.len;
 	for (unsigned int i = 0; i < count; i++)
 	  c->glyphs->add (alt_set[i]);
       }
     }
   }
@@ -474,17 +474,17 @@ struct AlternateSubstFormat1
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     Coverage::Iter iter;
     unsigned int count = alternateSet.len;
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       c->input->add (iter.get_glyph ());
       const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
       unsigned int count = alt_set.len;
       for (unsigned int i = 0; i < count; i++)
 	c->output->add (alt_set[i]);
     }
   }
 
@@ -547,17 +547,17 @@ struct AlternateSubstFormat1
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
   OffsetArrayOf<AlternateSet>
 		alternateSet;		/* Array of AlternateSet tables
 					 * ordered by Coverage Index */
   public:
   DEFINE_SIZE_ARRAY (6, alternateSet);
@@ -589,17 +589,17 @@ struct AlternateSubst
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   AlternateSubstFormat1	format1;
   } u;
 };
 
 
 struct Ligature
 {
   inline void closure (hb_closure_context_t *c) const
@@ -787,31 +787,31 @@ struct LigatureSubstFormat1
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
     Coverage::Iter iter;
     unsigned int count = ligatureSet.len;
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       if (c->glyphs->has (iter.get_glyph ()))
 	(this+ligatureSet[iter.get_coverage ()]).closure (c);
     }
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     Coverage::Iter iter;
     unsigned int count = ligatureSet.len;
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       c->input->add (iter.get_glyph ());
       (this+ligatureSet[iter.get_coverage ()]).collect_glyphs (c);
     }
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
@@ -863,17 +863,17 @@ struct LigatureSubstFormat1
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
   OffsetArrayOf<LigatureSet>
 		ligatureSet;		/* Array LigatureSet tables
 					 * ordered by Coverage Index */
   public:
   DEFINE_SIZE_ARRAY (6, ligatureSet);
@@ -913,17 +913,17 @@ struct LigatureSubst
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   LigatureSubstFormat1	format1;
   } u;
 };
 
 
 struct ContextSubst : Context {};
 
 struct ChainContextSubst : ChainContext {};
@@ -956,17 +956,17 @@ struct ReverseChainSingleSubstFormat1
         return;
 
     const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
     Coverage::Iter iter;
     count = substitute.len;
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       if (c->glyphs->has (iter.get_glyph ()))
 	c->glyphs->add (substitute[iter.get_coverage ()]);
     }
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
@@ -1011,21 +1011,21 @@ struct ReverseChainSingleSubstFormat1
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
     const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
 
   unsigned int start_index = 0, end_index = 0;
     if (match_backtrack (c,
-			 backtrack.len, (USHORT *) backtrack.array,
+			 backtrack.len, (UINT16 *) backtrack.array,
 			 match_coverage, this,
 			 &start_index) &&
         match_lookahead (c,
-			 lookahead.len, (USHORT *) lookahead.array,
+			 lookahead.len, (UINT16 *) lookahead.array,
 			 match_coverage, this,
 			 1, &end_index))
     {
       c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
       c->replace_glyph_inplace (substitute[index]);
       /* Note: We DON'T decrease buffer->idx.  The main loop does it
        * for us.  This is useful for preventing surprises if someone
        * calls us through a Context lookup. */
@@ -1043,17 +1043,17 @@ struct ReverseChainSingleSubstFormat1
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
     if (!lookahead.sanitize (c, this))
       return_trace (false);
     const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
     return_trace (substitute.sanitize (c));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
   OffsetArrayOf<Coverage>
 		backtrack;		/* Array of coverage tables
 					 * in backtracking sequence, in  glyph
 					 * sequence order */
   OffsetArrayOf<Coverage>
@@ -1077,17 +1077,17 @@ struct ReverseChainSingleSubst
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT				format;		/* Format identifier */
+  UINT16				format;		/* Format identifier */
   ReverseChainSingleSubstFormat1	format1;
   } u;
 };
 
 
 
 /*
  * SubstLookup
@@ -1123,17 +1123,17 @@ struct SubstLookupSubTable
     case Extension:		return_trace (u.extension.dispatch (c));
     case ReverseChainSingle:	return_trace (u.reverseChainContextSingle.dispatch (c));
     default:			return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT			sub_format;
+  UINT16			sub_format;
   SingleSubst			single;
   MultipleSubst			multiple;
   AlternateSubst		alternate;
   LigatureSubst			ligature;
   ContextSubst			context;
   ChainContextSubst		chainContext;
   ExtensionSubst		extension;
   ReverseChainSingleSubst	reverseChainContextSingle;
@@ -1275,19 +1275,21 @@ struct SubstLookup : Lookup
   {
     TRACE_SANITIZE (this);
     if (unlikely (!Lookup::sanitize (c))) return_trace (false);
     if (unlikely (!dispatch (c))) return_trace (false);
 
     if (unlikely (get_type () == SubstLookupSubTable::Extension))
     {
       /* The spec says all subtables of an Extension lookup should
-       * have the same type.  This is specially important if one has
-       * a reverse type! */
+       * have the same type, which shall not be the Extension type
+       * itself. This is specially important if one has a reverse type! */
       unsigned int type = get_subtable (0).u.extension.get_type ();
+      if (unlikely (type == SubstLookupSubTable::Extension))
+	return_trace (false);
       unsigned int count = get_subtable_count ();
       for (unsigned int i = 1; i < count; i++)
         if (get_subtable (i).u.extension.get_type () != type)
 	  return_trace (false);
     }
     return_trace (true);
   }
 };
--- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
@@ -229,17 +229,17 @@ struct hb_apply_context_t :
 	     ignore_zwj (false),
 	     mask (-1),
 #define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
 	     syllable arg1(0),
 #undef arg1
 	     match_func (nullptr),
 	     match_data (nullptr) {};
 
-    typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
+    typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const UINT16 &value, const void *data);
 
     inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
     inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
     inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
     inline void set_mask (hb_mask_t mask_) { mask = mask_; }
     inline void set_syllable (uint8_t syllable_)  { syllable = syllable_; }
     inline void set_match_func (match_func_t match_func_,
 				const void *match_data_)
@@ -247,17 +247,17 @@ struct hb_apply_context_t :
 
     enum may_match_t {
       MATCH_NO,
       MATCH_YES,
       MATCH_MAYBE
     };
 
     inline may_match_t may_match (const hb_glyph_info_t &info,
-				  const USHORT          *glyph_data) const
+				  const UINT16          *glyph_data) const
     {
       if (!(info.mask & mask) ||
 	  (syllable && syllable != info.syllable ()))
 	return MATCH_NO;
 
       if (match_func)
         return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
 
@@ -310,17 +310,17 @@ struct hb_apply_context_t :
       matcher.set_mask (context_match ? -1 : c->lookup_mask);
     }
     inline void set_lookup_props (unsigned int lookup_props)
     {
       matcher.set_lookup_props (lookup_props);
     }
     inline void set_match_func (matcher_t::match_func_t match_func_,
 				const void *match_data_,
-				const USHORT glyph_data[])
+				const UINT16 glyph_data[])
     {
       matcher.set_match_func (match_func_, match_data_);
       match_glyph_data = glyph_data;
     }
 
     inline void reset (unsigned int start_index_,
 		       unsigned int num_items_)
     {
@@ -393,32 +393,32 @@ struct hb_apply_context_t :
       }
       return false;
     }
 
     unsigned int idx;
     protected:
     hb_apply_context_t *c;
     matcher_t matcher;
-    const USHORT *match_glyph_data;
+    const UINT16 *match_glyph_data;
 
     unsigned int num_items;
     unsigned int end;
   };
 
 
   inline const char *get_name (void) { return "APPLY"; }
   typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
   template <typename T>
   inline return_t dispatch (const T &obj) { return obj.apply (this); }
   static return_t default_return_value (void) { return false; }
   bool stop_sublookup_iteration (return_t r) const { return r; }
   return_t recurse (unsigned int lookup_index)
   {
-    if (unlikely (nesting_level_left == 0 || !recurse_func))
+    if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
       return default_return_value ();
 
     nesting_level_left--;
     bool ret = recurse_func (this, lookup_index);
     nesting_level_left++;
     return ret;
   }
 
@@ -563,121 +563,121 @@ struct hb_apply_context_t :
   {
     _set_glyph_props (glyph_index, class_guess, false, true);
     buffer->output_glyph (glyph_index);
   }
 };
 
 
 
-typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
-typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
-typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
+typedef bool (*intersects_func_t) (hb_set_t *glyphs, const UINT16 &value, const void *data);
+typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const UINT16 &value, const void *data);
+typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const UINT16 &value, const void *data);
 
 struct ContextClosureFuncs
 {
   intersects_func_t intersects;
 };
 struct ContextCollectGlyphsFuncs
 {
   collect_glyphs_func_t collect;
 };
 struct ContextApplyFuncs
 {
   match_func_t match;
 };
 
 
-static inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
+static inline bool intersects_glyph (hb_set_t *glyphs, const UINT16 &value, const void *data HB_UNUSED)
 {
   return glyphs->has (value);
 }
-static inline bool intersects_class (hb_set_t *glyphs, const USHORT &value, const void *data)
+static inline bool intersects_class (hb_set_t *glyphs, const UINT16 &value, const void *data)
 {
   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   return class_def.intersects_class (glyphs, value);
 }
-static inline bool intersects_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
+static inline bool intersects_coverage (hb_set_t *glyphs, const UINT16 &value, const void *data)
 {
   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   return (data+coverage).intersects (glyphs);
 }
 
 static inline bool intersects_array (hb_closure_context_t *c,
 				     unsigned int count,
-				     const USHORT values[],
+				     const UINT16 values[],
 				     intersects_func_t intersects_func,
 				     const void *intersects_data)
 {
   for (unsigned int i = 0; i < count; i++)
     if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
       return false;
   return true;
 }
 
 
-static inline void collect_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
+static inline void collect_glyph (hb_set_t *glyphs, const UINT16 &value, const void *data HB_UNUSED)
 {
   glyphs->add (value);
 }
-static inline void collect_class (hb_set_t *glyphs, const USHORT &value, const void *data)
+static inline void collect_class (hb_set_t *glyphs, const UINT16 &value, const void *data)
 {
   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   class_def.add_class (glyphs, value);
 }
-static inline void collect_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
+static inline void collect_coverage (hb_set_t *glyphs, const UINT16 &value, const void *data)
 {
   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   (data+coverage).add_coverage (glyphs);
 }
 static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
 				  hb_set_t *glyphs,
 				  unsigned int count,
-				  const USHORT values[],
+				  const UINT16 values[],
 				  collect_glyphs_func_t collect_func,
 				  const void *collect_data)
 {
   for (unsigned int i = 0; i < count; i++)
     collect_func (glyphs, values[i], collect_data);
 }
 
 
-static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
+static inline bool match_glyph (hb_codepoint_t glyph_id, const UINT16 &value, const void *data HB_UNUSED)
 {
   return glyph_id == value;
 }
-static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
+static inline bool match_class (hb_codepoint_t glyph_id, const UINT16 &value, const void *data)
 {
   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   return class_def.get_class (glyph_id) == value;
 }
-static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
+static inline bool match_coverage (hb_codepoint_t glyph_id, const UINT16 &value, const void *data)
 {
   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
 }
 
 static inline bool would_match_input (hb_would_apply_context_t *c,
 				      unsigned int count, /* Including the first glyph (not matched) */
-				      const USHORT input[], /* Array of input values--start with second glyph */
+				      const UINT16 input[], /* Array of input values--start with second glyph */
 				      match_func_t match_func,
 				      const void *match_data)
 {
   if (count != c->len)
     return false;
 
   for (unsigned int i = 1; i < count; i++)
     if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
       return false;
 
   return true;
 }
 static inline bool match_input (hb_apply_context_t *c,
 				unsigned int count, /* Including the first glyph (not matched) */
-				const USHORT input[], /* Array of input values--start with second glyph */
+				const UINT16 input[], /* Array of input values--start with second glyph */
 				match_func_t match_func,
 				const void *match_data,
 				unsigned int *end_offset,
 				unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
 				bool *p_is_mark_ligature = nullptr,
 				unsigned int *p_total_component_count = nullptr)
 {
   TRACE_APPLY (nullptr);
@@ -706,17 +706,17 @@ static inline bool match_input (hb_apply
    *
    *   o If a ligature tries ligating with marks that belong to it itself, go ahead,
    *     assuming that the font designer knows what they are doing (otherwise it can
    *     break Indic stuff when a matra wants to ligate with a conjunct,
    *
    *   o If two marks want to ligate and they belong to different components of the
    *     same ligature glyph, and said ligature glyph is to be ignored according to
    *     mark-filtering rules, then allow.
-   *     https://github.com/behdad/harfbuzz/issues/545
+   *     https://github.com/harfbuzz/harfbuzz/issues/545
    */
 
   bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur());
 
   unsigned int total_component_count = 0;
   total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
 
   unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
@@ -891,17 +891,17 @@ static inline bool ligate_input (hb_appl
 	break;
     }
   }
   return_trace (true);
 }
 
 static inline bool match_backtrack (hb_apply_context_t *c,
 				    unsigned int count,
-				    const USHORT backtrack[],
+				    const UINT16 backtrack[],
 				    match_func_t match_func,
 				    const void *match_data,
 				    unsigned int *match_start)
 {
   TRACE_APPLY (nullptr);
 
   hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
   skippy_iter.reset (c->buffer->backtrack_len (), count);
@@ -913,17 +913,17 @@ static inline bool match_backtrack (hb_a
 
   *match_start = skippy_iter.idx;
 
   return_trace (true);
 }
 
 static inline bool match_lookahead (hb_apply_context_t *c,
 				    unsigned int count,
-				    const USHORT lookahead[],
+				    const UINT16 lookahead[],
 				    match_func_t match_func,
 				    const void *match_data,
 				    unsigned int offset,
 				    unsigned int *end_index)
 {
   TRACE_APPLY (nullptr);
 
   hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
@@ -944,19 +944,19 @@ static inline bool match_lookahead (hb_a
 struct LookupRecord
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  USHORT	sequenceIndex;		/* Index into current glyph
+  UINT16	sequenceIndex;		/* Index into current glyph
 					 * sequence--first glyph = 0 */
-  USHORT	lookupListIndex;	/* Lookup to apply to that
+  UINT16	lookupListIndex;	/* Lookup to apply to that
 					 * position--zero--based */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 
 template <typename context_t>
 static inline void recurse_lookups (context_t *c,
@@ -997,17 +997,21 @@ static inline bool apply_lookup (hb_appl
     if (idx >= count)
       continue;
 
     /* Don't recurse to ourself at same position.
      * Note that this test is too naive, it doesn't catch longer loops. */
     if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
       continue;
 
-    buffer->move_to (match_positions[idx]);
+    if (unlikely (!buffer->move_to (match_positions[idx])))
+      break;
+
+    if (unlikely (buffer->max_ops <= 0))
+      break;
 
     unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
     if (!c->recurse (lookupRecord[i].lookupListIndex))
       continue;
 
     unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
     int delta = new_len - orig_len;
 
@@ -1103,56 +1107,56 @@ struct ContextCollectGlyphsLookupContext
 struct ContextApplyLookupContext
 {
   ContextApplyFuncs funcs;
   const void *match_data;
 };
 
 static inline void context_closure_lookup (hb_closure_context_t *c,
 					   unsigned int inputCount, /* Including the first glyph (not matched) */
-					   const USHORT input[], /* Array of input values--start with second glyph */
+					   const UINT16 input[], /* Array of input values--start with second glyph */
 					   unsigned int lookupCount,
 					   const LookupRecord lookupRecord[],
 					   ContextClosureLookupContext &lookup_context)
 {
   if (intersects_array (c,
 			inputCount ? inputCount - 1 : 0, input,
 			lookup_context.funcs.intersects, lookup_context.intersects_data))
     recurse_lookups (c,
 		     lookupCount, lookupRecord);
 }
 
 static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
 						  unsigned int inputCount, /* Including the first glyph (not matched) */
-						  const USHORT input[], /* Array of input values--start with second glyph */
+						  const UINT16 input[], /* Array of input values--start with second glyph */
 						  unsigned int lookupCount,
 						  const LookupRecord lookupRecord[],
 						  ContextCollectGlyphsLookupContext &lookup_context)
 {
   collect_array (c, c->input,
 		 inputCount ? inputCount - 1 : 0, input,
 		 lookup_context.funcs.collect, lookup_context.collect_data);
   recurse_lookups (c,
 		   lookupCount, lookupRecord);
 }
 
 static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
 					       unsigned int inputCount, /* Including the first glyph (not matched) */
-					       const USHORT input[], /* Array of input values--start with second glyph */
+					       const UINT16 input[], /* Array of input values--start with second glyph */
 					       unsigned int lookupCount HB_UNUSED,
 					       const LookupRecord lookupRecord[] HB_UNUSED,
 					       ContextApplyLookupContext &lookup_context)
 {
   return would_match_input (c,
 			    inputCount, input,
 			    lookup_context.funcs.match, lookup_context.match_data);
 }
 static inline bool context_apply_lookup (hb_apply_context_t *c,
 					 unsigned int inputCount, /* Including the first glyph (not matched) */
-					 const USHORT input[], /* Array of input values--start with second glyph */
+					 const UINT16 input[], /* Array of input values--start with second glyph */
 					 unsigned int lookupCount,
 					 const LookupRecord lookupRecord[],
 					 ContextApplyLookupContext &lookup_context)
 {
   unsigned int match_length = 0;
   unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
   return match_input (c,
 		      inputCount, input,
@@ -1208,21 +1212,21 @@ struct Rule
     return_trace (inputCount.sanitize (c) &&
 		  lookupCount.sanitize (c) &&
 		  c->check_range (inputZ,
 				  inputZ[0].static_size * inputCount +
 				  lookupRecordX[0].static_size * lookupCount));
   }
 
   protected:
-  USHORT	inputCount;		/* Total number of glyphs in input
+  UINT16	inputCount;		/* Total number of glyphs in input
 					 * glyph sequence--includes the first
 					 * glyph */
-  USHORT	lookupCount;		/* Number of LookupRecords */
-  USHORT	inputZ[VAR];		/* Array of match inputs--start with
+  UINT16	lookupCount;		/* Number of LookupRecords */
+  UINT16	inputZ[VAR];		/* Array of match inputs--start with
 					 * second glyph */
   LookupRecord	lookupRecordX[VAR];	/* Array of LookupRecords--in
 					 * design order */
   public:
   DEFINE_SIZE_ARRAY2 (4, inputZ, lookupRecordX);
 };
 
 struct RuleSet
@@ -1352,17 +1356,17 @@ struct ContextFormat1
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
   OffsetArrayOf<RuleSet>
 		ruleSet;		/* Array of RuleSet tables
 					 * ordered by Coverage Index */
   public:
   DEFINE_SIZE_ARRAY (6, ruleSet);
@@ -1445,17 +1449,17 @@ struct ContextFormat2
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 2 */
+  UINT16	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
   OffsetTo<ClassDef>
 		classDef;		/* Offset to glyph ClassDef table--from
 					 * beginning of table */
   OffsetArrayOf<RuleSet>
 		ruleSet;		/* Array of RuleSet tables
@@ -1474,48 +1478,48 @@ struct ContextFormat3
       return;
 
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
     struct ContextClosureLookupContext lookup_context = {
       {intersects_coverage},
       this
     };
     context_closure_lookup (c,
-			    glyphCount, (const USHORT *) (coverageZ + 1),
+			    glyphCount, (const UINT16 *) (coverageZ + 1),
 			    lookupCount, lookupRecord,
 			    lookup_context);
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     (this+coverageZ[0]).add_coverage (c->input);
 
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
     struct ContextCollectGlyphsLookupContext lookup_context = {
       {collect_coverage},
       this
     };
 
     context_collect_glyphs_lookup (c,
-				   glyphCount, (const USHORT *) (coverageZ + 1),
+				   glyphCount, (const UINT16 *) (coverageZ + 1),
 				   lookupCount, lookupRecord,
 				   lookup_context);
   }
 
   inline bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
 
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
     struct ContextApplyLookupContext lookup_context = {
       {match_coverage},
       this
     };
-    return_trace (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
+    return_trace (context_would_apply_lookup (c, glyphCount, (const UINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverageZ[0];
   }
 
   inline bool apply (hb_apply_context_t *c) const
@@ -1524,37 +1528,37 @@ struct ContextFormat3
     unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
     struct ContextApplyLookupContext lookup_context = {
       {match_coverage},
       this
     };
-    return_trace (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
+    return_trace (context_apply_lookup (c, glyphCount, (const UINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     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 (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return_trace (false);
     for (unsigned int i = 0; i < count; i++)
       if (!coverageZ[i].sanitize (c, this)) return_trace (false);
     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
     return_trace (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 3 */
-  USHORT	glyphCount;		/* Number of glyphs in the input glyph
+  UINT16	format;			/* Format identifier--format = 3 */
+  UINT16	glyphCount;		/* Number of glyphs in the input glyph
 					 * sequence */
-  USHORT	lookupCount;		/* Number of LookupRecords */
+  UINT16	lookupCount;		/* Number of LookupRecords */
   OffsetTo<Coverage>
 		coverageZ[VAR];		/* Array of offsets to Coverage
 					 * table in glyph sequence order */
   LookupRecord	lookupRecordX[VAR];	/* Array of LookupRecords--in
 					 * design order */
   public:
   DEFINE_SIZE_ARRAY2 (6, coverageZ, lookupRecordX);
 };
@@ -1571,17 +1575,17 @@ struct Context
     case 2: return_trace (c->dispatch (u.format2));
     case 3: return_trace (c->dispatch (u.format3));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   ContextFormat1	format1;
   ContextFormat2	format2;
   ContextFormat3	format3;
   } u;
 };
 
 
 /* Chaining Contextual lookups */
@@ -1601,21 +1605,21 @@ struct ChainContextCollectGlyphsLookupCo
 struct ChainContextApplyLookupContext
 {
   ContextApplyFuncs funcs;
   const void *match_data[3];
 };
 
 static inline void chain_context_closure_lookup (hb_closure_context_t *c,
 						 unsigned int backtrackCount,
-						 const USHORT backtrack[],
+						 const UINT16 backtrack[],
 						 unsigned int inputCount, /* Including the first glyph (not matched) */
-						 const USHORT input[], /* Array of input values--start with second glyph */
+						 const UINT16 input[], /* Array of input values--start with second glyph */
 						 unsigned int lookaheadCount,
-						 const USHORT lookahead[],
+						 const UINT16 lookahead[],
 						 unsigned int lookupCount,
 						 const LookupRecord lookupRecord[],
 						 ChainContextClosureLookupContext &lookup_context)
 {
   if (intersects_array (c,
 			backtrackCount, backtrack,
 			lookup_context.funcs.intersects, lookup_context.intersects_data[0])
    && intersects_array (c,
@@ -1625,21 +1629,21 @@ static inline void chain_context_closure
 		       lookaheadCount, lookahead,
 		       lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
     recurse_lookups (c,
 		     lookupCount, lookupRecord);
 }
 
 static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
 						        unsigned int backtrackCount,
-						        const USHORT backtrack[],
+						        const UINT16 backtrack[],
 						        unsigned int inputCount, /* Including the first glyph (not matched) */
-						        const USHORT input[], /* Array of input values--start with second glyph */
+						        const UINT16 input[], /* Array of input values--start with second glyph */
 						        unsigned int lookaheadCount,
-						        const USHORT lookahead[],
+						        const UINT16 lookahead[],
 						        unsigned int lookupCount,
 						        const LookupRecord lookupRecord[],
 						        ChainContextCollectGlyphsLookupContext &lookup_context)
 {
   collect_array (c, c->before,
 		 backtrackCount, backtrack,
 		 lookup_context.funcs.collect, lookup_context.collect_data[0]);
   collect_array (c, c->input,
@@ -1649,38 +1653,38 @@ static inline void chain_context_collect
 		 lookaheadCount, lookahead,
 		 lookup_context.funcs.collect, lookup_context.collect_data[2]);
   recurse_lookups (c,
 		   lookupCount, lookupRecord);
 }
 
 static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
 						     unsigned int backtrackCount,
-						     const USHORT backtrack[] HB_UNUSED,
+						     const UINT16 backtrack[] HB_UNUSED,
 						     unsigned int inputCount, /* Including the first glyph (not matched) */
-						     const USHORT input[], /* Array of input values--start with second glyph */
+						     const UINT16 input[], /* Array of input values--start with second glyph */
 						     unsigned int lookaheadCount,
-						     const USHORT lookahead[] HB_UNUSED,
+						     const UINT16 lookahead[] HB_UNUSED,
 						     unsigned int lookupCount HB_UNUSED,
 						     const LookupRecord lookupRecord[] HB_UNUSED,
 						     ChainContextApplyLookupContext &lookup_context)
 {
   return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
       && would_match_input (c,
 			    inputCount, input,
 			    lookup_context.funcs.match, lookup_context.match_data[1]);
 }
 
 static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
 					       unsigned int backtrackCount,
-					       const USHORT backtrack[],
+					       const UINT16 backtrack[],
 					       unsigned int inputCount, /* Including the first glyph (not matched) */
-					       const USHORT input[], /* Array of input values--start with second glyph */
+					       const UINT16 input[], /* Array of input values--start with second glyph */
 					       unsigned int lookaheadCount,
-					       const USHORT lookahead[],
+					       const UINT16 lookahead[],
 					       unsigned int lookupCount,
 					       const LookupRecord lookupRecord[],
 					       ChainContextApplyLookupContext &lookup_context)
 {
   unsigned int start_index = 0, match_length = 0, end_index = 0;
   unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
   return match_input (c,
 		      inputCount, input,
@@ -1701,88 +1705,88 @@ static inline bool chain_context_apply_l
 		       match_length));
 }
 
 struct ChainRule
 {
   inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
   {
     TRACE_CLOSURE (this);
-    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
-    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
+    const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack);
+    const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     chain_context_closure_lookup (c,
 				  backtrack.len, backtrack.array,
 				  input.len, input.array,
 				  lookahead.len, lookahead.array,
 				  lookup.len, lookup.array,
 				  lookup_context);
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
-    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
+    const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack);
+    const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     chain_context_collect_glyphs_lookup (c,
 					 backtrack.len, backtrack.array,
 					 input.len, input.array,
 					 lookahead.len, lookahead.array,
 					 lookup.len, lookup.array,
 					 lookup_context);
   }
 
   inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
   {
     TRACE_WOULD_APPLY (this);
-    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
-    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
+    const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack);
+    const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     return_trace (chain_context_would_apply_lookup (c,
 						    backtrack.len, backtrack.array,
 						    input.len, input.array,
 						    lookahead.len, lookahead.array, lookup.len,
 						    lookup.array, lookup_context));
   }
 
   inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
-    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
-    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
+    const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack);
+    const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     return_trace (chain_context_apply_lookup (c,
 					      backtrack.len, backtrack.array,
 					      input.len, input.array,
 					      lookahead.len, lookahead.array, lookup.len,
 					      lookup.array, lookup_context));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!backtrack.sanitize (c)) return_trace (false);
-    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
+    const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack);
     if (!input.sanitize (c)) return_trace (false);
-    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
+    const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input);
     if (!lookahead.sanitize (c)) return_trace (false);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     return_trace (lookup.sanitize (c));
   }
 
   protected:
-  ArrayOf<USHORT>
+  ArrayOf<UINT16>
 		backtrack;		/* Array of backtracking values
 					 * (to be matched before the input
 					 * sequence) */
-  HeadlessArrayOf<USHORT>
+  HeadlessArrayOf<UINT16>
 		inputX;			/* Array of input values (start with
 					 * second glyph) */
-  ArrayOf<USHORT>
+  ArrayOf<UINT16>
 		lookaheadX;		/* Array of lookahead values's (to be
 					 * matched after the input sequence) */
   ArrayOf<LookupRecord>
 		lookupX;		/* Array of LookupRecords--in
 					 * design order) */
   public:
   DEFINE_SIZE_MIN (8);
 };
@@ -1909,17 +1913,17 @@ struct ChainContextFormat1
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
   OffsetArrayOf<ChainRuleSet>
 		ruleSet;		/* Array of ChainRuleSet tables
 					 * ordered by Coverage Index */
   public:
   DEFINE_SIZE_ARRAY (6, ruleSet);
@@ -2024,17 +2028,17 @@ struct ChainContextFormat2
     return_trace (coverage.sanitize (c, this) &&
 		  backtrackClassDef.sanitize (c, this) &&
 		  inputClassDef.sanitize (c, this) &&
 		  lookaheadClassDef.sanitize (c, this) &&
 		  ruleSet.sanitize (c, this));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 2 */
+  UINT16	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
   OffsetTo<ClassDef>
 		backtrackClassDef;	/* Offset to glyph ClassDef table
 					 * containing backtrack sequence
 					 * data--from beginning of table */
   OffsetTo<ClassDef>
@@ -2064,19 +2068,19 @@ struct ChainContextFormat3
 
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     struct ChainContextClosureLookupContext lookup_context = {
       {intersects_coverage},
       {this, this, this}
     };
     chain_context_closure_lookup (c,
-				  backtrack.len, (const USHORT *) backtrack.array,
-				  input.len, (const USHORT *) input.array + 1,
-				  lookahead.len, (const USHORT *) lookahead.array,
+				  backtrack.len, (const UINT16 *) backtrack.array,
+				  input.len, (const UINT16 *) input.array + 1,
+				  lookahead.len, (const UINT16 *) lookahead.array,
 				  lookup.len, lookup.array,
 				  lookup_context);
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
@@ -2085,38 +2089,38 @@ struct ChainContextFormat3
 
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     struct ChainContextCollectGlyphsLookupContext lookup_context = {
       {collect_coverage},
       {this, this, this}
     };
     chain_context_collect_glyphs_lookup (c,
-					 backtrack.len, (const USHORT *) backtrack.array,
-					 input.len, (const USHORT *) input.array + 1,
-					 lookahead.len, (const USHORT *) lookahead.array,
+					 backtrack.len, (const UINT16 *) backtrack.array,
+					 input.len, (const UINT16 *) input.array + 1,
+					 lookahead.len, (const UINT16 *) lookahead.array,
 					 lookup.len, lookup.array,
 					 lookup_context);
   }
 
   inline bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
 
     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     struct ChainContextApplyLookupContext lookup_context = {
       {match_coverage},
       {this, this, this}
     };
     return_trace (chain_context_would_apply_lookup (c,
-						    backtrack.len, (const USHORT *) backtrack.array,
-						    input.len, (const USHORT *) input.array + 1,
-						    lookahead.len, (const USHORT *) lookahead.array,
+						    backtrack.len, (const UINT16 *) backtrack.array,
+						    input.len, (const UINT16 *) input.array + 1,
+						    lookahead.len, (const UINT16 *) lookahead.array,
 						    lookup.len, lookup.array, lookup_context));
   }
 
   inline const Coverage &get_coverage (void) const
   {
     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
     return this+input[0];
   }
@@ -2131,19 +2135,19 @@ struct ChainContextFormat3
 
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     struct ChainContextApplyLookupContext lookup_context = {
       {match_coverage},
       {this, this, this}
     };
     return_trace (chain_context_apply_lookup (c,
-					      backtrack.len, (const USHORT *) backtrack.array,
-					      input.len, (const USHORT *) input.array + 1,
-					      lookahead.len, (const USHORT *) lookahead.array,
+					      backtrack.len, (const UINT16 *) backtrack.array,
+					      input.len, (const UINT16 *) input.array + 1,
+					      lookahead.len, (const UINT16 *) lookahead.array,
 					      lookup.len, lookup.array, lookup_context));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!backtrack.sanitize (c, this)) return_trace (false);
     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
@@ -2151,17 +2155,17 @@ struct ChainContextFormat3
     if (!input.len) return_trace (false); /* To be consistent with Context. */
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
     if (!lookahead.sanitize (c, this)) return_trace (false);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     return_trace (lookup.sanitize (c));
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 3 */
+  UINT16	format;			/* Format identifier--format = 3 */
   OffsetArrayOf<Coverage>
 		backtrack;		/* Array of coverage tables
 					 * in backtracking sequence, in  glyph
 					 * sequence order */
   OffsetArrayOf<Coverage>
 		inputX		;	/* Array of coverage
 					 * tables in input sequence, in glyph
 					 * sequence order */
@@ -2188,17 +2192,17 @@ struct ChainContext
     case 2: return_trace (c->dispatch (u.format2));
     case 3: return_trace (c->dispatch (u.format3));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT		format;	/* Format identifier */
+  UINT16		format;	/* Format identifier */
   ChainContextFormat1	format1;
   ChainContextFormat2	format2;
   ChainContextFormat3	format3;
   } u;
 };
 
 
 template <typename T>
@@ -2225,21 +2229,21 @@ struct ExtensionFormat1
   /* This is called from may_dispatch() above with hb_sanitize_context_t. */
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && extensionOffset != 0);
   }
 
   protected:
-  USHORT	format;			/* Format identifier. Set to 1. */
-  USHORT	extensionLookupType;	/* Lookup type of subtable referenced
+  UINT16	format;			/* Format identifier. Set to 1. */
+  UINT16	extensionLookupType;	/* Lookup type of subtable referenced
 					 * by ExtensionOffset (i.e. the
 					 * extension subtable). */
-  ULONG		extensionOffset;	/* Offset to the extension subtable,
+  UINT32		extensionOffset;	/* Offset to the extension subtable,
 					 * of lookup type subtable. */
   public:
   DEFINE_SIZE_STATIC (8);
 };
 
 template <typename T>
 struct Extension
 {
@@ -2267,31 +2271,28 @@ struct Extension
     switch (u.format) {
     case 1: return_trace (u.format1.dispatch (c));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   ExtensionFormat1<T>	format1;
   } u;
 };
 
 
 /*
  * GSUB/GPOS Common
  */
 
 struct GSUBGPOS
 {
-  static const hb_tag_t GSUBTag	= HB_OT_TAG_GSUB;
-  static const hb_tag_t GPOSTag	= HB_OT_TAG_GPOS;
-
   inline unsigned int get_script_count (void) const
   { return (this+scriptList).len; }
   inline const Tag& get_script_tag (unsigned int i) const
   { return (this+scriptList).get_tag (i); }
   inline 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); }
--- a/gfx/harfbuzz/src/hb-ot-layout-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-private.hh
@@ -268,23 +268,23 @@ static inline void
       if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ;
       else if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ;
       /* Mongolian Free Variation Selectors need to be remembered
        * because although we need to hide them like default-ignorables,
        * they need to non-ignorable during shaping.  This is similar to
        * what we do for joiners in Indic-like shapers, but since the
        * FVSes are GC=Mn, we have use a separate bit to remember them.
        * Fixes:
-       * https://github.com/behdad/harfbuzz/issues/234 */
+       * https://github.com/harfbuzz/harfbuzz/issues/234 */
       else if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN;
       /* TAG characters need similar treatment. Fixes:
-       * https://github.com/behdad/harfbuzz/issues/463 */
+       * https://github.com/harfbuzz/harfbuzz/issues/463 */
       else if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
       /* COMBINING GRAPHEME JOINER should not be skipped; at least some times.
-       * https://github.com/behdad/harfbuzz/issues/554 */
+       * https://github.com/harfbuzz/harfbuzz/issues/554 */
       else if (unlikely (u == 0x034Fu)) props |= UPROPS_MASK_HIDDEN;
     }
     else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat)))
     {
       /* The above check is just an optimization to let in only things we need further
        * processing on. */
 
       /* Only Mn and Mc can have non-zero ccc:
@@ -300,17 +300,17 @@ static inline void
        * Also, all Mn's that are Default_Ignorable, have ccc=0, hence
        * the "else if".
        */
       props |= unicode->modified_combining_class (info->codepoint)<<8;
 
       /* Recategorize emoji skin-tone modifiers as Unicode mark, so they
        * behave correctly in non-native directionality.  They originally
        * are MODIFIER_SYMBOL.  Fixes:
-       * https://github.com/behdad/harfbuzz/issues/169
+       * https://github.com/harfbuzz/harfbuzz/issues/169
        */
       if (unlikely (hb_in_range (u, 0x1F3FBu, 0x1F3FFu)))
       {
 	props = gen_cat = HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
       }
     }
   }
 
--- a/gfx/harfbuzz/src/hb-ot-layout.cc
+++ b/gfx/harfbuzz/src/hb-ot-layout.cc
@@ -596,16 +596,17 @@ hb_ot_layout_feature_get_lookups (hb_fac
  * hb_ot_layout_table_get_lookup_count:
  *
  * Since: 0.9.22
  **/
 unsigned int
 hb_ot_layout_table_get_lookup_count (hb_face_t    *face,
 				     hb_tag_t      table_tag)
 {
+  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return 0;
   switch (table_tag)
   {
     case HB_OT_TAG_GSUB:
     {
       return hb_ot_layout_from_face (face)->gsub_lookup_count;
     }
     case HB_OT_TAG_GPOS:
     {
--- a/gfx/harfbuzz/src/hb-ot-math-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-math-table.hh
@@ -43,17 +43,17 @@ struct MathValueRecord
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && deviceTable.sanitize (c, base));
   }
 
   protected:
-  SHORT			value;		/* The X or Y value in design units */
+  INT16			value;		/* The X or Y value in design units */
   OffsetTo<Device>	deviceTable;	/* Offset to the device table - from the
 					 * beginning of parent table. May be nullptr.
 					 * Suggested format for device table is 1. */
 
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
@@ -149,20 +149,20 @@ struct MathConstants
       return radicalDegreeBottomRaisePercent;
 
     default:
       return 0;
     }
   }
 
   protected:
-  SHORT percentScaleDown[2];
-  USHORT minHeight[2];
+  INT16 percentScaleDown[2];
+  UINT16 minHeight[2];
   MathValueRecord mathValueRecords[51];
-  SHORT radicalDegreeBottomRaisePercent;
+  INT16 radicalDegreeBottomRaisePercent;
 
   public:
   DEFINE_SIZE_STATIC (214);
 };
 
 struct MathItalicsCorrectionInfo
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -274,17 +274,17 @@ struct MathKern
 	count -= half + 1;
       } else
 	count = half;
     }
     return kernValue[i].get_x_value(font, this);
   }
 
   protected:
-  USHORT	  heightCount;
+  UINT16	  heightCount;
   MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
 					  * which the kern value changes.
 					  * Sorted by the height value in
 					  * design units (heightCount entries),
 					  * Followed by:
 					  * Array of kern values corresponding
 					  * to heights. (heightCount+1 entries).
 					  */
@@ -420,25 +420,25 @@ struct MathGlyphVariantRecord
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   protected:
   GlyphID variantGlyph;       /* Glyph ID for the variant. */
-  USHORT  advanceMeasurement; /* Advance width/height, in design units, of the
+  UINT16  advanceMeasurement; /* Advance width/height, in design units, of the
 			       * variant, in the direction of requested
 			       * glyph extension. */
 
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
-struct PartFlags : USHORT
+struct PartFlags : UINT16
 {
   enum Flags {
     Extender	= 0x0001u, /* If set, the part can be skipped or repeated. */
 
     Defined	= 0x0001u, /* All defined flags. */
   };
 
   public:
@@ -468,25 +468,25 @@ struct MathGlyphPartRecord
 
     out.flags = (hb_ot_math_glyph_part_flags_t)
 		(unsigned int)
 		(partFlags & PartFlags::Defined);
   }
 
   protected:
   GlyphID   glyph;		  /* Glyph ID for the part. */
-  USHORT    startConnectorLength; /* Advance width/ height of the straight bar
+  UINT16    startConnectorLength; /* Advance width/ height of the straight bar
 				   * connector material, in design units, is at
 				   * the beginning of the glyph, in the
 				   * direction of the extension. */
-  USHORT    endConnectorLength;   /* Advance width/ height of the straight bar
+  UINT16    endConnectorLength;   /* Advance width/ height of the straight bar
 				   * connector material, in design units, is at
 				   * the end of the glyph, in the direction of
 				   * the extension. */
-  USHORT    fullAdvance;	  /* Full advance width/height for this part,
+  UINT16    fullAdvance;	  /* Full advance width/height for this part,
 				   * in the direction of the extension.
 				   * In design units. */
   PartFlags partFlags;		  /* Part qualifiers. */
 
   public:
   DEFINE_SIZE_STATIC (10);
 };
 
@@ -646,29 +646,29 @@ struct MathVariants
 
     if (!vertical)
       index += vertGlyphCount;
 
     return this+glyphConstruction[index];
   }
 
   protected:
-  USHORT	     minConnectorOverlap; /* Minimum overlap of connecting
+  UINT16	     minConnectorOverlap; /* Minimum overlap of connecting
 					   * glyphs during glyph construction,
 					   * in design units. */
   OffsetTo<Coverage> vertGlyphCoverage;   /* Offset to Coverage table -
 					   * from the beginning of MathVariants
 					   * table. */
   OffsetTo<Coverage> horizGlyphCoverage;  /* Offset to Coverage table -
 					   * from the beginning of MathVariants
 					   * table. */
-  USHORT	     vertGlyphCount;      /* Number of glyphs for which
+  UINT16	     vertGlyphCount;      /* Number of glyphs for which
 					   * information is provided for
 					   * vertically growing variants. */
-  USHORT	     horizGlyphCount;     /* Number of glyphs for which
+  UINT16	     horizGlyphCount;     /* Number of glyphs for which
 					   * information is provided for
 					   * horizontally growing variants. */
 
   /* Array of offsets to MathGlyphConstruction tables - from the beginning of
      the MathVariants table, for shapes growing in vertical/horizontal
      direction. */
   OffsetTo<MathGlyphConstruction> glyphConstruction[VAR];
 
--- a/gfx/harfbuzz/src/hb-ot-maxp-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-maxp-table.hh
@@ -55,17 +55,17 @@ struct maxp
 		  likely (version.major == 1 ||
 			  (version.major == 0 && version.minor == 0x5000u)));
   }
 
   /* We only implement version 0.5 as none of the extra fields in version 1.0 are useful. */
   protected:
   FixedVersion<>version;		/* Version of the maxp table (0.5 or 1.0),
 					 * 0x00005000u or 0x00010000u. */
-  USHORT	numGlyphs;		/* The number of glyphs in the font. */
+  UINT16	numGlyphs;		/* The number of glyphs in the font. */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
 
 } /* namespace OT */
 
 
--- a/gfx/harfbuzz/src/hb-ot-name-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-name-table.hh
@@ -60,22 +60,22 @@ struct NameRecord
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     /* We can check from base all the way up to the end of string... */
     return_trace (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset));
   }
 
-  USHORT	platformID;	/* Platform ID. */
-  USHORT	encodingID;	/* Platform-specific encoding ID. */
-  USHORT	languageID;	/* Language ID. */
-  USHORT	nameID;		/* Name ID. */
-  USHORT	length;		/* String length (in bytes). */
-  USHORT	offset;		/* String offset from start of storage area (in bytes). */
+  UINT16	platformID;	/* Platform ID. */
+  UINT16	encodingID;	/* Platform-specific encoding ID. */
+  UINT16	languageID;	/* Language ID. */
+  UINT16	nameID;		/* Name ID. */
+  UINT16	length;		/* String length (in bytes). */
+  UINT16	offset;		/* String offset from start of storage area (in bytes). */
   public:
   DEFINE_SIZE_STATIC (12);
 };
 
 struct name
 {
   static const hb_tag_t tableTag	= HB_OT_TAG_name;
 
@@ -118,19 +118,19 @@ struct name
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  likely (format == 0 || format == 1) &&
 		  c->check_array (nameRecord, nameRecord[0].static_size, count) &&
 		  sanitize_records (c));
   }
 
   /* We only implement format 0 for now. */
-  USHORT	format;			/* Format selector (=0/1). */
-  USHORT	count;			/* Number of name records. */
-  Offset<>	stringOffset;		/* Offset to start of string storage (from start of table). */
+  UINT16	format;			/* Format selector (=0/1). */
+  UINT16	count;			/* Number of name records. */
+  Offset16	stringOffset;		/* Offset to start of string storage (from start of table). */
   NameRecord	nameRecord[VAR];	/* The name records where count is the number of records. */
   public:
   DEFINE_SIZE_ARRAY (6, nameRecord);
 };
 
 
 } /* namespace OT */
 
--- a/gfx/harfbuzz/src/hb-ot-os2-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-os2-table.hh
@@ -45,60 +45,60 @@ struct os2
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   public:
-  USHORT	version;
+  UINT16	version;
 
   /* Version 0 */
-  SHORT		xAvgCharWidth;
-  USHORT	usWeightClass;
-  USHORT	usWidthClass;
-  USHORT	fsType;
-  SHORT		ySubscriptXSize;
-  SHORT		ySubscriptYSize;
-  SHORT		ySubscriptXOffset;
-  SHORT		ySubscriptYOffset;
-  SHORT		ySuperscriptXSize;
-  SHORT		ySuperscriptYSize;
-  SHORT		ySuperscriptXOffset;
-  SHORT		ySuperscriptYOffset;
-  SHORT		yStrikeoutSize;
-  SHORT		yStrikeoutPosition;
-  SHORT		sFamilyClass;
-  BYTE		panose[10];
-  ULONG		ulUnicodeRange[4];
+  INT16		xAvgCharWidth;
+  UINT16	usWeightClass;
+  UINT16	usWidthClass;
+  UINT16	fsType;
+  INT16		ySubscriptXSize;
+  INT16		ySubscriptYSize;
+  INT16		ySubscriptXOffset;
+  INT16		ySubscriptYOffset;
+  INT16		ySuperscriptXSize;
+  INT16		ySuperscriptYSize;
+  INT16		ySuperscriptXOffset;
+  INT16		ySuperscriptYOffset;
+  INT16		yStrikeoutSize;
+  INT16		yStrikeoutPosition;
+  INT16		sFamilyClass;
+  UINT8		panose[10];
+  UINT32		ulUnicodeRange[4];
   Tag		achVendID;
-  USHORT	fsSelection;
-  USHORT	usFirstCharIndex;
-  USHORT	usLastCharIndex;
-  SHORT		sTypoAscender;
-  SHORT		sTypoDescender;
-  SHORT		sTypoLineGap;
-  USHORT	usWinAscent;
-  USHORT	usWinDescent;
+  UINT16	fsSelection;
+  UINT16	usFirstCharIndex;
+  UINT16	usLastCharIndex;
+  INT16		sTypoAscender;
+  INT16		sTypoDescender;
+  INT16		sTypoLineGap;
+  UINT16	usWinAscent;
+  UINT16	usWinDescent;
 
   /* Version 1 */
-  //ULONG ulCodePageRange1;
-  //ULONG ulCodePageRange2;
+  //UINT32 ulCodePageRange1;
+  //UINT32 ulCodePageRange2;
 
   /* Version 2 */
-  //SHORT sxHeight;
-  //SHORT sCapHeight;
-  //USHORT  usDefaultChar;
-  //USHORT  usBreakChar;
-  //USHORT  usMaxContext;
+  //INT16 sxHeight;
+  //INT16 sCapHeight;
+  //UINT16  usDefaultChar;
+  //UINT16  usBreakChar;
+  //UINT16  usMaxContext;
 
   /* Version 5 */
-  //USHORT  usLowerOpticalPointSize;
-  //USHORT  usUpperOpticalPointSize;
+  //UINT16  usLowerOpticalPointSize;
+  //UINT16  usUpperOpticalPointSize;
 
   public:
   DEFINE_SIZE_STATIC (78);
 };
 
 } /* namespace OT */
 
 
--- a/gfx/harfbuzz/src/hb-ot-post-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-post-table.hh
@@ -51,20 +51,20 @@ namespace OT {
 struct postV2Tail
 {
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (glyphNameIndex.sanitize (c));
   }
 
-  ArrayOf<USHORT>glyphNameIndex;	/* This is not an offset, but is the
+  ArrayOf<UINT16>glyphNameIndex;	/* This is not an offset, but is the
 					 * ordinal number of the glyph in 'post'
 					 * string tables. */
-  BYTE		namesX[VAR];		/* Glyph names with length bytes [variable]
+  UINT8		namesX[VAR];		/* Glyph names with length bytes [variable]
 					 * (a Pascal string). */
 
   DEFINE_SIZE_ARRAY2 (2, glyphNameIndex, namesX);
 };
 
 struct post
 {
   static const hb_tag_t tableTag = HB_OT_TAG_post;
@@ -79,29 +79,33 @@ struct post
       const postV2Tail &v2 = StructAfter<postV2Tail> (*this);
       return_trace (v2.sanitize (c));
     }
     return_trace (true);
   }
 
   struct accelerator_t
   {
-    inline void init (const post *table, unsigned int post_len)
+    inline void init (hb_face_t *face)
     {
+      blob = Sanitizer<post>::sanitize (face->reference_table (HB_OT_TAG_post));
+      const post *table = Sanitizer<post>::lock_instance (blob);
+      unsigned int table_length = hb_blob_get_length (blob);
+
       version = table->version.to_int ();
       index_to_offset.init ();
       if (version != 0x00020000)
         return;
 
       const postV2Tail &v2 = StructAfter<postV2Tail> (*table);
 
       glyphNameIndex = &v2.glyphNameIndex;
       pool = &StructAfter<uint8_t> (v2.glyphNameIndex);
 
-      const uint8_t *end = (uint8_t *) table + post_len;
+      const uint8_t *end = (uint8_t *) table + table_length;
       for (const uint8_t *data = pool; data < end && data + *data <= end; data += 1 + *data)
       {
 	uint32_t *offset = index_to_offset.push ();
 	if (unlikely (!offset))
 	  break;
 	*offset = data - pool;
       }
     }
@@ -222,18 +226,20 @@ struct post
 
       const uint8_t *data = pool + offset;
       unsigned int name_length = *data;
       data++;
 
       return hb_string_t ((const char *) data, name_length);
     }
 
+    private:
+    hb_blob_t *blob;
     uint32_t version;
-    const ArrayOf<USHORT> *glyphNameIndex;
+    const ArrayOf<UINT16> *glyphNameIndex;
     hb_prealloced_array_t<uint32_t, 1> index_to_offset;
     const uint8_t *pool;
     mutable uint16_t *gids_sorted_by_name;
   };
 
   public:
   FixedVersion<>version;		/* 0x00010000 for version 1.0
 					 * 0x00020000 for version 2.0
@@ -250,26 +256,26 @@ struct post
 					 * dictionary key (the y coordinate of the
 					 * center of the stroke) is not used for
 					 * historical reasons. The value of the
 					 * PostScript key may be calculated by
 					 * subtracting half the underlineThickness
 					 * from the value of this field. */
   FWORD		underlineThickness;	/* Suggested values for the underline
 					   thickness. */
-  ULONG		isFixedPitch;		/* Set to 0 if the font is proportionally
+  UINT32		isFixedPitch;		/* Set to 0 if the font is proportionally
 					 * spaced, non-zero if the font is not
 					 * proportionally spaced (i.e. monospaced). */
-  ULONG		minMemType42;		/* Minimum memory usage when an OpenType font
+  UINT32		minMemType42;		/* Minimum memory usage when an OpenType font
 					 * is downloaded. */
-  ULONG		maxMemType42;		/* Maximum memory usage when an OpenType font
+  UINT32		maxMemType42;		/* Maximum memory usage when an OpenType font
 					 * is downloaded. */
-  ULONG		minMemType1;		/* Minimum memory usage when an OpenType font
+  UINT32		minMemType1;		/* Minimum memory usage when an OpenType font
 					 * is downloaded as a Type 1 font. */
-  ULONG		maxMemType1;		/* Maximum memory usage when an OpenType font
+  UINT32		maxMemType1;		/* Maximum memory usage when an OpenType font
 					 * is downloaded as a Type 1 font. */
 /*postV2Tail	v2[VAR];*/
   DEFINE_SIZE_STATIC (32);
 };
 
 } /* namespace OT */
 
 
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh
@@ -38,26 +38,26 @@
 
 /* First we measure, then we cut. */
 #ifndef OT_MEASURE
 #define OT_MEASURE
 #define OT_TABLE_START			static const struct TABLE_NAME {
 #define OT_TABLE_END			}
 #define OT_LABEL_START(Name)		unsigned char Name[
 #define OT_LABEL_END			];
-#define OT_BYTE(u8)			+1/*byte*/
-#define OT_USHORT(u16)			+2/*bytes*/
+#define OT_UINT8(u8)			+1/*byte*/
+#define OT_UINT16(u16)			+2/*bytes*/
 #else
 #undef  OT_MEASURE
 #define OT_TABLE_START			TABLE_NAME = {
 #define OT_TABLE_END			};
 #define OT_LABEL_START(Name)		{
 #define OT_LABEL_END			},
-#define OT_BYTE(u8)			(u8),
-#define OT_USHORT(u16)			(unsigned char)((u16)>>8), (unsigned char)((u16)&0xFFu),
+#define OT_UINT8(u8)			(u8),
+#define OT_UINT16(u16)			(unsigned char)((u16)>>8), (unsigned char)((u16)&0xFFu),
 #define OT_COUNT(Name, ItemSize)	((unsigned int) sizeof(((struct TABLE_NAME*)0)->Name) \
 					 / (unsigned int)(ItemSize) \
 					 /* OT_ASSERT it's divisible (and positive). */)
 #define OT_DISTANCE(From,To)		((unsigned int) \
 					 ((char*)(&((struct TABLE_NAME*)0)->To) - \
 					  (char*)(&((struct TABLE_NAME*)0)->From)) \
 					 /* OT_ASSERT it's positive. */)
 #endif
@@ -75,60 +75,60 @@
 #define OT_LIST(...) __VA_ARGS__
 
 
 /*
  * Basic Types
  */
 
 #define OT_TAG(a,b,c,d) \
-	OT_BYTE(a) OT_BYTE(b) OT_BYTE(c) OT_BYTE(d)
+	OT_UINT8(a) OT_UINT8(b) OT_UINT8(c) OT_UINT8(d)
 
 #define OT_OFFSET(From, To) /* Offset from From to To in bytes */ \
-	OT_USHORT(OT_DISTANCE(From, To))
+	OT_UINT16(OT_DISTANCE(From, To))
 
 #define OT_GLYPHID /* GlyphID */ \
-	OT_USHORT
+	OT_UINT16
 
 #define OT_UARRAY(Name, Items) \
 	OT_LABEL_START(Name) \
-	OT_USHORT(OT_COUNT(Name##Data, 2)) \
+	OT_UINT16(OT_COUNT(Name##Data, 2)) \
 	OT_LABEL(Name##Data) \
 	Items \
 	OT_LABEL_END
 
 #define OT_UHEADLESSARRAY(Name, Items) \
 	OT_LABEL_START(Name) \
-	OT_USHORT(OT_COUNT(Name##Data, 2) + 1) \
+	OT_UINT16(OT_COUNT(Name##Data, 2) + 1) \
 	OT_LABEL(Name##Data) \
 	Items \
 	OT_LABEL_END
 
 
 /*
  * Common Types
  */
 
 #define OT_LOOKUP_FLAG_IGNORE_MARKS	0x08u
 
 #define OT_LOOKUP(Name, LookupType, LookupFlag, SubLookupOffsets) \
 	OT_LABEL_START(Name) \
-	OT_USHORT(LookupType) \
-	OT_USHORT(LookupFlag) \
+	OT_UINT16(LookupType) \
+	OT_UINT16(LookupFlag) \
 	OT_LABEL_END \
 	OT_UARRAY(Name##SubLookupOffsetsArray, OT_LIST(SubLookupOffsets))
 
 #define OT_SUBLOOKUP(Name, SubFormat, Items) \
 	OT_LABEL_START(Name) \
-	OT_USHORT(SubFormat) \
+	OT_UINT16(SubFormat) \
 	Items
 
 #define OT_COVERAGE1(Name, Items) \
 	OT_LABEL_START(Name) \
-	OT_USHORT(1) \
+	OT_UINT16(1) \
 	OT_LABEL_END \
 	OT_UARRAY(Name##Glyphs, OT_LIST(Items))
 
 
 /*
  * GSUB
  */
 
@@ -169,17 +169,17 @@
  */
 
 /* Table name. */
 #define TABLE_NAME arabic_win1256_gsub_lookups
 
 /* Table manifest. */
 #define MANIFEST(Items) \
 	OT_LABEL_START(manifest) \
-	OT_USHORT(OT_COUNT(manifestData, 6)) \
+	OT_UINT16(OT_COUNT(manifestData, 6)) \
 	OT_LABEL(manifestData) \
 	Items \
 	OT_LABEL_END
 
 #define MANIFEST_LOOKUP(Tag, Name) \
 	Tag \
 	OT_OFFSET(manifest, Name)
 
@@ -299,18 +299,18 @@ OT_TABLE_END
 
 /*
  * Clean up
  */
 #undef OT_TABLE_START
 #undef OT_TABLE_END
 #undef OT_LABEL_START
 #undef OT_LABEL_END
-#undef OT_BYTE
-#undef OT_USHORT
+#undef OT_UINT8
+#undef OT_UINT16
 #undef OT_DISTANCE
 #undef OT_COUNT
 
 /*
  * Include a second time to get the table data...
  */
 #if 0
 #include "hb-private.hh" /* Make check-includes.sh happy. */
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc
@@ -31,17 +31,17 @@
 
 
 /* buffer var allocations */
 #define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */
 
 #define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_COMPLEX0
 
 /* See:
- * https://github.com/behdad/harfbuzz/commit/6e6f82b6f3dde0fc6c3c7d991d9ec6cfff57823d#commitcomment-14248516 */
+ * https://github.com/harfbuzz/harfbuzz/commit/6e6f82b6f3dde0fc6c3c7d991d9ec6cfff57823d#commitcomment-14248516 */
 #define HB_ARABIC_GENERAL_CATEGORY_IS_WORD(gen_cat) \
 	(FLAG_UNSAFE (gen_cat) & \
 	 (FLAG (HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED) | \
 	  FLAG (HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE) | \
 	  /*FLAG (HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER) |*/ \
 	  FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER) | \
 	  FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) | \
 	  /*FLAG (HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER) |*/ \
@@ -193,17 +193,17 @@ collect_features_arabic (hb_ot_shape_pla
    *
    * At least for Arabic, looks like Uniscribe has a pause between
    * rlig and calt.  Otherwise the IranNastaliq's ALLAH ligature won't
    * work.  However, testing shows that rlig and calt are applied
    * together for Mongolian in Uniscribe.  As such, we only add a
    * pause for Arabic, not other scripts.
    *
    * A pause after calt is required to make KFGQPC Uthmanic Script HAFS
-   * work correctly.  See https://github.com/behdad/harfbuzz/issues/505
+   * work correctly.  See https://github.com/harfbuzz/harfbuzz/issues/505
    */
 
   map->add_gsub_pause (nuke_joiners);
 
   map->add_global_bool_feature (HB_TAG('s','t','c','h'));
   map->add_gsub_pause (record_stch);
 
   map->add_global_bool_feature (HB_TAG('c','c','m','p'));
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
@@ -156,17 +156,17 @@ compose_hebrew (const hb_ot_shape_normal
 
 static bool
 disable_otl_hebrew (const hb_ot_shape_plan_t *plan)
 {
   /* For Hebrew shaper, use fallback if GPOS does not have 'hebr'
    * script.  This matches Uniscribe better, and makes fonts like
    * Arial that have GSUB/GPOS/GDEF but no data for Hebrew work.
    * See:
-   * https://github.com/behdad/harfbuzz/issues/347#issuecomment-267838368
+   * https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368
    */
   return plan->map.chosen_script[1] != HB_TAG ('h','e','b','r');
 }
 
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
 {
   nullptr, /* collect_features */
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh
@@ -118,17 +118,17 @@ enum indic_syllabic_category_t {
   INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER		= OT_M, /* U+17CD only. */
   INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL		= OT_CM,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER		= OT_PLACEHOLDER,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA	= OT_Repha,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED		= OT_X, /* Don't care. */
   INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED		= OT_CM,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA	= OT_N,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER	= OT_CS,
-  INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK		= OT_SM, /* https://github.com/behdad/harfbuzz/issues/552 */
+  INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK		= OT_SM, /* https://github.com/harfbuzz/harfbuzz/issues/552 */
   INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER		= OT_Coeng,
   INDIC_SYLLABIC_CATEGORY_JOINER			= OT_ZWJ,
   INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER		= OT_X,
   INDIC_SYLLABIC_CATEGORY_NON_JOINER			= OT_ZWNJ,
   INDIC_SYLLABIC_CATEGORY_NUKTA				= OT_N,
   INDIC_SYLLABIC_CATEGORY_NUMBER			= OT_PLACEHOLDER,
   INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER			= OT_PLACEHOLDER, /* Don't care. */
   INDIC_SYLLABIC_CATEGORY_PURE_KILLER			= OT_M, /* Is like a vowel matra. */
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc
@@ -205,29 +205,30 @@ set_indic_properties (hb_glyph_info_t &i
   {
     /* These can occur mid-syllable (eg. before matras), even though Unicode marks them as Syllable_Modifier.
      * https://github.com/roozbehp/unicode-data/issues/5 */
     cat = OT_M;
     pos = POS_ABOVE_C;
   }
   else if (unlikely (u == 0x0A51u))
   {
-    /* https://github.com/behdad/harfbuzz/issues/524 */
+    /* https://github.com/harfbuzz/harfbuzz/issues/524 */
     cat = OT_M;
     pos = POS_BELOW_C;
   }
 
   /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
    * so the Indic shaper needs to know their categories. */
   else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM;
   else if (unlikely (u == 0x1133cu)) cat = OT_N;
 
-  else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/behdad/harfbuzz/issues/552 */
+  else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */
 
-  else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/behdad/harfbuzz/issues/538 */
+  else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
+  else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
   else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */
   else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
 				    cat = OT_PLACEHOLDER;
   else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
 
 
   /*
    * Re-assign position.
@@ -686,17 +687,17 @@ static void
 initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
 				       hb_face_t *face,
 				       hb_buffer_t *buffer,
 				       unsigned int start, unsigned int end)
 {
   const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
   hb_glyph_info_t *info = buffer->info;
 
-  /* https://github.com/behdad/harfbuzz/issues/435#issuecomment-335560167
+  /* https://github.com/harfbuzz/harfbuzz/issues/435#issuecomment-335560167
    * // For compatibility with legacy usage in Kannada,
    * // Ra+h+ZWJ must behave like Ra+ZWJ+h...
    */
   if (buffer->props.script == HB_SCRIPT_KANNADA &&
       start + 3 <= end &&
       is_one_of (info[start  ], FLAG (OT_Ra)) &&
       is_one_of (info[start+1], FLAG (OT_H)) &&
       is_one_of (info[start+2], FLAG (OT_ZWJ)))
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl
@@ -85,17 +85,17 @@ VMBlw	= 38; # VOWEL_MOD_BELOW
 VMPst	= 39; # VOWEL_MOD_POST
 VMPre	= 23; # VOWEL_MOD_PRE
 SMAbv	= 41; # SYM_MOD_ABOVE
 SMBlw	= 42; # SYM_MOD_BELOW
 CS	= 43; # CONS_WITH_STACKER
 
 
 consonant_modifiers = CMAbv* CMBlw* ((H B | SUB) VS? CMAbv? CMBlw*)*;
-# Override: Allow two MBlw. https://github.com/behdad/harfbuzz/issues/376
+# Override: Allow two MBlw. https://github.com/harfbuzz/harfbuzz/issues/376
 medial_consonants = MPre? MAbv? MBlw?.MBlw? MPst?;
 dependent_vowels = VPre* VAbv* VBlw* VPst*;
 vowel_modifiers = VMPre* VMAbv* VMBlw* VMPst*;
 final_consonants = FAbv* FBlw* FPst* FM?;
 
 virama_terminated_cluster =
 	(R|CS)? (B | GB) VS?
 	consonant_modifiers
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc
@@ -343,17 +343,24 @@ static const USE_TABLE_ELEMENT_TYPE use_
 
   /* 2060 */    WJ,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
   /* Superscripts and Subscripts */
 
   /* 2070 */     O,     O,     O,     O,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 2080 */     O,     O,    FM,    FM,    FM,     O,     O,     O,
 
-#define use_offset_0xa800u 2616
+#define use_offset_0x20f0u 2616
+
+
+  /* Combining Diacritical Marks for Symbols */
+
+  /* 20F0 */ VMAbv,     O,     O,     O,     O,     O,     O,     O,
+
+#define use_offset_0xa800u 2624
 
 
   /* Syloti Nagri */
 
   /* A800 */     B,     B,     O,     B,     B,     B,  VAbv,     B,     B,     B,     B, VMAbv,     B,     B,     B,     B,
   /* A810 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* A820 */     B,     B,     B,  VPst,  VPst,  VBlw,  VAbv,  VPst,     O,     O,     O,     O,     O,     O,     O,     O,
   /* A830 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
@@ -365,17 +372,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
   /* A860 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* A870 */     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
   /* Saurashtra */
 
   /* A880 */ VMPst, VMPst,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* A890 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* A8A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A8B0 */     B,     B,     B,     B,  FPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,
+  /* A8B0 */     B,     B,     B,     B,  MPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,
   /* A8C0 */  VPst,  VPst,  VPst,  VPst,     H, VMAbv,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* A8D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
   /* Devanagari Extended */
 
   /* A8E0 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,
   /* A8F0 */ VMAbv, VMAbv,     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
@@ -430,45 +437,45 @@ static const USE_TABLE_ELEMENT_TYPE use_
   /* AAC0 */     B, VMAbv,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* AAD0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
   /* Meetei Mayek Extensions */
 
   /* AAE0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPre,  VBlw,  VAbv,  VPre,  VPst,
   /* AAF0 */     O,     O,     O,     O,     O, VMPst,     H,     O,
 
-#define use_offset_0xabc0u 3376
+#define use_offset_0xabc0u 3384
 
 
   /* Meetei Mayek */
 
   /* ABC0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* ABD0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* ABE0 */     B,     B,     B,  VPst,  VPst,  VAbv,  VPst,  VPst,  VBlw,  VPst,  VPst,     O, VMPst,  VBlw,     O,     O,
   /* ABF0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0xfe00u 3440
+#define use_offset_0xfe00u 3448
 
 
   /* Variation Selectors */
 
   /* FE00 */    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,
 
-#define use_offset_0x10a00u 3456
+#define use_offset_0x10a00u 3464
 
 
   /* Kharoshthi */
 
   /* 10A00 */     B,  VBlw,  VBlw,  VBlw,     O,  VAbv,  VBlw,     O,     O,     O,     O,     O,  VBlw,  VBlw, VMBlw, VMAbv,
   /* 10A10 */     B,     B,     B,     B,     O,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,
   /* 10A20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 10A30 */     B,     B,     B,     B,     O,     O,     O,     O, CMAbv, CMBlw, CMBlw,     O,     O,     O,     O,     H,
   /* 10A40 */     B,     B,     B,     B,     B,     B,     B,     B,
 
-#define use_offset_0x11000u 3528
+#define use_offset_0x11000u 3536
 
 
   /* Brahmi */
 
   /* 11000 */ VMPst, VMAbv, VMPst,    CS,    CS,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11010 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11020 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11030 */     B,     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,
@@ -479,17 +486,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
 
   /* Kaithi */
 
   /* 11080 */ VMAbv, VMAbv, VMPst,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11090 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 110A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 110B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VAbv,  VAbv,  VPst,  VPst,     H, CMBlw,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11100u 3720
+#define use_offset_0x11100u 3728
 
 
   /* Chakma */
 
   /* 11100 */ VMAbv, VMAbv, VMAbv,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11110 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11120 */     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VAbv,  VAbv,  VAbv,
   /* 11130 */  VAbv,  VBlw,  VBlw,     H,  VAbv,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
@@ -517,17 +524,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
 
   /* Khojki */
 
   /* 11200 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11210 */     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11220 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,  VPst,  VPst,  VBlw,
   /* 11230 */  VAbv,  VAbv,  VAbv,  VAbv, VMAbv,     H, CMAbv, CMAbv,     O,     O,     O,     O,     O,     O, VMAbv,     O,
 
-#define use_offset_0x11280u 4040
+#define use_offset_0x11280u 4048
 
 
   /* Multani */
 
   /* 11280 */     B,     B,     B,     B,     B,     B,     B,     O,     B,     O,     B,     B,     B,     B,     O,     B,
   /* 11290 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,
   /* 112A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,
 
@@ -545,17 +552,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
   /* 11310 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11320 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 11330 */     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VPst,
   /* 11340 */  VAbv,  VPst,  VPst,  VPst,  VPst,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,     O,     O,
   /* 11350 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     O,     O,     B,     B,
   /* 11360 */     B,     B,  VPst,  VPst,     O,     O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
   /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
 
-#define use_offset_0x11400u 4288
+#define use_offset_0x11400u 4296
 
 
   /* Newa */
 
   /* 11400 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11410 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11420 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11430 */     B,     B,     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,
@@ -568,17 +575,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
 
   /* 11480 */     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11490 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 114A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 114B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VPre,  VAbv,  VPre,  VPre,  VPst,  VPre, VMAbv,
   /* 114C0 */ VMAbv, VMPst,     H, CMBlw,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 114D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11580u 4512
+#define use_offset_0x11580u 4520
 
 
   /* Siddham */
 
   /* 11580 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11590 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 115A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,
   /* 115B0 */  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,  VPre,  VPre, VMAbv, VMAbv, VMPst,     H,
@@ -611,17 +618,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
 
   /* Ahom */
 
   /* 11700 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11710 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,  MBlw,  MPre,  MAbv,
   /* 11720 */  VPst,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VAbv,  VBlw,  VAbv,  VAbv,  VAbv,     O,     O,     O,     O,
   /* 11730 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
 
-#define use_offset_0x11a00u 4960
+#define use_offset_0x11a00u 4968
 
 
   /* Zanabazar Square */
 
   /* 11A00 */     B,  VAbv,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,     B,     B,     B,     B,     B,
   /* 11A10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11A20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11A30 */     B,     B,     B,    FM,  VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst,     R,  MBlw,  MBlw,  MBlw,  MBlw,    GB,
@@ -630,17 +637,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
   /* Soyombo */
 
   /* 11A50 */     B,  VAbv,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VPst,  VPst,  VBlw,  VBlw,  VBlw,     B,     B,     B,     B,
   /* 11A60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11A70 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11A80 */     B,     B,     B,     B,     O,     O,     R,     R,     R,     R,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,
   /* 11A90 */  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw, VMAbv, VMPst, CMAbv,     H,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11c00u 5120
+#define use_offset_0x11c00u 5128
 
 
   /* Bhaiksuki */
 
   /* 11C00 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 11C10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11C20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,
   /* 11C30 */  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,     O,  VAbv,  VAbv,  VAbv,  VAbv, VMAbv, VMAbv, VMPst,     H,
@@ -651,29 +658,29 @@ static const USE_TABLE_ELEMENT_TYPE use_
   /* Marchen */
 
   /* 11C70 */     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11C80 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11C90 */     O,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
   /* 11CA0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
   /* 11CB0 */  VBlw,  VPre,  VBlw,  VAbv,  VPst, VMAbv, VMAbv,     O,
 
-#define use_offset_0x11d00u 5304
+#define use_offset_0x11d00u 5312
 
 
   /* Masaram Gondi */
 
   /* 11D00 */     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,
   /* 11D10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11D20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11D30 */     B,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,     O,     O,     O,  VAbv,     O,  VAbv,  VAbv,     O,  VAbv,
   /* 11D40 */ VMAbv, VMAbv, CMBlw,  VAbv,  VBlw,     H,     R,  MBlw,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11D50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-}; /* Table items: 5400; occupancy: 73% */
+}; /* Table items: 5408; occupancy: 73% */
 
 USE_TABLE_ELEMENT_TYPE
 hb_use_get_categories (hb_codepoint_t u)
 {
   switch (u >> 12)
   {
     case 0x0u:
       if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u];
@@ -689,16 +696,17 @@ hb_use_get_categories (hb_codepoint_t u)
       if (hb_in_range<hb_codepoint_t> (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u];
       if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u];
       if (hb_in_range<hb_codepoint_t> (u, 0x1DF8u, 0x1DFFu)) return use_table[u - 0x1DF8u + use_offset_0x1df8u];
       break;
 
     case 0x2u:
       if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2017u)) return use_table[u - 0x2008u + use_offset_0x2008u];
       if (hb_in_range<hb_codepoint_t> (u, 0x2060u, 0x2087u)) return use_table[u - 0x2060u + use_offset_0x2060u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x20F0u, 0x20F7u)) return use_table[u - 0x20F0u + use_offset_0x20f0u];
       if (unlikely (u == 0x25CCu)) return GB;
       break;
 
     case 0xAu:
       if (hb_in_range<hb_codepoint_t> (u, 0xA800u, 0xAAF7u)) return use_table[u - 0xA800u + use_offset_0xa800u];
       if (hb_in_range<hb_codepoint_t> (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u];
       break;
 
--- a/gfx/harfbuzz/src/hb-ot-shape-fallback.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-fallback.cc
@@ -213,20 +213,20 @@ position_mark (const hb_ot_shape_plan_t 
   /* We don't position LEFT and RIGHT marks. */
 
   /* X positioning */
   switch (combining_class)
   {
     case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW:
     case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
       if (buffer->props.direction == HB_DIRECTION_LTR) {
-	pos.x_offset += base_extents.x_bearing - mark_extents.width / 2 - mark_extents.x_bearing;
+	pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing;
         break;
       } else if (buffer->props.direction == HB_DIRECTION_RTL) {
-	pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing;
+	pos.x_offset += base_extents.x_bearing - mark_extents.width / 2 - mark_extents.x_bearing;
         break;
       }
       HB_FALLTHROUGH;
 
     default:
     case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
     case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
     case HB_UNICODE_COMBINING_CLASS_BELOW:
--- a/gfx/harfbuzz/src/hb-ot-shape.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape.cc
@@ -103,17 +103,17 @@ hb_ot_shape_collect_features (hb_ot_shap
       map->add_feature (horizontal_features[i], 1, F_GLOBAL |
 			(horizontal_features[i] == HB_TAG('k','e','r','n') ?
 			 F_HAS_FALLBACK : F_NONE));
   else
   {
     /* We really want to find a 'vert' feature if there's any in the font, no
      * matter which script/langsys it is listed (or not) under.
      * See various bugs referenced from:
-     * https://github.com/behdad/harfbuzz/issues/63 */
+     * https://github.com/harfbuzz/harfbuzz/issues/63 */
     map->add_feature (HB_TAG ('v','e','r','t'), 1, F_GLOBAL | 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];
@@ -812,21 +812,26 @@ hb_propagate_flags (hb_buffer_t *buffer)
 
 /* Pull it all together! */
 
 static void
 hb_ot_shape_internal (hb_ot_shape_context_t *c)
 {
   c->buffer->deallocate_var_all ();
   c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
-  if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_EXPANSION_FACTOR)))
+  if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR)))
   {
-    c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_EXPANSION_FACTOR,
+    c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR,
 			      (unsigned) HB_BUFFER_MAX_LEN_MIN);
   }
+  if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR)))
+  {
+    c->buffer->max_ops = MAX (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR,
+			      (unsigned) HB_BUFFER_MAX_OPS_MIN);
+  }
 
   bool disable_otl = c->plan->shaper->disable_otl && c->plan->shaper->disable_otl (c->plan);
   //c->fallback_substitute     = disable_otl || !hb_ot_layout_has_substitution (c->face);
   c->fallback_positioning    = disable_otl || !hb_ot_layout_has_positioning (c->face);
   c->fallback_glyph_classes  = disable_otl || !hb_ot_layout_has_glyph_classes (c->face);
 
   /* Save the original direction, we use it later. */
   c->target_direction = c->buffer->props.direction;
@@ -856,16 +861,17 @@ hb_ot_shape_internal (hb_ot_shape_contex
 
   hb_propagate_flags (c->buffer);
 
   _hb_buffer_deallocate_unicode_vars (c->buffer);
 
   c->buffer->props.direction = c->target_direction;
 
   c->buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
+  c->buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
   c->buffer->deallocate_var_all ();
 }
 
 
 hb_bool_t
 _hb_ot_shape (hb_shape_plan_t    *shape_plan,
 	      hb_font_t          *font,
 	      hb_buffer_t        *buffer,
--- a/gfx/harfbuzz/src/hb-ot-var-avar-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-var-avar-table.hh
@@ -128,18 +128,18 @@ struct avar
       coords[i] = map->map (coords[i]);
       map = &StructAfter<SegmentMaps> (*map);
     }
   }
 
   protected:
   FixedVersion<>version;	/* Version of the avar table
 				 * initially set to 0x00010000u */
-  USHORT	reserved;	/* This field is permanently reserved. Set to 0. */
-  USHORT	axisCount;	/* The number of variation axes in the font. This
+  UINT16	reserved;	/* This field is permanently reserved. Set to 0. */
+  UINT16	axisCount;	/* The number of variation axes in the font. This
 				 * must be the same number as axisCount in the
 				 * 'fvar' table. */
   SegmentMaps	axisSegmentMapsZ;
 
   public:
   DEFINE_SIZE_MIN (8);
 };
 
--- a/gfx/harfbuzz/src/hb-ot-var-fvar-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-var-fvar-table.hh
@@ -37,21 +37,21 @@ struct InstanceRecord
   inline bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  c->check_array (coordinates, coordinates[0].static_size, axis_count));
   }
 
   protected:
-  USHORT	subfamilyNameID;/* The name ID for entries in the 'name' table
+  UINT16	subfamilyNameID;/* The name ID for entries in the 'name' table
 				 * that provide subfamily names for this instance. */
-  USHORT	reserved;	/* Reserved for future use — set to 0. */
+  UINT16	reserved;	/* Reserved for future use — set to 0. */
   Fixed		coordinates[VAR];/* The coordinates array for this instance. */
-  //USHORT	postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
+  //UINT16	postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
   //				  * table that provide PostScript names for this
   //				  * instance. */
 
   public:
   DEFINE_SIZE_ARRAY (4, coordinates);
 };
 
 struct AxisRecord
@@ -62,18 +62,18 @@ struct AxisRecord
     return_trace (c->check_struct (this));
   }
 
   public:
   Tag		axisTag;	/* Tag identifying the design variation for the axis. */
   Fixed		minValue;	/* The minimum coordinate value for the axis. */
   Fixed		defaultValue;	/* The default coordinate value for the axis. */
   Fixed		maxValue;	/* The maximum coordinate value for the axis. */
-  USHORT	reserved;	/* Reserved for future use — set to 0. */
-  USHORT	axisNameID;	/* The name ID for entries in the 'name' table that
+  UINT16	reserved;	/* Reserved for future use — set to 0. */
+  UINT16	axisNameID;	/* The name ID for entries in the 'name' table that
 				 * provide a display name for this axis. */
 
   public:
   DEFINE_SIZE_STATIC (20);
 };
 
 
 /*
@@ -181,26 +181,26 @@ struct fvar
   { return &StructAtOffset<AxisRecord> (this, things); }
 
   inline const InstanceRecord * get_instances (void) const
   { return &StructAtOffset<InstanceRecord> (get_axes () + axisCount, 0); }
 
   protected:
   FixedVersion<>version;	/* Version of the fvar table
 				 * initially set to 0x00010000u */
-  Offset<>	things;		/* Offset in bytes from the beginning of the table
+  Offset16	things;		/* Offset in bytes from the beginning of the table
 				 * to the start of the AxisRecord array. */
-  USHORT	reserved;	/* This field is permanently reserved. Set to 2. */
-  USHORT	axisCount;	/* The number of variation axes in the font (the
+  UINT16	reserved;	/* This field is permanently reserved. Set to 2. */
+  UINT16	axisCount;	/* The number of variation axes in the font (the
 				 * number of records in the axes array). */
-  USHORT	axisSize;	/* The size in bytes of each VariationAxisRecord —
+  UINT16	axisSize;	/* The size in bytes of each VariationAxisRecord —
 				 * set to 20 (0x0014) for this version. */
-  USHORT	instanceCount;	/* The number of named instances defined in the font
+  UINT16	instanceCount;	/* The number of named instances defined in the font
 				 * (the number of records in the instances array). */
-  USHORT	instanceSize;	/* The size in bytes of each InstanceRecord — set
+  UINT16	instanceSize;	/* The size in bytes of each InstanceRecord — set
 				 * to either axisCount * sizeof(Fixed) + 4, or to
 				 * axisCount * sizeof(Fixed) + 6. */
 
   public:
   DEFINE_SIZE_STATIC (16);
 };
 
 } /* namespace OT */
--- a/gfx/harfbuzz/src/hb-ot-var-hvar-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-var-hvar-table.hh
@@ -50,17 +50,17 @@ struct DeltaSetIndexMap
       return v;
 
     if (v >= mapCount)
       v = mapCount - 1;
 
     unsigned int u = 0;
     { /* Fetch it. */
       unsigned int w = get_width ();
-      const BYTE *p = mapData + w * v;
+      const UINT8 *p = mapData + w * v;
       for (; w; w--)
 	u = (u << 8) + *p++;
     }
 
     { /* Repack it. */
       unsigned int n = get_inner_bitcount ();
       unsigned int outer = u >> n;
       unsigned int inner = u & ((1 << n) - 1);
@@ -73,20 +73,20 @@ struct DeltaSetIndexMap
   protected:
   inline unsigned int get_width (void) const
   { return ((format >> 4) & 3) + 1; }
 
   inline unsigned int get_inner_bitcount (void) const
   { return (format & 0xF) + 1; }
 
   protected:
-  USHORT	format;		/* A packed field that describes the compressed
+  UINT16	format;		/* A packed field that describes the compressed
 				 * representation of delta-set indices. */
-  USHORT	mapCount;	/* The number of mapping entries. */
-  BYTE		mapData[VAR];	/* The delta-set index mapping data. */
+  UINT16	mapCount;	/* The number of mapping entries. */
+  UINT8		mapData[VAR];	/* The delta-set index mapping data. */
 
   public:
   DEFINE_SIZE_ARRAY (4, mapData);
 };
 
 
 /*
  * HVAR -- The Horizontal Metrics Variations Table
--- a/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh
@@ -38,17 +38,17 @@ struct VariationValueRecord
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   public:
   Tag		valueTag;	/* Four-byte tag identifying a font-wide measure. */
-  ULONG		varIdx;		/* Outer/inner index into VariationStore item. */
+  UINT32		varIdx;		/* Outer/inner index into VariationStore item. */
 
   public:
   DEFINE_SIZE_STATIC (8);
 };
 
 
 /*
  * MVAR -- Metrics Variations Table
@@ -90,23 +90,23 @@ protected:
     const hb_tag_t *a = (const hb_tag_t *) pa;
     const Tag *b = (const Tag *) pb;
     return b->cmp (*a);
   }
 
   protected:
   FixedVersion<>version;	/* Version of the metrics variation table
 				 * initially set to 0x00010000u */
-  USHORT	reserved;	/* Not used; set to 0. */
-  USHORT	valueRecordSize;/* The size in bytes of each value record —
+  UINT16	reserved;	/* Not used; set to 0. */
+  UINT16	valueRecordSize;/* The size in bytes of each value record —
 				 * must be greater than zero. */
-  USHORT	valueRecordCount;/* The number of value records — may be zero. */
+  UINT16	valueRecordCount;/* The number of value records — may be zero. */
   OffsetTo<VariationStore>
 		varStore;	/* Offset to item variation store table. */
-  BYTE		values[VAR];	/* Array of value records. The records must be
+  UINT8		values[VAR];	/* Array of value records. The records must be
 				 * in binary order of their valueTag field. */
 
   public:
   DEFINE_SIZE_ARRAY (12, values);
 };
 
 } /* namespace OT */
 
--- a/gfx/harfbuzz/src/hb-private.hh
+++ b/gfx/harfbuzz/src/hb-private.hh
@@ -687,17 +687,17 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, 
 }
 
 
 /* Enable bitwise ops on enums marked as flags_t */
 /* To my surprise, looks like the function resolver is happy to silently cast
  * one enum to another...  So this doesn't provide the type-checking that I
  * originally had in mind... :(.
  *
- * For MSVC warnings, see: https://github.com/behdad/harfbuzz/pull/163
+ * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
  */
 #ifdef _MSC_VER
 # pragma warning(disable:4200)
 # pragma warning(disable:4800)
 #endif
 #define HB_MARK_AS_FLAG_T(T) \
 	extern "C++" { \
 	  static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
--- a/gfx/harfbuzz/src/hb-set-private.hh
+++ b/gfx/harfbuzz/src/hb-set-private.hh
@@ -30,47 +30,67 @@
 #include "hb-private.hh"
 #include "hb-object-private.hh"
 
 
 /*
  * hb_set_t
  */
 
+/* TODO Keep a free-list so we can free pages that are completely zeroed.  At that
+ * point maybe also use a sentinel value for "all-1" pages? */
+
 struct hb_set_t
 {
   struct page_map_t
   {
     inline int cmp (const page_map_t *o) const { return (int) o->major - (int) major; }
 
     uint32_t major;
     uint32_t index;
   };
 
   struct page_t
   {
-    inline void init (void) {
-      memset (&v, 0, sizeof (v));
-    }
+    inline void init0 (void) { memset (&v, 0, sizeof (v)); }
+    inline void init1 (void) { memset (&v, 0xff, sizeof (v)); }
 
     inline unsigned int len (void) const
     { return ARRAY_LENGTH_CONST (v); }
 
     inline bool is_empty (void) const
     {
       for (unsigned int i = 0; i < len (); i++)
         if (v[i])
 	  return false;
       return true;
     }
 
     inline void add (hb_codepoint_t g) { elt (g) |= mask (g); }
     inline void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
     inline bool has (hb_codepoint_t g) const { return !!(elt (g) & mask (g)); }
 
+    inline void add_range (hb_codepoint_t a, hb_codepoint_t b)
+    {
+     elt_t *la = &elt (a);
+     elt_t *lb = &elt (b);
+     if (la == lb)
+       *la |= (mask (b) << 1) - mask(a);
+     else
+     {
+       *la |= ~(mask (a) - 1);
+       la++;
+
+       memset (la, 0xff, (char *) lb - (char *) la);
+
+       *lb |= ((mask (b) << 1) - 1);
+
+     }
+    }
+
     inline bool is_equal (const page_t *other) const
     {
       return 0 == memcmp (&v, &other->v, sizeof (v));
     }
 
     inline unsigned int get_population (void) const
     {
       unsigned int pop = 0;
@@ -191,37 +211,59 @@ struct hb_set_t
     return true;
   }
 
   inline void add (hb_codepoint_t g)
   {
     if (unlikely (in_error)) return;
     if (unlikely (g == INVALID)) return;
     page_t *page = page_for_insert (g);
-    if (!page)
-      return;
+    if (unlikely (!page)) return;
     page->add (g);
   }
   inline void add_range (hb_codepoint_t a, hb_codepoint_t b)
   {
-    if (unlikely (in_error)) return;
-    /* TODO Speedup */
-    for (unsigned int i = a; i < b + 1; i++)
-      add (i);
+    if (unlikely (in_error || a > b || a == INVALID || b == INVALID)) return;
+    unsigned int ma = get_major (a);
+    unsigned int mb = get_major (b);
+    if (ma == mb)
+    {
+      page_t *page = page_for_insert (a);
+      if (unlikely (!page)) return;
+      page->add_range (a, b);
+    }
+    else
+    {
+      page_t *page = page_for_insert (a);
+      if (unlikely (!page)) return;
+      page->add_range (a, major_start (ma + 1) - 1);
+
+      for (unsigned int m = ma + 1; m < mb; m++)
+      {
+	page = page_for_insert (major_start (m));
+	if (unlikely (!page)) return;
+	page->init1 ();
+      }
+
+      page = page_for_insert (b);
+      if (unlikely (!page)) return;
+      page->add_range (major_start (mb), b);
+    }
   }
   inline void del (hb_codepoint_t g)
   {
     if (unlikely (in_error)) return;
     page_t *p = page_for (g);
     if (!p)
       return;
     p->del (g);
   }
   inline void del_range (hb_codepoint_t a, hb_codepoint_t b)
   {
+    /* TODO Optimize, like add_range(). */
     if (unlikely (in_error)) return;
     for (unsigned int i = a; i < b + 1; i++)
       del (i);
   }
   inline bool has (hb_codepoint_t g) const
   {
     const page_t *p = page_for (g);
     if (!p)
@@ -428,46 +470,47 @@ struct hb_set_t
     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 INVALID;
   }
 
   static  const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
 
-  page_t *page_for_insert (hb_codepoint_t g)
+  inline page_t *page_for_insert (hb_codepoint_t g)
   {
     page_map_t map = {get_major (g), pages.len};
     unsigned int i;
     if (!page_map.bfind (&map, &i))
     {
       if (!resize (pages.len + 1))
 	return nullptr;
 
-      pages[map.index].init ();
+      pages[map.index].init0 ();
       memmove (&page_map[i + 1], &page_map[i], (page_map.len - 1 - i) * sizeof (page_map[0]));
       page_map[i] = map;
     }
     return &pages[page_map[i].index];
   }
-  page_t *page_for (hb_codepoint_t g)
+  inline page_t *page_for (hb_codepoint_t g)
   {
     page_map_t key = {get_major (g)};
     const page_map_t *found = page_map.bsearch (&key);
     if (found)
       return &pages[found->index];
     return nullptr;
   }
-  const page_t *page_for (hb_codepoint_t g) const
+  inline const page_t *page_for (hb_codepoint_t g) const
   {
     page_map_t key = {get_major (g)};
     const page_map_t *found = page_map.bsearch (&key);
     if (found)
       return &pages[found->index];
     return nullptr;
   }
-  page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
-  const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
-  unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
+  inline page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
+  inline const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
+  inline unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
+  inline hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
 };
 
 
 #endif /* HB_SET_PRIVATE_HH */
--- a/gfx/harfbuzz/src/hb-string-array.hh
+++ b/gfx/harfbuzz/src/hb-string-array.hh
@@ -43,17 +43,17 @@ static const union HB_STRING_ARRAY_TYPE_
 /* I like to avoid storing the nul-termination byte since we don't need it,
  * but C++ does not allow that.
  * https://stackoverflow.com/questions/28433862/why-initializer-string-for-array-of-chars-is-too-long-compiles-fine-in-c-not
  */
 #define _S(s) char HB_PASTE (str, __LINE__)[sizeof (s)];
 #include HB_STRING_ARRAY_LIST
 #undef _S
   } st;
-  char str[0];
+  char str[VAR];
 }
 HB_STRING_ARRAY_POOL_NAME =
 {
   {
 #define _S(s) s,
 #include HB_STRING_ARRAY_LIST
 #undef _S
   }
--- a/gfx/harfbuzz/src/hb-unicode-private.hh
+++ b/gfx/harfbuzz/src/hb-unicode-private.hh
@@ -132,17 +132,17 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIM
   }
 
   /* Default_Ignorable codepoints:
    *
    * Note: While U+115F, U+1160, U+3164 and U+FFA0 are Default_Ignorable,
    * we do NOT want to hide them, as the way Uniscribe has implemented them
    * is with regular spacing glyphs, and that's the way fonts are made to work.
    * As such, we make exceptions for those four.
-   * Also ignoring U+1BCA0..1BCA3. https://github.com/behdad/harfbuzz/issues/503
+   * Also ignoring U+1BCA0..1BCA3. https://github.com/harfbuzz/harfbuzz/issues/503
    *
    * Unicode 7.0:
    * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
    * 00AD          # Cf       SOFT HYPHEN
    * 034F          # Mn       COMBINING GRAPHEME JOINER
    * 061C          # Cf       ARABIC LETTER MARK
    * 115F..1160    # Lo   [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
    * 17B4..17B5    # Mn   [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
--- a/gfx/harfbuzz/src/hb-version.h
+++ b/gfx/harfbuzz/src/hb-version.h
@@ -33,19 +33,19 @@
 
 #include "hb-common.h"
 
 HB_BEGIN_DECLS
 
 
 #define HB_VERSION_MAJOR 1
 #define HB_VERSION_MINOR 7
-#define HB_VERSION_MICRO 1
+#define HB_VERSION_MICRO 2
 
-#define HB_VERSION_STRING "1.7.1"
+#define HB_VERSION_STRING "1.7.2"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
 	((major)*10000+(minor)*100+(micro) <= \
 	 HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
 
 
 HB_EXTERN void
 hb_version (unsigned int *major,
--- a/gfx/harfbuzz/src/main.cc
+++ b/gfx/harfbuzz/src/main.cc
@@ -101,18 +101,18 @@ main (int argc, char **argv)
       const OpenTypeTable &table = font.get_table (n_table);
       printf ("  Table %2d of %2d: %.4s (0x%08x+0x%08x)\n", n_table, num_tables,
 	      (const char *)table.tag,
 	      (unsigned int) table.offset,
 	      (unsigned int) table.length);
 
       switch (table.tag) {
 
-      case GSUBGPOS::GSUBTag:
-      case GSUBGPOS::GPOSTag:
+      case HB_OT_TAG_GSUB:
+      case HB_OT_TAG_GPOS:
 	{
 
 	const GSUBGPOS &g = *CastP<GSUBGPOS> (font_data + table.offset);
 
 	int num_scripts = g.get_script_count ();
 	printf ("    %d script(s) found in table\n", num_scripts);
 	for (int n_script = 0; n_script < num_scripts; n_script++) {
 	  const Script &script = g.get_script (n_script);
--- a/gfx/harfbuzz/src/sample.py
+++ b/gfx/harfbuzz/src/sample.py
@@ -40,17 +40,17 @@ class Debugger(object):
 		return True
 debugger = Debugger()
 hb.buffer_set_message_func (buf, debugger.message, 1, 0)
 
 ##
 ## Add text to buffer
 ##
 #
-# See https://github.com/behdad/harfbuzz/pull/271
+# See https://github.com/harfbuzz/harfbuzz/pull/271
 #
 if False:
 	# If you do not care about cluster values reflecting Python
 	# string indices, then this is quickest way to add text to
 	# buffer:
 	hb.buffer_add_utf8 (buf, text.encode('utf-8'), 0, -1)
 	# Otherwise, then following handles both narrow and wide
 	# Python builds: