Bug 1560439 - Update HarfBuzz to 2.5.3. r=jfkthame
authorRyan VanderMeulen <ryanvm@gmail.com>
Sat, 29 Jun 2019 17:29:36 +0000
changeset 480696 4f4de7a970353de0c86ee8cf7470ea00feb0cec9
parent 480695 a120e7b0d3058a947f39618faa2d40ab2863b4a8
child 480697 4ec7371e5a41eb4a6a54a5e1174fa228d912a968
push id36218
push userdvarga@mozilla.com
push dateSat, 29 Jun 2019 21:30:26 +0000
treeherdermozilla-central@4f4de7a97035 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1560439
milestone69.0a1
first release with
nightly linux32
4f4de7a97035 / 69.0a1 / 20190629213026 / files
nightly linux64
4f4de7a97035 / 69.0a1 / 20190629213026 / files
nightly mac
4f4de7a97035 / 69.0a1 / 20190629213026 / files
nightly win32
4f4de7a97035 / 69.0a1 / 20190629213026 / files
nightly win64
4f4de7a97035 / 69.0a1 / 20190629213026 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1560439 - Update HarfBuzz to 2.5.3. r=jfkthame Differential Revision: https://phabricator.services.mozilla.com/D36282
gfx/harfbuzz/Makefile.am
gfx/harfbuzz/NEWS
gfx/harfbuzz/README-mozilla
gfx/harfbuzz/README.md
gfx/harfbuzz/configure.ac
gfx/harfbuzz/src/Makefile.am
gfx/harfbuzz/src/Makefile.sources
gfx/harfbuzz/src/gen-ucd-table.py
gfx/harfbuzz/src/hb-aat-layout.cc
gfx/harfbuzz/src/hb-aat-layout.hh
gfx/harfbuzz/src/hb-aat-map.cc
gfx/harfbuzz/src/hb-algs.hh
gfx/harfbuzz/src/hb-array.hh
gfx/harfbuzz/src/hb-atomic.hh
gfx/harfbuzz/src/hb-bimap.hh
gfx/harfbuzz/src/hb-blob.cc
gfx/harfbuzz/src/hb-buffer-serialize.cc
gfx/harfbuzz/src/hb-buffer.cc
gfx/harfbuzz/src/hb-buffer.hh
gfx/harfbuzz/src/hb-cff-interp-cs-common.hh
gfx/harfbuzz/src/hb-cff-interp-dict-common.hh
gfx/harfbuzz/src/hb-common.cc
gfx/harfbuzz/src/hb-config.hh
gfx/harfbuzz/src/hb-coretext.cc
gfx/harfbuzz/src/hb-deprecated.h
gfx/harfbuzz/src/hb-directwrite.cc
gfx/harfbuzz/src/hb-face.cc
gfx/harfbuzz/src/hb-fallback-shape.cc
gfx/harfbuzz/src/hb-font.cc
gfx/harfbuzz/src/hb-font.h
gfx/harfbuzz/src/hb-font.hh
gfx/harfbuzz/src/hb-ft.cc
gfx/harfbuzz/src/hb-glib.cc
gfx/harfbuzz/src/hb-gobject-enums.cc.tmpl
gfx/harfbuzz/src/hb-gobject-structs.cc
gfx/harfbuzz/src/hb-graphite2.cc
gfx/harfbuzz/src/hb-icu.cc
gfx/harfbuzz/src/hb-mutex.hh
gfx/harfbuzz/src/hb-null.hh
gfx/harfbuzz/src/hb-open-type.hh
gfx/harfbuzz/src/hb-ot-cff-common.hh
gfx/harfbuzz/src/hb-ot-cff1-table.cc
gfx/harfbuzz/src/hb-ot-cff1-table.hh
gfx/harfbuzz/src/hb-ot-cff2-table.cc
gfx/harfbuzz/src/hb-ot-cff2-table.hh
gfx/harfbuzz/src/hb-ot-cmap-table.hh
gfx/harfbuzz/src/hb-ot-color.cc
gfx/harfbuzz/src/hb-ot-face-table-list.hh
gfx/harfbuzz/src/hb-ot-face.cc
gfx/harfbuzz/src/hb-ot-face.hh
gfx/harfbuzz/src/hb-ot-font.cc
gfx/harfbuzz/src/hb-ot-glyf-table.hh
gfx/harfbuzz/src/hb-ot-hmtx-table.hh
gfx/harfbuzz/src/hb-ot-layout-common.hh
gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh
gfx/harfbuzz/src/hb-ot-layout.cc
gfx/harfbuzz/src/hb-ot-math.cc
gfx/harfbuzz/src/hb-ot-maxp-table.hh
gfx/harfbuzz/src/hb-ot-name-table.hh
gfx/harfbuzz/src/hb-ot-name.cc
gfx/harfbuzz/src/hb-ot-os2-table.hh
gfx/harfbuzz/src/hb-ot-post-table.hh
gfx/harfbuzz/src/hb-ot-shape-complex-indic.hh
gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.rl
gfx/harfbuzz/src/hb-ot-shape.cc
gfx/harfbuzz/src/hb-ot-shape.hh
gfx/harfbuzz/src/hb-ot-stat-table.hh
gfx/harfbuzz/src/hb-ot-tag.cc
gfx/harfbuzz/src/hb-ot-var-mvar-table.hh
gfx/harfbuzz/src/hb-ot-var.cc
gfx/harfbuzz/src/hb-ot-vorg-table.hh
gfx/harfbuzz/src/hb-serialize.hh
gfx/harfbuzz/src/hb-shaper-list.hh
gfx/harfbuzz/src/hb-static.cc
gfx/harfbuzz/src/hb-subset-cff-common.cc
gfx/harfbuzz/src/hb-subset-cff-common.hh
gfx/harfbuzz/src/hb-subset-cff1.cc
gfx/harfbuzz/src/hb-subset-cff2.cc
gfx/harfbuzz/src/hb-subset-plan.cc
gfx/harfbuzz/src/hb-subset.cc
gfx/harfbuzz/src/hb-ucd-table.hh
gfx/harfbuzz/src/hb-ucd.cc
gfx/harfbuzz/src/hb-unicode.hh
gfx/harfbuzz/src/hb-uniscribe.cc
gfx/harfbuzz/src/hb-version.h
gfx/harfbuzz/src/hb.hh
gfx/harfbuzz/src/main.cc
gfx/harfbuzz/src/moz.build
gfx/harfbuzz/src/test-buffer-serialize.cc
gfx/harfbuzz/src/test-gpos-size-params.cc
gfx/harfbuzz/src/test-gsub-would-substitute.cc
gfx/harfbuzz/src/test-ot-color.cc
gfx/harfbuzz/src/test-ot-name.cc
gfx/harfbuzz/src/test.cc
gfx/harfbuzz/update.sh
--- a/gfx/harfbuzz/Makefile.am
+++ b/gfx/harfbuzz/Makefile.am
@@ -8,16 +8,17 @@ SUBDIRS = src util test docs
 
 EXTRA_DIST = \
 	autogen.sh \
 	harfbuzz.doap \
 	README.md \
 	README.mingw.md \
 	README.python.md \
 	BUILD.md \
+	CONFIG.md \
 	RELEASING.md \
 	TESTING.md \
 	CMakeLists.txt \
 	replace-enum-strings.cmake \
 	mingw-configure.sh \
 	mingw-ldd.py \
 	mingw32.sh \
 	mingw64.sh \
--- a/gfx/harfbuzz/NEWS
+++ b/gfx/harfbuzz/NEWS
@@ -1,8 +1,27 @@
+Overview of changes leading to 2.5.3
+Wednesday, June 26, 2019
+====================================
+- Fix UCD script data for Unicode 10+ scripts.  This was broken since 2.5.0.
+- More optimizations for HB_TINY.
+
+
+Overview of changes leading to 2.5.2
+Thursday, June 20, 2019
+====================================
+- More hb-config.hh facilities to shrink library size, namely when built as
+  HB_TINY.
+- New documentation of custom configurations in CONFIG.md.
+- Fix build on gcc 4.8.  That's supported again.
+- Universal Shaping Engine improvements thanks to David Corbett.
+- API Changes: Undeprecate some horizontal-kerning API and re-enable in hb-ft,
+  such that Type1 fonts will continue kerning.
+
+
 Overview of changes leading to 2.5.1
 Friday, May 31, 2019
 ====================================
 - Fix build with various versions of Visual Studio.
 - Improved documentation, thanks to Nathan Willis.
 - Bugfix in subsetting glyf table.
 - Improved scripts for cross-compiling for Windows using mingw.
 - Rename HB_MATH_GLYPH_PART_FLAG_EXTENDER to HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER.
--- a/gfx/harfbuzz/README-mozilla
+++ b/gfx/harfbuzz/README-mozilla
@@ -1,12 +1,12 @@
 This directory contains the HarfBuzz source from the upstream repo:
 https://github.com/harfbuzz/harfbuzz
 
-Current version: 2.5.1 [commit 93c455567fe3d92a7efe65bf0e9ac2af794e2c4f]
+Current version: 2.5.3 [commit b14e413fae8f14b75c5956e9b38e413c878ded0c]
 
 UPDATING:
 
 Our in-tree copy of HarfBuzz does not depend on any generated files from the
 upstream build system. Therefore, it should be sufficient to simply overwrite
 the in-tree files one the updated ones from upstream to perform updates.
 
 To simplify this, the in-tree copy can be updated by running
--- a/gfx/harfbuzz/README.md
+++ b/gfx/harfbuzz/README.md
@@ -12,11 +12,13 @@ This is HarfBuzz, a text shaping library
 For bug reports, mailing list, and other information please visit:
 
   http://harfbuzz.org/
 
 For license information, see [COPYING](COPYING).
 
 For build information, see [BUILD.md](BUILD.md).
 
+For custom configurations, see [CONFIG.md](CONFIG.md).
+
 For test execution, see [TESTING.md](TESTING.md).
 
 Documentation: https://harfbuzz.github.io
--- a/gfx/harfbuzz/configure.ac
+++ b/gfx/harfbuzz/configure.ac
@@ -1,11 +1,11 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [2.5.1],
+        [2.5.3],
         [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])
 
@@ -72,23 +72,17 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl]
 	if test "x$enable_gtk_doc" = xyes; then
 		have_gtk_doc=true
 	fi
 ], [
 	AM_CONDITIONAL([ENABLE_GTK_DOC], false)
 ])
 
 # Functions and headers
-AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l posix_memalign)
-
-save_libs="$LIBS"
-LIBS="$LIBS -lm"
-AC_CHECK_FUNCS([round], ,[AC_CHECK_DECLS([round], , ,[#include <math.h>])])
-LIBS="$save_libs"
-
+AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l)
 AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h stdbool.h)
 
 # Compiler flags
 AC_CANONICAL_HOST
 AC_CHECK_ALIGNOF([struct{char;}])
 if test "x$GCC" = "xyes"; then
 
 	# Make symbols link locally
@@ -137,24 +131,16 @@ have_pthread=false
 AX_PTHREAD([have_pthread=true])
 if $have_pthread; then
 	AC_DEFINE(HAVE_PTHREAD, 1, [Have POSIX threads])
 fi
 AM_CONDITIONAL(HAVE_PTHREAD, $have_pthread)
 
 dnl ==========================================================================
 
-have_fallback=true
-if $have_fallback; then
-	AC_DEFINE(HAVE_FALLBACK, 1, [Have simple TrueType Layout backend])
-fi
-AM_CONDITIONAL(HAVE_FALLBACK, $have_fallback)
-
-dnl ===========================================================================
-
 AC_ARG_WITH(glib,
 	[AS_HELP_STRING([--with-glib=@<:@yes/no/auto@:>@],
 			[Use glib @<:@default=auto@:>@])],,
 	[with_glib=auto])
 have_glib=false
 GLIB_DEPS="glib-2.0 >= 2.19.1"
 AC_SUBST(GLIB_DEPS)
 if test "x$with_glib" = "xyes" -o "x$with_glib" = "xauto"; then
--- a/gfx/harfbuzz/src/Makefile.am
+++ b/gfx/harfbuzz/src/Makefile.am
@@ -23,20 +23,16 @@ include Makefile.sources
 HBCFLAGS =
 HBLIBS =
 HBNONPCLIBS =
 HBDEPS =
 HBSOURCES =  $(HB_BASE_sources)
 HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources)
 HBHEADERS = $(HB_BASE_headers)
 
-if HAVE_FALLBACK
-HBSOURCES += $(HB_FALLBACK_sources)
-endif
-
 if HAVE_PTHREAD
 HBCFLAGS += $(PTHREAD_CFLAGS)
 HBNONPCLIBS += $(PTHREAD_LIBS)
 endif
 
 if HAVE_GLIB
 HBCFLAGS += $(GLIB_CFLAGS)
 HBLIBS   += $(GLIB_LIBS)
@@ -423,16 +419,17 @@ HarfBuzz_0_0_gir_CFLAGS = \
 	-DHB_H \
 	-DHB_H_IN \
 	-DHB_OT_H \
 	-DHB_OT_H_IN \
 	-DHB_AAT_H \
 	-DHB_AAT_H_IN \
 	-DHB_GOBJECT_H \
 	-DHB_GOBJECT_H_IN \
+	-DHAVE_GOBJECT \
 	-DHB_EXTERN= \
 	$(NULL)
 HarfBuzz_0_0_gir_LIBS = \
 	libharfbuzz.la \
 	libharfbuzz-gobject.la \
 	$(NULL)
 HarfBuzz_0_0_gir_FILES = \
 	$(HBHEADERS) \
--- a/gfx/harfbuzz/src/Makefile.sources
+++ b/gfx/harfbuzz/src/Makefile.sources
@@ -31,23 +31,25 @@ HB_BASE_sources = \
 	hb-cff1-interp-cs.hh \
 	hb-cff2-interp-cs.hh \
 	hb-common.cc \
 	hb-config.hh \
 	hb-debug.hh \
 	hb-dispatch.hh \
 	hb-face.cc \
 	hb-face.hh \
+	hb-fallback-shape.cc \
 	hb-font.cc \
 	hb-font.hh \
 	hb-iter.hh \
 	hb-kern.hh \
 	hb-machinery.hh \
 	hb-map.cc \
 	hb-map.hh \
+	hb-bimap.hh \
 	hb-meta.hh \
 	hb-mutex.hh \
 	hb-null.hh \
 	hb-object.hh \
 	hb-open-file.hh \
 	hb-open-type.hh \
 	hb-ot-cff-common.hh \
 	hb-ot-cff1-table.cc \
@@ -58,16 +60,17 @@ HB_BASE_sources = \
 	hb-ot-color-cbdt-table.hh \
 	hb-ot-color-colr-table.hh \
 	hb-ot-color-cpal-table.hh \
 	hb-ot-color-sbix-table.hh \
 	hb-ot-color-svg-table.hh \
 	hb-ot-color.cc \
 	hb-ot-face.cc \
 	hb-ot-face.hh \
+	hb-ot-face-table-list.hh \
 	hb-ot-font.cc \
 	hb-ot-gasp-table.hh \
 	hb-ot-glyf-table.hh \
 	hb-ot-hdmx-table.hh \
 	hb-ot-head-table.hh \
 	hb-ot-hhea-table.hh \
 	hb-ot-hmtx-table.hh \
 	hb-ot-kern-table.hh \
@@ -195,20 +198,16 @@ HB_BASE_headers = \
 	hb-set.h \
 	hb-shape-plan.h \
 	hb-shape.h \
 	hb-unicode.h \
 	hb-version.h \
 	hb.h \
 	$(NULL)
 
-HB_FALLBACK_sources = \
-	hb-fallback-shape.cc	\
-	$(NULL)
-
 # Optional Sources and Headers with external deps
 
 HB_FT_sources = hb-ft.cc
 HB_FT_headers = hb-ft.h
 
 HB_GLIB_sources = hb-glib.cc
 HB_GLIB_headers = hb-glib.h
 
--- a/gfx/harfbuzz/src/gen-ucd-table.py
+++ b/gfx/harfbuzz/src/gen-ucd-table.py
@@ -1,123 +1,162 @@
 #!/usr/bin/env python
 
 from __future__ import print_function, division, absolute_import
 
 import io, os.path, sys, re
+import logging
+logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
 
 if len (sys.argv) != 2:
-	print("usage: ./gen-ucd-table ucd.nonunihan.grouped.xml", file=sys.stderr)
+	print("usage: ./gen-ucd-table ucd.nounihan.grouped.xml", file=sys.stderr)
 	sys.exit(1)
 
-
 # https://github.com/harfbuzz/packtab
 import packTab
 import packTab.ucdxml
 
+logging.info('Loading UCDXML...')
 ucdxml = packTab.ucdxml.load_ucdxml(sys.argv[1])
 ucd = packTab.ucdxml.ucdxml_get_repertoire(ucdxml)
 
+logging.info('Preparing data tables...')
 
 gc = [u['gc'] for u in ucd]
 ccc = [int(u['ccc']) for u in ucd]
 bmg = [int(v, 16) - int(u) if v else 0 for u,v in enumerate(u['bmg'] for u in ucd)]
 #gc_ccc_non0 = set((cat,klass) for cat,klass in zip(gc,ccc) if klass)
 #gc_bmg_non0 = set((cat,mirr) for cat,mirr in zip(gc, bmg) if mirr)
 
 sc = [u['sc'] for u in ucd]
 
 dm = {i:tuple(int(v, 16) for v in u['dm'].split()) for i,u in enumerate(ucd)
       if u['dm'] != '#' and u['dt'] == 'can' and not (0xAC00 <= i < 0xAC00+11172)}
 ce = {i for i,u in enumerate(ucd) if u['Comp_Ex'] == 'Y'}
 
 assert not any(v for v in dm.values() if len(v) not in (1,2))
 dm1 = sorted(set(v for v in dm.values() if len(v) == 1))
-dm1_array = ['0x%04Xu' % v for v in dm1]
+assert all((v[0] >> 16) in (0,2) for v in dm1)
+dm1_p0_array = ['0x%04Xu' % (v[0] & 0xFFFF) for v in dm1 if (v[0] >> 16) == 0]
+dm1_p2_array = ['0x%04Xu' % (v[0] & 0xFFFF) for v in dm1 if (v[0] >> 16) == 2]
 dm1_order = {v:i+1 for i,v in enumerate(dm1)}
-dm2 = sorted((v, i) for i,v in dm.items() if len(v) == 2)
-dm2 = [("HB_CODEPOINT_ENCODE3 (0x%04Xu, 0x%04Xu, 0x%04Xu)" %
-        (v+(i if i not in ce and not ccc[i] else 0,)), v)
-       for v,i in dm2]
-dm2_array = [s for s,v in dm2]
-l = 1 + len(dm1_array)
+
+dm2 = sorted((v+(i if i not in ce and not ccc[i] else 0,), v)
+             for i,v in dm.items() if len(v) == 2)
+
+filt = lambda v: ((v[0] & 0xFFFFF800) == 0x0000 and
+                  (v[1] & 0xFFFFFF80) == 0x0300 and
+                  (v[2] & 0xFFF0C000) == 0x0000)
+dm2_u32_array = [v for v in dm2 if filt(v[0])]
+dm2_u64_array = [v for v in dm2 if not filt(v[0])]
+assert dm2_u32_array + dm2_u64_array == dm2
+dm2_u32_array = ["HB_CODEPOINT_ENCODE3_11_7_14 (0x%04Xu, 0x%04Xu, 0x%04Xu)" % v[0] for v in dm2_u32_array]
+dm2_u64_array = ["HB_CODEPOINT_ENCODE3 (0x%04Xu, 0x%04Xu, 0x%04Xu)" % v[0] for v in dm2_u64_array]
+
+l = 1 + len(dm1_p0_array) + len(dm1_p2_array)
 dm2_order = {v[1]:i+l for i,v in enumerate(dm2)}
+
 dm_order = {None: 0}
 dm_order.update(dm1_order)
 dm_order.update(dm2_order)
 
-gc_order = packTab.AutoMapping()
-for _ in ('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu',
-          'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf',
-          'Pi', 'Po', 'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs',):
-    gc_order[_]
+gc_order = dict()
+for i,v in enumerate(('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu',
+                      'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf',
+                      'Pi', 'Po', 'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs',)):
+    gc_order[i] = v
+    gc_order[v] = i
 
-sc_order = packTab.AutoMapping()
+sc_order = dict()
 sc_array = []
-sc_re = re.compile(" (HB_SCRIPT_[_A-Z]*).*HB_TAG [(]'(.)','(.)','(.)','(.)'[)]")
+sc_re = re.compile(r"\b(HB_SCRIPT_[_A-Z]*).*HB_TAG [(]'(.)','(.)','(.)','(.)'[)]")
 for line in open('hb-common.h'):
     m = sc_re.search (line)
     if not m: continue
     name = m.group(1)
     tag = ''.join(m.group(i) for i in range(2, 6))
-    i = sc_order[tag]
-    assert i == len(sc_array)
+    i = len(sc_array)
+    sc_order[tag] = i
+    sc_order[i] = tag
     sc_array.append(name)
 
-# TODO Currently if gc_order or sc_order do not capture all values, we get in
-# trouble because they silently add new values.  We should be able to "freeze"
-# them, or just do the mapping ourselves.
-
 DEFAULT = 1
 COMPACT = 3
+SLOPPY  = 5
 
 
+logging.info('Generating output...')
 print("/* == Start of generated table == */")
 print("/*")
 print(" * The following table is generated by running:")
 print(" *")
-print(" *   ./gen-ucd-table.py ucd.nonunihan.grouped.xml")
+print(" *   ./gen-ucd-table.py ucd.nounihan.grouped.xml")
 print(" *")
 print(" * on file with this description:", ucdxml.description)
 print(" */")
 print()
 print("#ifndef HB_UCD_TABLE_HH")
 print("#define HB_UCD_TABLE_HH")
 print()
-
-print()
 print('#include "hb.hh"')
 print()
 
 code = packTab.Code('_hb_ucd')
 sc_array, _ = code.addArray('hb_script_t', 'sc_map', sc_array)
-dm1_array, _ = code.addArray('hb_codepoint_t', 'dm1_map', dm1_array)
-dm2_array, _ = code.addArray('uint64_t', 'dm2_map', dm2_array)
+dm1_p0_array, _ = code.addArray('uint16_t', 'dm1_p0_map', dm1_p0_array)
+dm1_p2_array, _ = code.addArray('uint16_t', 'dm1_p2_map', dm1_p2_array)
+dm2_u32_array, _ = code.addArray('uint32_t', 'dm2_u32_map', dm2_u32_array)
+dm2_u64_array, _ = code.addArray('uint64_t', 'dm2_u64_map', dm2_u64_array)
 code.print_c(linkage='static inline')
 
-for compression in (DEFAULT, COMPACT):
+datasets = [
+    ('gc', gc, 'Cn', gc_order),
+    ('ccc', ccc, 0, None),
+    ('bmg', bmg, 0, None),
+    ('sc', sc, 'Zzzz', sc_order),
+    ('dm', dm, None, dm_order),
+]
+
+for compression in (DEFAULT, COMPACT, SLOPPY):
+    logging.info('  Compression=%d:' % compression)
     print()
     if compression == DEFAULT:
         print('#ifndef HB_OPTIMIZE_SIZE')
+    elif compression == COMPACT:
+        print('#elif !defined(HB_NO_UCD_UNASSIGNED)')
     else:
         print('#else')
     print()
 
+    if compression == SLOPPY:
+        for i in range(len(gc)):
+            if (i % 128) and gc[i] == 'Cn':
+                gc[i] = gc[i - 1]
+        for i in range(len(gc) - 2, -1, -1):
+            if ((i + 1) % 128) and gc[i] == 'Cn':
+                gc[i] = gc[i + 1]
+        for i in range(len(sc)):
+            if (i % 128) and sc[i] == 'Zzzz':
+                sc[i] = sc[i - 1]
+        for i in range(len(sc) - 2, -1, -1):
+            if ((i + 1) % 128) and sc[i] == 'Zzzz':
+                sc[i] = sc[i + 1]
+
+
     code = packTab.Code('_hb_ucd')
 
-    packTab.pack_table(gc, 'Cn', mapping=gc_order, compression=compression).genCode(code, 'gc')
-    packTab.pack_table(ccc, 0, compression=compression).genCode(code, 'ccc')
-    packTab.pack_table(bmg, 0, compression=compression).genCode(code, 'bmg')
-    packTab.pack_table(sc, 'Zzzz', mapping=sc_order, compression=compression).genCode(code, 'sc')
-    packTab.pack_table(dm, None, mapping=dm_order, compression=compression).genCode(code, 'dm')
+    for name,data,default,mapping in datasets:
+        sol = packTab.pack_table(data, default, mapping=mapping, compression=compression)
+        logging.info('      Dataset=%-8s FullCost=%d' % (name, sol.fullCost))
+        sol.genCode(code, name)
 
     code.print_c(linkage='static inline')
 
+    print()
 
-    if compression != DEFAULT:
-        print()
-        print('#endif')
-    print()
+print('#endif')
+print()
 
 print()
 print("#endif /* HB_UCD_TABLE_HH */")
 print()
 print("/* == End of generated table == */")
+logging.info('Done.')
--- a/gfx/harfbuzz/src/hb-aat-layout.cc
+++ b/gfx/harfbuzz/src/hb-aat-layout.cc
@@ -20,31 +20,69 @@
  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-open-type.hh"
+#include "hb.hh"
 
-#include "hb-ot-face.hh"
 #include "hb-aat-layout.hh"
 #include "hb-aat-fdsc-table.hh" // Just so we compile it; unused otherwise.
 #include "hb-aat-layout-ankr-table.hh"
 #include "hb-aat-layout-bsln-table.hh" // Just so we compile it; unused otherwise.
 #include "hb-aat-layout-feat-table.hh"
 #include "hb-aat-layout-just-table.hh" // Just so we compile it; unused otherwise.
 #include "hb-aat-layout-kerx-table.hh"
 #include "hb-aat-layout-morx-table.hh"
 #include "hb-aat-layout-trak-table.hh"
 #include "hb-aat-ltag-table.hh"
 
 
+/*
+ * hb_aat_apply_context_t
+ */
+
+/* Note: This context is used for kerning, even without AAT, hence the condition. */
+#if !defined(HB_NO_AAT) || !defined(HB_NO_OT_KERN)
+
+AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
+						     hb_font_t *font_,
+						     hb_buffer_t *buffer_,
+						     hb_blob_t *blob) :
+						       plan (plan_),
+						       font (font_),
+						       face (font->face),
+						       buffer (buffer_),
+						       sanitizer (),
+						       ankr_table (&Null(AAT::ankr)),
+						       lookup_index (0),
+						       debug_depth (0)
+{
+  sanitizer.init (blob);
+  sanitizer.set_num_glyphs (face->get_num_glyphs ());
+  sanitizer.start_processing ();
+  sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX);
+}
+
+AAT::hb_aat_apply_context_t::~hb_aat_apply_context_t ()
+{ sanitizer.end_processing (); }
+
+void
+AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_)
+{ ankr_table = ankr_table_; }
+
+#endif
+
+
+#ifndef HB_NO_AAT
+
+
 /**
  * SECTION:hb-aat-layout
  * @title: hb-aat-layout
  * @short_description: Apple Advanced Typography Layout
  * @include: hb-aat.h
  *
  * Functions for querying OpenType Layout features in the font face.
  **/
@@ -130,74 +168,33 @@ static const hb_aat_feature_mapping_t fe
   {HB_TAG ('v','p','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT,          (hb_aat_layout_feature_selector_t) 7},
   {HB_TAG ('v','r','t','2'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION,   HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON,   HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF},
   {HB_TAG ('z','e','r','o'), HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS,      HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON,                HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF},
 };
 
 const hb_aat_feature_mapping_t *
 hb_aat_layout_find_feature_mapping (hb_tag_t tag)
 {
-#ifdef HB_NO_SHAPE_AAT
-  return nullptr;
-#endif
-
-  return (const hb_aat_feature_mapping_t *) bsearch (&tag,
-						     feature_mappings,
-						     ARRAY_LENGTH (feature_mappings),
-						     sizeof (feature_mappings[0]),
-						     hb_aat_feature_mapping_t::cmp);
+  return (const hb_aat_feature_mapping_t *) hb_bsearch (&tag,
+							feature_mappings,
+							ARRAY_LENGTH (feature_mappings),
+							sizeof (feature_mappings[0]),
+							hb_aat_feature_mapping_t::cmp);
 }
 
 
 /*
- * hb_aat_apply_context_t
- */
-
-/* Note: This context is used for kerning, even without AAT. */
-
-AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
-						     hb_font_t *font_,
-						     hb_buffer_t *buffer_,
-						     hb_blob_t *blob) :
-						       plan (plan_),
-						       font (font_),
-						       face (font->face),
-						       buffer (buffer_),
-						       sanitizer (),
-						       ankr_table (&Null(AAT::ankr)),
-						       lookup_index (0),
-						       debug_depth (0)
-{
-  sanitizer.init (blob);
-  sanitizer.set_num_glyphs (face->get_num_glyphs ());
-  sanitizer.start_processing ();
-  sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX);
-}
-
-AAT::hb_aat_apply_context_t::~hb_aat_apply_context_t ()
-{ sanitizer.end_processing (); }
-
-void
-AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_)
-{ ankr_table = ankr_table_; }
-
-
-/*
  * mort/morx/kerx/trak
  */
 
 
 void
 hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
 			   hb_aat_map_t *map)
 {
-#ifdef HB_NO_SHAPE_AAT
-  return;
-#endif
-
   const AAT::morx& morx = *mapper->face->table.morx;
   if (morx.has_data ())
   {
     morx.compile_flags (mapper, map);
     return;
   }
 
   const AAT::mort& mort = *mapper->face->table.mort;
@@ -214,33 +211,25 @@ hb_aat_layout_compile_map (const hb_aat_
  * @face:
  *
  * Returns:
  * Since: 2.3.0
  */
 hb_bool_t
 hb_aat_layout_has_substitution (hb_face_t *face)
 {
-#ifdef HB_NO_SHAPE_AAT
-  return false;
-#endif
-
   return face->table.morx->has_data () ||
 	 face->table.mort->has_data ();
 }
 
 void
 hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
 			  hb_font_t *font,
 			  hb_buffer_t *buffer)
 {
-#ifdef HB_NO_SHAPE_AAT
-  return;
-#endif
-
   hb_blob_t *morx_blob = font->face->table.morx.get_blob ();
   const AAT::morx& morx = *morx_blob->as<AAT::morx> ();
   if (morx.has_data ())
   {
     AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob);
     morx.apply (&c);
     return;
   }
@@ -253,20 +242,16 @@ hb_aat_layout_substitute (const hb_ot_sh
     mort.apply (&c);
     return;
   }
 }
 
 void
 hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer)
 {
-#ifdef HB_NO_SHAPE_AAT
-  return;
-#endif
-
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
   hb_glyph_position_t *pos = buffer->pos;
   for (unsigned int i = 0; i < count; i++)
     if (unlikely (info[i].codepoint == AAT::DELETED_GLYPH))
       pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
 }
 
@@ -274,49 +259,37 @@ static bool
 is_deleted_glyph (const hb_glyph_info_t *info)
 {
   return info->codepoint == AAT::DELETED_GLYPH;
 }
 
 void
 hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
 {
-#ifdef HB_NO_SHAPE_AAT
-  return;
-#endif
-
   hb_ot_layout_delete_glyphs_inplace (buffer, is_deleted_glyph);
 }
 
 /*
  * hb_aat_layout_has_positioning:
  * @face:
  *
  * Returns:
  * Since: 2.3.0
  */
 hb_bool_t
 hb_aat_layout_has_positioning (hb_face_t *face)
 {
-#ifdef HB_NO_SHAPE_AAT
-  return false;
-#endif
-
   return face->table.kerx->has_data ();
 }
 
 void
 hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
 			hb_font_t *font,
 			hb_buffer_t *buffer)
 {
-#ifdef HB_NO_SHAPE_AAT
-  return;
-#endif
-
   hb_blob_t *kerx_blob = font->face->table.kerx.get_blob ();
   const AAT::kerx& kerx = *kerx_blob->as<AAT::kerx> ();
 
   AAT::hb_aat_apply_context_t c (plan, font, buffer, kerx_blob);
   c.set_ankr_table (font->face->table.ankr.get ());
   kerx.apply (&c);
 }
 
@@ -326,32 +299,24 @@ hb_aat_layout_position (const hb_ot_shap
  * @face:
  *
  * Returns:
  * Since: 2.3.0
  */
 hb_bool_t
 hb_aat_layout_has_tracking (hb_face_t *face)
 {
-#ifdef HB_NO_SHAPE_AAT
-  return false;
-#endif
-
   return face->table.trak->has_data ();
 }
 
 void
 hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
 		     hb_font_t *font,
 		     hb_buffer_t *buffer)
 {
-#ifdef HB_NO_SHAPE_AAT
-  return;
-#endif
-
   const AAT::trak& trak = *font->face->table.trak;
 
   AAT::hb_aat_apply_context_t c (plan, font, buffer);
   trak.apply (&c);
 }
 
 /**
  * hb_aat_layout_get_feature_types:
@@ -365,42 +330,32 @@ hb_aat_layout_track (const hb_ot_shape_p
  * Since: 2.2.0
  */
 unsigned int
 hb_aat_layout_get_feature_types (hb_face_t                    *face,
 				 unsigned int                  start_offset,
 				 unsigned int                 *feature_count, /* IN/OUT.  May be NULL. */
 				 hb_aat_layout_feature_type_t *features       /* OUT.     May be NULL. */)
 {
-#ifdef HB_NO_SHAPE_AAT
-  if (feature_count)
-    *feature_count = 0;
-  return 0;
-#endif
-
   return face->table.feat->get_feature_types (start_offset, feature_count, features);
 }
 
 /**
  * hb_aat_layout_feature_type_get_name_id:
  * @face: a face object
  * @feature_type: feature id
  *
  * Return value: Name ID index
  *
  * Since: 2.2.0
  */
 hb_ot_name_id_t
 hb_aat_layout_feature_type_get_name_id (hb_face_t                    *face,
 					hb_aat_layout_feature_type_t  feature_type)
 {
-#ifdef HB_NO_SHAPE_AAT
-  return HB_OT_NAME_ID_INVALID;
-#endif
-
   return face->table.feat->get_feature_name_id (feature_type);
 }
 
 /**
  * hb_aat_layout_feature_type_get_selectors:
  * @face:    a face object
  * @feature_type: feature id
  * @start_offset:    iteration's start offset
@@ -419,16 +374,13 @@ hb_aat_layout_feature_type_get_name_id (
 unsigned int
 hb_aat_layout_feature_type_get_selector_infos (hb_face_t                             *face,
 					       hb_aat_layout_feature_type_t           feature_type,
 					       unsigned int                           start_offset,
 					       unsigned int                          *selector_count, /* IN/OUT.  May be NULL. */
 					       hb_aat_layout_feature_selector_info_t *selectors,      /* OUT.     May be NULL. */
 					       unsigned int                          *default_index   /* OUT.     May be NULL. */)
 {
-#ifdef HB_NO_SHAPE_AAT
-  if (selector_count)
-    *selector_count = 0;
-  return 0;
-#endif
-
   return face->table.feat->get_selector_infos (feature_type, start_offset, selector_count, selectors, default_index);
 }
+
+
+#endif
--- a/gfx/harfbuzz/src/hb-aat-layout.hh
+++ b/gfx/harfbuzz/src/hb-aat-layout.hh
@@ -73,17 +73,9 @@ hb_aat_layout_position (const hb_ot_shap
 			hb_buffer_t *buffer);
 
 HB_INTERNAL void
 hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
 		     hb_font_t *font,
 		     hb_buffer_t *buffer);
 
 
-inline hb_language_t
-_hb_aat_language_get (hb_face_t *face,
-                      unsigned int i)
-{
-  return face->table.ltag->get_language (i);
-}
-
-
 #endif /* HB_AAT_LAYOUT_HH */
--- a/gfx/harfbuzz/src/hb-aat-map.cc
+++ b/gfx/harfbuzz/src/hb-aat-map.cc
@@ -21,28 +21,28 @@
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Red Hat Author(s): Behdad Esfahbod
  * Google Author(s): Behdad Esfahbod
  */
 
+#include "hb.hh"
+
+#ifndef HB_NO_SHAPE_AAT
+
 #include "hb-aat-map.hh"
 
 #include "hb-aat-layout.hh"
 
 
 void hb_aat_map_builder_t::add_feature (hb_tag_t tag,
 					unsigned int value)
 {
-#ifdef HB_NO_SHAPE_AAT
-  return;
-#endif
-
   if (tag == HB_TAG ('a','a','l','t'))
   {
     feature_info_t *info = features.push();
     info->type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES;
     info->setting = (hb_aat_layout_feature_selector_t) value;
     return;
   }
 
@@ -52,25 +52,24 @@ void hb_aat_map_builder_t::add_feature (
   feature_info_t *info = features.push();
   info->type = mapping->aatFeatureType;
   info->setting = value ? mapping->selectorToEnable : mapping->selectorToDisable;
 }
 
 void
 hb_aat_map_builder_t::compile (hb_aat_map_t  &m)
 {
-#ifdef HB_NO_SHAPE_AAT
-  return;
-#endif
-
   /* Sort features and merge duplicates */
   if (features.length)
   {
     features.qsort ();
     unsigned int j = 0;
     for (unsigned int i = 1; i < features.length; i++)
       if (features[i].type != features[j].type)
 	features[++j] = features[i];
     features.shrink (j + 1);
   }
 
   hb_aat_layout_compile_map (this, &m);
 }
+
+
+#endif
--- a/gfx/harfbuzz/src/hb-algs.hh
+++ b/gfx/harfbuzz/src/hb-algs.hh
@@ -1,11 +1,11 @@
 /*
  * Copyright © 2017  Google, Inc.
- * Copyright © 2019  Google, Inc.
+ * Copyright © 2019  Facebook, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
  * Permission is hereby granted, without written agreement and without
  * license or royalty fees, to use, copy, modify, and distribute this
  * software and its documentation for any purpose, provided that the
  * above copyright notice and the following two paragraphs appear in
  * all copies of this software.
@@ -36,16 +36,21 @@
 
 /* Encodes three unsigned integers in one 64-bit number.  If the inputs have more than 21 bits,
  * values will be truncated / overlap, and might not decode exactly. */
 #define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z))
 #define HB_CODEPOINT_DECODE3_1(v) ((hb_codepoint_t) ((v) >> 42))
 #define HB_CODEPOINT_DECODE3_2(v) ((hb_codepoint_t) ((v) >> 21) & 0x1FFFFFu)
 #define HB_CODEPOINT_DECODE3_3(v) ((hb_codepoint_t) (v) & 0x1FFFFFu)
 
+/* Custom encoding used by hb-ucd. */
+#define HB_CODEPOINT_ENCODE3_11_7_14(x,y,z) (((uint32_t) ((x) & 0x07FFu) << 21) | (((uint32_t) (y) & 0x007Fu) << 14) | (uint32_t) ((z) & 0x3FFFu))
+#define HB_CODEPOINT_DECODE3_11_7_14_1(v) ((hb_codepoint_t) ((v) >> 21))
+#define HB_CODEPOINT_DECODE3_11_7_14_2(v) ((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300)
+#define HB_CODEPOINT_DECODE3_11_7_14_3(v) ((hb_codepoint_t) (v) & 0x3FFFu)
 
 struct
 {
   /* Note.  This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
   template <typename T> auto
   operator () (T&& v) const HB_AUTO_RETURN ( hb_forward<T> (v) )
 }
 HB_FUNCOBJ (hb_identity);
@@ -162,29 +167,47 @@ struct hb_partial_t
   private:
   hb_reference_wrapper<Appl> a;
   V v;
 };
 template <unsigned Pos=1, typename Appl, typename V>
 auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN
 (( hb_partial_t<Pos, Appl, V> (a, v) ))
 
-/* The following hacky replacement version is to make Visual Stuiod build:. */ \
+/* The following, HB_PARTIALIZE, macro uses a particular corner-case
+ * of C++11 that is not particularly well-supported by all compilers.
+ * What's happening is that it's using "this" in a trailing return-type
+ * via decltype().  Broken compilers deduce the type of "this" pointer
+ * in that context differently from what it resolves to in the body
+ * of the function.
+ *
+ * One probable cause of this is that at the time of trailing return
+ * type declaration, "this" points to an incomplete type, whereas in
+ * the function body the type is complete.  That doesn't justify the
+ * error in any way, but is probably what's happening.
+ *
+ * In the case of MSVC, we get around this by using C++14 "decltype(auto)"
+ * which deduces the type from the actual return statement.  For gcc 4.8
+ * we use "+this" instead of "this" which produces an rvalue that seems
+ * to be deduced as the same type with this particular compiler, and seem
+ * to be fine as default code path as well.
+ */
+#ifdef _MSC_VER
 /* https://github.com/harfbuzz/harfbuzz/issues/1730 */ \
-#ifdef _MSC_VER
 #define HB_PARTIALIZE(Pos) \
   template <typename _T> \
   decltype(auto) operator () (_T&& _v) const \
   { return hb_partial<Pos> (this, hb_forward<_T> (_v)); } \
   static_assert (true, "")
 #else
+/* https://github.com/harfbuzz/harfbuzz/issues/1724 */
 #define HB_PARTIALIZE(Pos) \
   template <typename _T> \
   auto operator () (_T&& _v) const HB_AUTO_RETURN \
-  (hb_partial<Pos> (this, hb_forward<_T> (_v))) \
+  (hb_partial<Pos> (+this, hb_forward<_T> (_v))) \
   static_assert (true, "")
 #endif
 
 
 struct
 {
   private:
 
@@ -395,17 +418,17 @@ hb_bit_storage (T v)
 
   if (sizeof (T) <= sizeof (unsigned long))
     return sizeof (unsigned long) * 8 - __builtin_clzl (v);
 
   if (sizeof (T) <= sizeof (unsigned long long))
     return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
 #endif
 
-#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
   if (sizeof (T) <= sizeof (unsigned int))
   {
     unsigned long where;
     _BitScanReverse (&where, v);
     return 1 + where;
   }
 # if defined(_WIN64)
   if (sizeof (T) <= 8)
@@ -469,17 +492,17 @@ hb_ctz (T v)
 
   if (sizeof (T) <= sizeof (unsigned long))
     return __builtin_ctzl (v);
 
   if (sizeof (T) <= sizeof (unsigned long long))
     return __builtin_ctzll (v);
 #endif
 
-#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
   if (sizeof (T) <= sizeof (unsigned int))
   {
     unsigned long where;
     _BitScanForward (&where, v);
     return where;
   }
 # if defined(_WIN64)
   if (sizeof (T) <= 8)
@@ -598,171 +621,248 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, 
 {
   return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
 }
 
 
 /*
  * Sort and search.
  */
-
+template <typename ...Ts>
 static inline void *
 hb_bsearch (const void *key, const void *base,
 	    size_t nmemb, size_t size,
-	    int (*compar)(const void *_key, const void *_item))
-{
-  int min = 0, max = (int) nmemb - 1;
-  while (min <= max)
-  {
-    int mid = (min + max) / 2;
-    const void *p = (const void *) (((const char *) base) + (mid * size));
-    int c = compar (key, p);
-    if (c < 0)
-      max = mid - 1;
-    else if (c > 0)
-      min = mid + 1;
-    else
-      return (void *) p;
-  }
-  return nullptr;
-}
-
-static inline void *
-hb_bsearch_r (const void *key, const void *base,
-	      size_t nmemb, size_t size,
-	      int (*compar)(const void *_key, const void *_item, void *_arg),
-	      void *arg)
+	    int (*compar)(const void *_key, const void *_item, Ts... _ds),
+	    Ts... ds)
 {
   int min = 0, max = (int) nmemb - 1;
   while (min <= max)
   {
     int mid = ((unsigned int) min + (unsigned int) max) / 2;
     const void *p = (const void *) (((const char *) base) + (mid * size));
-    int c = compar (key, p, arg);
+    int c = compar (key, p, ds...);
     if (c < 0)
       max = mid - 1;
     else if (c > 0)
       min = mid + 1;
     else
       return (void *) p;
   }
   return nullptr;
 }
 
 
 /* From https://github.com/noporpoise/sort_r
- * With following modifications:
- *
- * 10 November 2018:
- * https://github.com/noporpoise/sort_r/issues/7
- */
+   Feb 5, 2019 (c8c65c1e)
+   Modified to support optional argument using templates */
 
 /* Isaac Turner 29 April 2014 Public Domain */
 
 /*
-
-hb_sort_r function to be exported.
-
+hb_qsort function to be exported.
 Parameters:
   base is the array to be sorted
   nel is the number of elements in the array
   width is the size in bytes of each element of the array
   compar is the comparison function
-  arg is a pointer to be passed to the comparison function
+  arg (optional) is a pointer to be passed to the comparison function
 
-void hb_sort_r(void *base, size_t nel, size_t width,
-               int (*compar)(const void *_a, const void *_b, void *_arg),
-               void *arg);
+void hb_qsort(void *base, size_t nel, size_t width,
+              int (*compar)(const void *_a, const void *_b, [void *_arg]),
+              [void *arg]);
 */
 
+#define SORT_R_SWAP(a,b,tmp) ((tmp) = (a), (a) = (b), (b) = (tmp))
+
+/* swap a and b */
+/* a and b must not be equal! */
+static inline void sort_r_swap(char *__restrict a, char *__restrict b,
+                               size_t w)
+{
+  char tmp, *end = a+w;
+  for(; a < end; a++, b++) { SORT_R_SWAP(*a, *b, tmp); }
+}
 
 /* swap a, b iff a>b */
+/* a and b must not be equal! */
 /* __restrict is same as restrict but better support on old machines */
-static int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w,
-			  int (*compar)(const void *_a, const void *_b,
-					void *_arg),
-			  void *arg)
+template <typename ...Ts>
+static inline int sort_r_cmpswap(char *__restrict a,
+                                 char *__restrict b, size_t w,
+                                 int (*compar)(const void *_a,
+                                               const void *_b,
+                                               Ts... _ds),
+                                 Ts... ds)
 {
-  char tmp, *end = a+w;
-  if(compar(a, b, arg) > 0) {
-    for(; a < end; a++, b++) { tmp = *a; *a = *b; *b = tmp; }
+  if(compar(a, b, ds...) > 0) {
+    sort_r_swap(a, b, w);
     return 1;
   }
   return 0;
 }
 
+/*
+Swap consecutive blocks of bytes of size na and nb starting at memory addr ptr,
+with the smallest swap so that the blocks are in the opposite order. Blocks may
+be internally re-ordered e.g.
+  12345ab  ->   ab34512
+  123abc   ->   abc123
+  12abcde  ->   deabc12
+*/
+static inline void sort_r_swap_blocks(char *ptr, size_t na, size_t nb)
+{
+  if(na > 0 && nb > 0) {
+    if(na > nb) { sort_r_swap(ptr, ptr+na, nb); }
+    else { sort_r_swap(ptr, ptr+nb, na); }
+  }
+}
+
+/* Implement recursive quicksort ourselves */
 /* Note: quicksort is not stable, equivalent values may be swapped */
+template <typename ...Ts>
 static inline void sort_r_simple(void *base, size_t nel, size_t w,
-				 int (*compar)(const void *_a, const void *_b,
-					       void *_arg),
-				 void *arg)
+                                 int (*compar)(const void *_a,
+                                               const void *_b,
+                                               Ts... _ds),
+                                 Ts... ds)
 {
   char *b = (char *)base, *end = b + nel*w;
-  if(nel < 7) {
+
+  /* for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
+  printf("\n"); */
+
+  if(nel < 10) {
     /* Insertion sort for arbitrarily small inputs */
     char *pi, *pj;
     for(pi = b+w; pi < end; pi += w) {
-      for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {}
+      for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,ds...); pj -= w) {}
     }
   }
   else
   {
-    /* nel > 6; Quicksort */
+    /* nel > 9; Quicksort */
 
-    /* Use median of first, middle and last items as pivot */
-    char *x, *y, *xend, ch;
-    char *pl, *pm, *pr;
+    int cmp;
+    char *pl, *ple, *pr, *pre, *pivot;
     char *last = b+w*(nel-1), *tmp;
+
+    /*
+    Use median of second, middle and second-last items as pivot.
+    First and last may have been swapped with pivot and therefore be extreme
+    */
     char *l[3];
-    l[0] = b;
+    l[0] = b + w;
     l[1] = b+w*(nel/2);
-    l[2] = last;
+    l[2] = last - w;
 
-    if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
-    if(compar(l[1],l[2],arg) > 0) {
-      tmp=l[1]; l[1]=l[2]; l[2]=tmp; /* swap(l[1],l[2]) */
-      if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
+    /* printf("pivots: %i, %i, %i\n", *(int*)l[0], *(int*)l[1], *(int*)l[2]); */
+
+    if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
+    if(compar(l[1],l[2],ds...) > 0) {
+      SORT_R_SWAP(l[1], l[2], tmp);
+      if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
     }
 
-    /* swap l[id], l[2] to put pivot as last element */
-    for(x = l[1], y = last, xend = x+w; x<xend; x++, y++) {
-      ch = *x; *x = *y; *y = ch;
-    }
+    /* swap mid value (l[1]), and last element to put pivot as last element */
+    if(l[1] != last) { sort_r_swap(l[1], last, w); }
+
+    /*
+    pl is the next item on the left to be compared to the pivot
+    pr is the last item on the right that was compared to the pivot
+    ple is the left position to put the next item that equals the pivot
+    ple is the last right position where we put an item that equals the pivot
+                                           v- end (beyond the array)
+      EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE.
+      ^- b  ^- ple  ^- pl   ^- pr  ^- pre ^- last (where the pivot is)
+    Pivot comparison key:
+      E = equal, L = less than, u = unknown, G = greater than, E = equal
+    */
+    pivot = last;
+    ple = pl = b;
+    pre = pr = last;
 
-    pl = b;
-    pr = last;
-
+    /*
+    Strategy:
+    Loop into the list from the left and right at the same time to find:
+    - an item on the left that is greater than the pivot
+    - an item on the right that is less than the pivot
+    Once found, they are swapped and the loop continues.
+    Meanwhile items that are equal to the pivot are moved to the edges of the
+    array.
+    */
     while(pl < pr) {
-      pm = pl+((pr-pl+1)>>1);
-      for(; pl < pm; pl += w) {
-        if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
-          pr -= w; /* pivot now at pl */
-          break;
+      /* Move left hand items which are equal to the pivot to the far left.
+         break when we find an item that is greater than the pivot */
+      for(; pl < pr; pl += w) {
+        cmp = compar(pl, pivot, ds...);
+        if(cmp > 0) { break; }
+        else if(cmp == 0) {
+          if(ple < pl) { sort_r_swap(ple, pl, w); }
+          ple += w;
         }
       }
-      pm = pl+((pr-pl)>>1);
-      for(; pm < pr; pr -= w) {
-        if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
-          pl += w; /* pivot now at pr */
+      /* break if last batch of left hand items were equal to pivot */
+      if(pl >= pr) { break; }
+      /* Move right hand items which are equal to the pivot to the far right.
+         break when we find an item that is less than the pivot */
+      for(; pl < pr; ) {
+        pr -= w; /* Move right pointer onto an unprocessed item */
+        cmp = compar(pr, pivot, ds...);
+        if(cmp == 0) {
+          pre -= w;
+          if(pr < pre) { sort_r_swap(pr, pre, w); }
+        }
+        else if(cmp < 0) {
+          if(pl < pr) { sort_r_swap(pl, pr, w); }
+          pl += w;
           break;
         }
       }
     }
 
-    sort_r_simple(b, (pl-b)/w, w, compar, arg);
-    sort_r_simple(pl+w, (end-(pl+w))/w, w, compar, arg);
+    pl = pr; /* pr may have gone below pl */
+
+    /*
+    Now we need to go from: EEELLLGGGGEEEE
+                        to: LLLEEEEEEEGGGG
+    Pivot comparison key:
+      E = equal, L = less than, u = unknown, G = greater than, E = equal
+    */
+    sort_r_swap_blocks(b, ple-b, pl-ple);
+    sort_r_swap_blocks(pr, pre-pr, end-pre);
+
+    /*for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
+    printf("\n");*/
+
+    sort_r_simple(b, (pl-ple)/w, w, compar, ds...);
+    sort_r_simple(end-(pre-pr), (pre-pr)/w, w, compar, ds...);
   }
 }
 
 static inline void
-hb_sort_r (void *base, size_t nel, size_t width,
-	   int (*compar)(const void *_a, const void *_b, void *_arg),
-	   void *arg)
+hb_qsort (void *base, size_t nel, size_t width,
+	  int (*compar)(const void *_a, const void *_b))
 {
-    sort_r_simple(base, nel, width, compar, arg);
+#if defined(__OPTIMIZE_SIZE__) && !defined(HB_USE_INTERNAL_QSORT)
+  qsort (base, nel, width, compar);
+#else
+  sort_r_simple (base, nel, width, compar);
+#endif
+}
+
+static inline void
+hb_qsort (void *base, size_t nel, size_t width,
+	  int (*compar)(const void *_a, const void *_b, void *_arg),
+	  void *arg)
+{
+#ifdef HAVE_GNU_QSORT_R
+  qsort_r (base, nel, width, compar, arg);
+#else
+  sort_r_simple (base, nel, width, compar, arg);
+#endif
 }
 
 
 template <typename T, typename T2, typename T3> static inline void
 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2)
 {
   for (unsigned int i = 1; i < len; i++)
   {
@@ -840,16 +940,22 @@ HB_FUNCOBJ (hb_bitwise_xor);
 struct hb_bitwise_sub
 { HB_PARTIALIZE(2);
   static constexpr bool passthru_left = true;
   static constexpr bool passthru_right = false;
   template <typename T> auto
   operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
 }
 HB_FUNCOBJ (hb_bitwise_sub);
+struct
+{
+  template <typename T> auto
+  operator () (const T &a) const HB_AUTO_RETURN (~a)
+}
+HB_FUNCOBJ (hb_bitwise_neg);
 
 struct
 { HB_PARTIALIZE(2);
   template <typename T, typename T2> auto
   operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a + b)
 }
 HB_FUNCOBJ (hb_add);
 struct
@@ -888,64 +994,49 @@ struct
   operator () (const T &a) const HB_AUTO_RETURN (-a)
 }
 HB_FUNCOBJ (hb_neg);
 
 
 /* Compiler-assisted vectorization. */
 
 /* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
- * using vectorized operations if HB_VECTOR_SIZE is set to **bit** numbers (eg 128).
- * Define that to 0 to disable. */
+ * basically a fixed-size bitset. */
 template <typename elt_t, unsigned int byte_size>
 struct hb_vector_size_t
 {
-  elt_t& operator [] (unsigned int i) { return u.v[i]; }
-  const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
+  elt_t& operator [] (unsigned int i) { return v[i]; }
+  const elt_t& operator [] (unsigned int i) const { return v[i]; }
 
   void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
 
   template <typename Op>
+  hb_vector_size_t process (const Op& op) const
+  {
+    hb_vector_size_t r;
+    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+      r.v[i] = op (v[i]);
+    return r;
+  }
+  template <typename Op>
   hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const
   {
     hb_vector_size_t r;
-#if HB_VECTOR_SIZE
-    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
-      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
-	r.u.vec[i] = op (u.vec[i], o.u.vec[i]);
-    else
-#endif
-      for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
-	r.u.v[i] = op (u.v[i], o.u.v[i]);
+    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+      r.v[i] = op (v[i], o.v[i]);
     return r;
   }
   hb_vector_size_t operator | (const hb_vector_size_t &o) const
   { return process (hb_bitwise_or, o); }
   hb_vector_size_t operator & (const hb_vector_size_t &o) const
   { return process (hb_bitwise_and, o); }
   hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
   { return process (hb_bitwise_xor, o); }
   hb_vector_size_t operator ~ () const
-  {
-    hb_vector_size_t r;
-#if HB_VECTOR_SIZE && 0
-    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
-      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
-	r.u.vec[i] = ~u.vec[i];
-    else
-#endif
-    for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
-      r.u.v[i] = ~u.v[i];
-    return r;
-  }
+  { return process (hb_bitwise_neg); }
 
   private:
-  static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
-  union {
-    elt_t v[byte_size / sizeof (elt_t)];
-#if HB_VECTOR_SIZE
-    hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)];
-#endif
-  } u;
+  static_assert (0 == byte_size % sizeof (elt_t), "");
+  elt_t v[byte_size / sizeof (elt_t)];
 };
 
 
 #endif /* HB_ALGS_HH */
--- a/gfx/harfbuzz/src/hb-array.hh
+++ b/gfx/harfbuzz/src/hb-array.hh
@@ -136,31 +136,31 @@ struct hb_array_t : hb_iter_with_fallbac
       if (!this->arrayZ[i].cmp (x))
 	return &this->arrayZ[i];
     return not_found;
   }
 
   hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*))
   {
     if (likely (length))
-      ::qsort (arrayZ, length, this->item_size, cmp_);
+      hb_qsort (arrayZ, length, this->item_size, cmp_);
     return hb_sorted_array_t<Type> (*this);
   }
   hb_sorted_array_t<Type> qsort ()
   {
     if (likely (length))
-      ::qsort (arrayZ, length, this->item_size, Type::cmp);
+      hb_qsort (arrayZ, length, this->item_size, Type::cmp);
     return hb_sorted_array_t<Type> (*this);
   }
   void qsort (unsigned int start, unsigned int end)
   {
     end = hb_min (end, length);
     assert (start <= end);
     if (likely (start < end))
-      ::qsort (arrayZ + start, end - start, this->item_size, Type::cmp);
+      hb_qsort (arrayZ + start, end - start, this->item_size, Type::cmp);
   }
 
   /*
    * Other methods.
    */
 
   unsigned int get_size () const { return length * this->item_size; }
 
--- a/gfx/harfbuzz/src/hb-atomic.hh
+++ b/gfx/harfbuzz/src/hb-atomic.hh
@@ -102,17 +102,17 @@ static inline bool
 
 
 #elif !defined(HB_NO_MT) && defined(_WIN32)
 
 #include <windows.h>
 
 static inline void _hb_memory_barrier ()
 {
-#ifndef MemoryBarrier
+#if !defined(MemoryBarrier) && !defined(__MINGW32_VERSION)
   /* MinGW has a convoluted history of supporting MemoryBarrier. */
   LONG dummy = 0;
   InterlockedExchange (&dummy, 1);
 #else
   MemoryBarrier ();
 #endif
 }
 #define _hb_memory_barrier()			_hb_memory_barrier ()
new file mode 100644
--- /dev/null
+++ b/gfx/harfbuzz/src/hb-bimap.hh
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2019 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_BIMAP_HH
+#define HB_BIMAP_HH
+
+#include "hb.hh"
+
+/* Bi-directional map */
+struct hb_bimap_t
+{
+  hb_bimap_t () { init (); }
+  ~hb_bimap_t () { fini (); }
+
+  void init ()
+  {
+    forw_map.init ();
+    back_map.init ();
+  }
+
+  void fini ()
+  {
+    forw_map.fini ();
+    back_map.fini ();
+  }
+
+  void reset ()
+  {
+    forw_map.reset ();
+    back_map.reset ();
+  }
+
+  bool in_error () const { return forw_map.in_error () || back_map.in_error (); }
+
+  void set (hb_codepoint_t lhs, hb_codepoint_t rhs)
+  {
+    forw_map.set (lhs, rhs);
+    back_map.set (rhs, lhs);
+  }
+
+  hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); }
+  hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map.get (rhs); }
+
+  hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); }
+  bool has (hb_codepoint_t lhs, hb_codepoint_t *vp = nullptr) const { return forw_map.has (lhs, vp); }
+
+  void del (hb_codepoint_t lhs)
+  {
+    back_map.del (get (lhs));
+    forw_map.del (lhs);
+  }
+
+  void clear ()
+  {
+    forw_map.clear ();
+    back_map.clear ();
+  }
+
+  bool is_empty () const { return get_population () == 0; }
+
+  unsigned int get_population () const { return forw_map.get_population (); }
+
+  protected:
+  hb_map_t  forw_map;
+  hb_map_t  back_map;
+};
+
+/* Inremental bimap: only lhs is given, rhs is incrementally assigned */
+struct hb_inc_bimap_t : hb_bimap_t
+{
+  /* Add a mapping from lhs to rhs with a unique value if lhs is unknown.
+   * Return the rhs value as the result.
+   */
+  hb_codepoint_t add (hb_codepoint_t lhs)
+  {
+    hb_codepoint_t  rhs = forw_map[lhs];
+    if (rhs == HB_MAP_VALUE_INVALID)
+    {
+      rhs = get_population ();
+      set (lhs, rhs);
+    }
+    return rhs;
+  }
+
+  /* Create an identity map. */
+  bool identity (unsigned int size)
+  {
+    clear ();
+    for (hb_codepoint_t i = 0; i < size; i++) set (i, i);
+    return !in_error ();
+  }
+
+  protected:
+  static int cmp_id (const void* a, const void* b)
+  { return (int)*(const hb_codepoint_t *)a - (int)*(const hb_codepoint_t *)b; }
+
+  public:
+  /* Optional: after finished adding all mappings in a random order,
+   * reassign rhs to lhs so that they are in the same order. */
+  void sort ()
+  {
+    hb_codepoint_t  count = get_population ();
+    hb_vector_t <hb_codepoint_t> work;
+    work.resize (count);
+
+    for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
+      work[rhs] = back_map[rhs];
+  
+    work.qsort (cmp_id);
+  
+    for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
+      set (work[rhs], rhs);
+  }
+};
+
+#endif /* HB_BIMAP_HH */
--- a/gfx/harfbuzz/src/hb-blob.cc
+++ b/gfx/harfbuzz/src/hb-blob.cc
@@ -482,16 +482,17 @@ hb_blob_t::try_make_writable ()
 
   return true;
 }
 
 /*
  * Mmap
  */
 
+#ifndef HB_NO_OPEN
 #ifdef HAVE_MMAP
 # include <sys/types.h>
 # include <sys/stat.h>
 # include <fcntl.h>
 #endif
 
 #ifdef _WIN32
 # include <windows.h>
@@ -671,8 +672,9 @@ fail_without_close:
                          (hb_destroy_func_t) free);
 
 fread_fail:
   fclose (fp);
 fread_fail_without_close:
   free (data);
   return hb_blob_get_empty ();
 }
+#endif /* !HB_NO_OPEN */
--- a/gfx/harfbuzz/src/hb-buffer-serialize.cc
+++ b/gfx/harfbuzz/src/hb-buffer-serialize.cc
@@ -19,24 +19,26 @@
  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Google Author(s): Behdad Esfahbod
  */
 
+#include "hb.hh"
+
+#ifndef HB_NO_BUFFER_SERIALIZE
+
 #include "hb-buffer.hh"
 
 
 static const char *serialize_formats[] = {
-#ifndef HB_NO_BUFFER_SERIALIZE
   "text",
   "json",
-#endif
   nullptr
 };
 
 /**
  * hb_buffer_serialize_list_formats:
  *
  * Returns a list of supported buffer serialization formats.
  *
@@ -84,20 +86,18 @@ hb_buffer_serialize_format_from_string (
  *
  * Since: 0.9.7
  **/
 const char *
 hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
 {
   switch ((unsigned) format)
   {
-#ifndef HB_NO_BUFFER_SERIALIZE
     case HB_BUFFER_SERIALIZE_FORMAT_TEXT:	return serialize_formats[0];
     case HB_BUFFER_SERIALIZE_FORMAT_JSON:	return serialize_formats[1];
-#endif
     default:
     case HB_BUFFER_SERIALIZE_FORMAT_INVALID:	return nullptr;
   }
 }
 
 static unsigned int
 _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
 				  unsigned int start,
@@ -343,20 +343,16 @@ hb_buffer_serialize_glyphs (hb_buffer_t 
 
   unsigned int sconsumed;
   if (!buf_consumed)
     buf_consumed = &sconsumed;
   *buf_consumed = 0;
   if (buf_size)
     *buf = '\0';
 
-#ifdef HB_NO_BUFFER_SERIALIZE
-  return 0;
-#endif
-
   assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
 	  buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
 
   if (!buffer->have_positions)
     flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS;
 
   if (unlikely (start == end))
     return 0;
@@ -452,20 +448,16 @@ hb_buffer_deserialize_glyphs (hb_buffer_
 			      hb_font_t *font, /* May be NULL */
 			      hb_buffer_serialize_format_t format)
 {
   const char *end;
   if (!end_ptr)
     end_ptr = &end;
   *end_ptr = buf;
 
-#ifdef HB_NO_BUFFER_SERIALIZE
-  return false;
-#endif
-
   assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
 	  buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
 
   if (buf_len == -1)
     buf_len = strlen (buf);
 
   if (!buf_len)
   {
@@ -491,8 +483,11 @@ hb_buffer_deserialize_glyphs (hb_buffer_
 						 font);
 
     default:
     case HB_BUFFER_SERIALIZE_FORMAT_INVALID:
       return false;
 
   }
 }
+
+
+#endif
--- a/gfx/harfbuzz/src/hb-buffer.cc
+++ b/gfx/harfbuzz/src/hb-buffer.cc
@@ -1988,16 +1988,17 @@ hb_buffer_diff (hb_buffer_t *buffer,
   return result;
 }
 
 
 /*
  * Debugging.
  */
 
+#ifndef HB_NO_BUFFER_MESSAGE
 /**
  * hb_buffer_set_message_func:
  * @buffer: an #hb_buffer_t.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  *
@@ -2017,16 +2018,16 @@ hb_buffer_set_message_func (hb_buffer_t 
     buffer->message_data = user_data;
     buffer->message_destroy = destroy;
   } else {
     buffer->message_func = nullptr;
     buffer->message_data = nullptr;
     buffer->message_destroy = nullptr;
   }
 }
-
 bool
 hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap)
 {
   char buf[100];
-  vsnprintf (buf, sizeof (buf),  fmt, ap);
+  vsnprintf (buf, sizeof (buf), fmt, ap);
   return (bool) this->message_func (this, font, buf, this->message_data);
 }
+#endif
--- a/gfx/harfbuzz/src/hb-buffer.hh
+++ b/gfx/harfbuzz/src/hb-buffer.hh
@@ -119,17 +119,19 @@ struct hb_buffer_t
   /* Text before / after the main buffer contents.
    * Always in Unicode, and ordered outward.
    * Index 0 is for "pre-context", 1 for "post-context". */
   static constexpr unsigned CONTEXT_LENGTH = 5u;
   hb_codepoint_t context[2][CONTEXT_LENGTH];
   unsigned int context_len[2];
 
   /* Debugging API */
+#ifndef HB_NO_BUFFER_MESSAGE
   hb_buffer_message_func_t message_func;
+#endif
   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
@@ -342,26 +344,37 @@ struct hb_buffer_t
 
   typedef long scratch_buffer_t;
   HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);
 
   void clear_context (unsigned int side) { context_len[side] = 0; }
 
   HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
 
-  bool messaging () { return unlikely (message_func); }
+  bool messaging ()
+  {
+#ifdef HB_NO_BUFFER_MESSAGE
+    return false;
+#else
+    return unlikely (message_func);
+#endif
+  }
   bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
   {
+#ifdef HB_NO_BUFFER_MESSAGE
+   return true;
+#else
     if (!messaging ())
       return true;
     va_list ap;
     va_start (ap, fmt);
     bool ret = message_impl (font, fmt, ap);
     va_end (ap);
     return ret;
+#endif
   }
   HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
 
   static void
   set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
   {
     if (inf.cluster != cluster)
     {
--- a/gfx/harfbuzz/src/hb-cff-interp-cs-common.hh
+++ b/gfx/harfbuzz/src/hb-cff-interp-cs-common.hh
@@ -71,18 +71,18 @@ struct biased_subrs_t
     else if (nSubrs < 33900)
       bias = 1131;
     else
       bias = 32768;
   }
 
   void fini () {}
 
-  unsigned int get_count () const { return (subrs == nullptr)? 0: subrs->count; }
-  unsigned int get_bias () const { return bias; }
+  unsigned int get_count () const { return (subrs == nullptr) ? 0 : subrs->count; }
+  unsigned int get_bias () const  { return bias; }
 
   byte_str_t operator [] (unsigned int index) const
   {
     if (unlikely ((subrs == nullptr) || index >= subrs->count))
       return Null(byte_str_t);
     else
       return (*subrs)[index];
   }
--- a/gfx/harfbuzz/src/hb-cff-interp-dict-common.hh
+++ b/gfx/harfbuzz/src/hb-cff-interp-dict-common.hh
@@ -129,38 +129,38 @@ struct dict_opset_t : opset_t<number_t>
 
       switch (d)
       {
 	case RESERVED:
 	  str_ref.set_error ();
 	  return value;
 
 	case END:
-	  value = (double)(neg? -int_part: int_part);
+	  value = (double) (neg ? -int_part : int_part);
 	  if (frac_count > 0)
 	  {
-	    double frac = (frac_part / pow (10.0, (double)frac_count));
+	    double frac = (frac_part / pow (10.0, (double) frac_count));
 	    if (neg) frac = -frac;
 	    value += frac;
 	  }
 	  if (unlikely (exp_overflow))
 	  {
 	    if (value == 0.0)
 	      return value;
 	    if (exp_neg)
-	      return neg? -DBL_MIN: DBL_MIN;
+	      return neg ? -DBL_MIN : DBL_MIN;
 	    else
-	      return neg? -DBL_MAX: DBL_MAX;
+	      return neg ? -DBL_MAX : DBL_MAX;
 	  }
 	  if (exp_part != 0)
 	  {
 	    if (exp_neg)
-	      value /= pow (10.0, (double)exp_part);
+	      value /= pow (10.0, (double) exp_part);
 	    else
-	      value *= pow (10.0, (double)exp_part);
+	      value *= pow (10.0, (double) exp_part);
 	  }
 	  return value;
 
 	case NEG:
 	  if (i != 0)
 	  {
 	    str_ref.set_error ();
 	    return 0.0;
--- a/gfx/harfbuzz/src/hb-common.cc
+++ b/gfx/harfbuzz/src/hb-common.cc
@@ -30,16 +30,19 @@
 
 #include "hb-machinery.hh"
 
 #include <locale.h>
 #ifdef HAVE_XLOCALE_H
 #include <xlocale.h>
 #endif
 
+#ifdef HB_NO_SETLOCALE
+#define setlocale(Category, Locale) "C"
+#endif
 
 /**
  * SECTION:hb-common
  * @title: hb-common
  * @short_description: Common data types
  * @include: hb.h
  *
  * Common data types used across HarfBuzz are defined here.
@@ -62,17 +65,17 @@ void
   {
     while (*c)
     {
       const char *p = strchr (c, ':');
       if (!p)
         p = c + strlen (c);
 
 #define OPTION(name, symbol) \
-	if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) do { u.opts.symbol = true; } while (0)
+	if (0 == strncmp (c, name, p - c) && strlen (name) == static_cast<size_t>(p - c)) do { u.opts.symbol = true; } while (0)
 
       OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible);
       OPTION ("aat", aat);
 
 #undef OPTION
 
       c = *p ? p + 1 : p;
     }
--- a/gfx/harfbuzz/src/hb-config.hh
+++ b/gfx/harfbuzz/src/hb-config.hh
@@ -35,45 +35,60 @@
 #include "config.h"
 #endif
 
 
 #ifdef HB_TINY
 #define HB_LEAN
 #define HB_MINI
 #define HB_NO_MT
+#define HB_NO_UCD_UNASSIGNED
 #ifndef NDEBUG
 #define NDEBUG
 #endif
 #ifndef __OPTIMIZE_SIZE__
 #define __OPTIMIZE_SIZE__
 #endif
 #endif
 
 #ifdef HB_LEAN
 #define HB_DISABLE_DEPRECATED
 #define HB_NDEBUG
 #define HB_NO_ATEXIT
+#define HB_NO_BUFFER_MESSAGE
 #define HB_NO_BUFFER_SERIALIZE
 #define HB_NO_BITMAP
 #define HB_NO_CFF
 #define HB_NO_COLOR
+#define HB_NO_FACE_COLLECT_UNICODES
 #define HB_NO_GETENV
+#define HB_NO_HINTING
+#define HB_NO_LANGUAGE_PRIVATE_SUBTAG
+#define HB_NO_LAYOUT_FEATURE_PARAMS
+#define HB_NO_LAYOUT_COLLECT_GLYPHS
 #define HB_NO_LAYOUT_UNUSED
 #define HB_NO_MATH
+#define HB_NO_MMAP
 #define HB_NO_NAME
+#define HB_NO_OPEN
+#define HB_NO_SETLOCALE
+#define HB_NO_OT_FONT_GLYPH_NAMES
+#define HB_NO_OT_SHAPE_FRACTIONS
+#define HB_NO_STAT
 #define HB_NO_SUBSET_LAYOUT
+#define HB_NO_VAR
 #endif
 
 #ifdef HB_MINI
 #define HB_NO_AAT
 #define HB_NO_LEGACY
 #endif
 
-/* Closure. */
+
+/* Closure of options. */
 
 #ifdef HB_DISABLE_DEPRECATED
 #define HB_IF_NOT_DEPRECATED(x)
 #else
 #define HB_IF_NOT_DEPRECATED(x) x
 #endif
 
 #ifdef HB_NO_AAT
@@ -90,16 +105,19 @@
 #define HB_NO_SUBSET_CFF
 #endif
 
 #ifdef HB_NO_GETENV
 #define HB_NO_UNISCRIBE_BUG_COMPATIBLE
 #endif
 
 #ifdef HB_NO_LEGACY
+#define HB_NO_CMAP_LEGACY_SUBTABLES
+#define HB_NO_FALLBACK_SHAPE
+#define HB_NO_OT_KERN
 #define HB_NO_OT_LAYOUT_BLACKLIST
 #define HB_NO_OT_SHAPE_FALLBACK
 #endif
 
 #ifdef HB_NO_NAME
 #define HB_NO_OT_NAME_LANGUAGE
 #endif
 
--- a/gfx/harfbuzz/src/hb-coretext.cc
+++ b/gfx/harfbuzz/src/hb-coretext.cc
@@ -22,16 +22,19 @@
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Mozilla Author(s): Jonathan Kew
  * Google Author(s): Behdad Esfahbod
  */
 
 #include "hb.hh"
+
+#ifdef HAVE_CORETEXT
+
 #include "hb-shaper-impl.hh"
 
 #include "hb-coretext.h"
 #include "hb-aat-layout.hh"
 #include <math.h>
 
 
 /**
@@ -644,17 +647,17 @@ hb_bool_t
       log_clusters[chars_len++] = cluster; /* Surrogates. */
   }
 
 #define FAIL(...) \
   HB_STMT_START { \
     DEBUG_MSG (CORETEXT, nullptr, __VA_ARGS__); \
     ret = false; \
     goto fail; \
-  } HB_STMT_END;
+  } HB_STMT_END
 
   bool ret = true;
   CFStringRef string_ref = nullptr;
   CTLineRef line = nullptr;
 
   if (false)
   {
 resize_and_retry:
@@ -972,17 +975,17 @@ resize_and_retry:
 #define USE_PTR true
 
 #define SCRATCH_SAVE() \
   unsigned int scratch_size_saved = scratch_size; \
   hb_buffer_t::scratch_buffer_t *scratch_saved = scratch
 
 #define SCRATCH_RESTORE() \
   scratch_size = scratch_size_saved; \
-  scratch = scratch_saved;
+  scratch = scratch_saved
 
       { /* Setup glyphs */
         SCRATCH_SAVE();
 	const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : nullptr;
 	if (!glyphs) {
 	  ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs, goto resize_and_retry);
 	  CTRunGetGlyphs (run, range_all, glyph_buf);
 	  glyphs = glyph_buf;
@@ -1143,8 +1146,11 @@ fail:
     CFRelease (line);
 
   for (unsigned int i = 0; i < range_records.length; i++)
     if (range_records[i].font)
       CFRelease (range_records[i].font);
 
   return ret;
 }
+
+
+#endif
--- a/gfx/harfbuzz/src/hb-deprecated.h
+++ b/gfx/harfbuzz/src/hb-deprecated.h
@@ -160,40 +160,19 @@ hb_unicode_funcs_set_decompose_compatibi
 						   void *user_data, hb_destroy_func_t destroy);
 
 HB_EXTERN HB_DEPRECATED unsigned int
 hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
 				    hb_codepoint_t      u,
 				    hb_codepoint_t     *decomposed);
 
 
-typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
-							   hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-							   void *user_data);
-typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
 typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
 
 /**
- * hb_font_funcs_set_glyph_h_kerning_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- * Deprecated: 2.0.0
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
-					hb_font_get_glyph_h_kerning_func_t func,
-					void *user_data, hb_destroy_func_t destroy);
-
-/**
  * hb_font_funcs_set_glyph_v_kerning_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
@@ -201,26 +180,16 @@ hb_font_funcs_set_glyph_h_kerning_func (
  * Deprecated: 2.0.0
  **/
 HB_EXTERN void
 hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs,
 					hb_font_get_glyph_v_kerning_func_t func,
 					void *user_data, hb_destroy_func_t destroy);
 
 HB_EXTERN hb_position_t
-hb_font_get_glyph_h_kerning (hb_font_t *font,
-			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
-HB_EXTERN hb_position_t
 hb_font_get_glyph_v_kerning (hb_font_t *font,
 			     hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
 
-HB_EXTERN void
-hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
-					 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-					 hb_direction_t direction,
-					 hb_position_t *x, hb_position_t *y);
-
-
 #endif
 
 HB_END_DECLS
 
 #endif /* HB_DEPRECATED_H */
--- a/gfx/harfbuzz/src/hb-directwrite.cc
+++ b/gfx/harfbuzz/src/hb-directwrite.cc
@@ -18,16 +18,19 @@
  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  */
 
 #include "hb.hh"
+
+#ifdef HAVE_DIRECTWRITE
+
 #include "hb-shaper-impl.hh"
 
 #include <DWrite_1.h>
 
 #include "hb-directwrite.h"
 
 
 /*
@@ -168,17 +171,17 @@ hb_directwrite_face_data_t *
   uint64_t fontFileKey = 0;
   hr = dwriteFactory->CreateCustomFontFileReference (&fontFileKey, sizeof (fontFileKey),
 						     fontFileLoader, &fontFile);
 
 #define FAIL(...) \
   HB_STMT_START { \
     DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \
     return nullptr; \
-  } HB_STMT_END;
+  } HB_STMT_END
 
   if (FAILED (hr))
     FAIL ("Failed to load font file from data!");
 
   BOOL isSupported;
   DWRITE_FONT_FILE_TYPE fileType;
   DWRITE_FONT_FACE_TYPE faceType;
   uint32_t numberOfFaces;
@@ -946,15 +949,18 @@ hb_directwrite_face_create (IDWriteFontF
 }
 
 /**
 * hb_directwrite_face_get_font_face:
 * @face: a #hb_face_t object
 *
 * Return value: DirectWrite IDWriteFontFace object corresponding to the given input
 *
-* Since: REPLACEME
+* Since: 2.5.0
 **/
 IDWriteFontFace *
 hb_directwrite_face_get_font_face (hb_face_t *face)
 {
   return face->data.directwrite->fontFace;
 }
+
+
+#endif
--- a/gfx/harfbuzz/src/hb-face.cc
+++ b/gfx/harfbuzz/src/hb-face.cc
@@ -526,63 +526,62 @@ hb_face_get_table_tags (const hb_face_t 
 }
 
 
 /*
  * Character set.
  */
 
 
+#ifndef HB_NO_FACE_COLLECT_UNICODES
 /**
  * hb_face_collect_unicodes:
  * @face: font face.
  * @out: set to add Unicode characters covered by @face to.
  *
  * Since: 1.9.0
  */
 void
 hb_face_collect_unicodes (hb_face_t *face,
 			  hb_set_t  *out)
 {
   face->table.cmap->collect_unicodes (out);
 }
-
 /**
  * hb_face_collect_variation_selectors:
  * @face: font face.
  * @out: set to add Variation Selector characters covered by @face to.
  *
  *
  *
  * Since: 1.9.0
  */
 void
 hb_face_collect_variation_selectors (hb_face_t *face,
 				     hb_set_t  *out)
 {
   face->table.cmap->collect_variation_selectors (out);
 }
-
 /**
  * hb_face_collect_variation_unicodes:
  * @face: font face.
  * @out: set to add Unicode characters for @variation_selector covered by @face to.
  *
  *
  *
  * Since: 1.9.0
  */
 void
 hb_face_collect_variation_unicodes (hb_face_t *face,
 				    hb_codepoint_t variation_selector,
 				    hb_set_t  *out)
 {
   face->table.cmap->collect_variation_unicodes (variation_selector, out);
 }
-
+#endif
 
 
 /*
  * face-builder: A face that has add_table().
  */
 
 struct hb_face_builder_data_t
 {
--- a/gfx/harfbuzz/src/hb-fallback-shape.cc
+++ b/gfx/harfbuzz/src/hb-fallback-shape.cc
@@ -21,16 +21,17 @@
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Google Author(s): Behdad Esfahbod
  */
 
 #include "hb-shaper-impl.hh"
 
+#ifndef HB_NO_FALLBACK_SHAPE
 
 /*
  * shaper face data
  */
 
 struct hb_fallback_face_data_t {};
 
 hb_fallback_face_data_t *
@@ -115,8 +116,10 @@ hb_bool_t
 
   if (HB_DIRECTION_IS_BACKWARD (direction))
     hb_buffer_reverse (buffer);
 
   buffer->safe_to_break_all ();
 
   return true;
 }
+
+#endif
--- a/gfx/harfbuzz/src/hb-font.cc
+++ b/gfx/harfbuzz/src/hb-font.cc
@@ -331,17 +331,16 @@ hb_font_get_glyph_v_origin_default (hb_f
 				    void *user_data HB_UNUSED)
 {
   hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
   if (ret)
     font->parent_scale_position (x, y);
   return ret;
 }
 
-#ifndef HB_DISABLE_DEPRECATED
 static hb_position_t
 hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
 				 void *font_data HB_UNUSED,
 				 hb_codepoint_t left_glyph HB_UNUSED,
 				 hb_codepoint_t right_glyph HB_UNUSED,
 				 void *user_data HB_UNUSED)
 {
   return 0;
@@ -351,16 +350,17 @@ hb_font_get_glyph_h_kerning_default (hb_
 				     void *font_data HB_UNUSED,
 				     hb_codepoint_t left_glyph,
 				     hb_codepoint_t right_glyph,
 				     void *user_data HB_UNUSED)
 {
   return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
 }
 
+#ifndef HB_DISABLE_DEPRECATED
 static hb_position_t
 hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
 				 void *font_data HB_UNUSED,
 				 hb_codepoint_t top_glyph HB_UNUSED,
 				 hb_codepoint_t bottom_glyph HB_UNUSED,
 				 void *user_data HB_UNUSED)
 {
   return 0;
@@ -922,37 +922,36 @@ hb_font_get_glyph_h_origin (hb_font_t *f
 hb_bool_t
 hb_font_get_glyph_v_origin (hb_font_t *font,
 			    hb_codepoint_t glyph,
 			    hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_v_origin (glyph, x, y);
 }
 
-#ifndef HB_DISABLE_DEPRECATED
 /**
  * hb_font_get_glyph_h_kerning:
  * @font: a font.
  * @left_glyph: 
  * @right_glyph: 
  *
  * 
  *
  * Return value: 
  *
  * Since: 0.9.2
- * Deprecated: 2.0.0
  **/
 hb_position_t
 hb_font_get_glyph_h_kerning (hb_font_t *font,
 			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
 {
   return font->get_glyph_h_kerning (left_glyph, right_glyph);
 }
 
+#ifndef HB_DISABLE_DEPRECATED
 /**
  * hb_font_get_glyph_v_kerning:
  * @font: a font.
  * @top_glyph: 
  * @bottom_glyph: 
  *
  * 
  *
@@ -1172,40 +1171,37 @@ void
 hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
 					     hb_codepoint_t glyph,
 					     hb_direction_t direction,
 					     hb_position_t *x, hb_position_t *y)
 {
   return font->subtract_glyph_origin_for_direction (glyph, direction, x, y);
 }
 
-#ifndef HB_DISABLE_DEPRECATED
 /**
  * hb_font_get_glyph_kerning_for_direction:
  * @font: a font.
  * @first_glyph: 
  * @second_glyph: 
  * @direction: 
  * @x: (out): 
  * @y: (out): 
  *
  * 
  *
  * Since: 0.9.2
- * Deprecated: 2.0.0
  **/
 void
 hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
 					 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
 					 hb_direction_t direction,
 					 hb_position_t *x, hb_position_t *y)
 {
   return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y);
 }
-#endif
 
 /**
  * hb_font_get_glyph_extents_for_origin:
  * @font: a font.
  * @glyph: 
  * @direction: 
  * @extents: (out): 
  *
@@ -1823,16 +1819,17 @@ static void
 				      unsigned int coords_length)
 {
   free (font->coords);
 
   font->coords = coords;
   font->num_coords = coords_length;
 }
 
+#ifndef HB_NO_VAR
 /**
  * hb_font_set_variations:
  *
  * Since: 1.4.2
  */
 void
 hb_font_set_variations (hb_font_t *font,
 			const hb_variation_t *variations,
@@ -1853,17 +1850,16 @@ hb_font_set_variations (hb_font_t *font,
   if (unlikely (coords_length && !normalized))
     return;
 
   hb_ot_var_normalize_variations (font->face,
 				  variations, variations_length,
 				  normalized, coords_length);
   _hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
 }
-
 /**
  * hb_font_set_var_coords_design:
  *
  * Since: 1.4.2
  */
 void
 hb_font_set_var_coords_design (hb_font_t *font,
 			       const float *coords,
@@ -1874,16 +1870,17 @@ hb_font_set_var_coords_design (hb_font_t
 
   int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
   if (unlikely (coords_length && !normalized))
     return;
 
   hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized);
   _hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
 }
+#endif
 
 /**
  * hb_font_set_var_coords_normalized:
  *
  * Since: 1.4.2
  */
 void
 hb_font_set_var_coords_normalized (hb_font_t *font,
--- a/gfx/harfbuzz/src/hb-font.h
+++ b/gfx/harfbuzz/src/hb-font.h
@@ -152,16 +152,21 @@ typedef hb_font_get_glyph_advances_func_
 
 typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
 						      hb_codepoint_t glyph,
 						      hb_position_t *x, hb_position_t *y,
 						      void *user_data);
 typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t;
 typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t;
 
+typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
+							   hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+							   void *user_data);
+typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
+
 
 typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
 						       hb_codepoint_t glyph,
 						       hb_glyph_extents_t *extents,
 						       void *user_data);
 typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, void *font_data,
 							     hb_codepoint_t glyph, unsigned int point_index,
 							     hb_position_t *x, hb_position_t *y,
@@ -352,16 +357,32 @@ hb_font_funcs_set_glyph_h_origin_func (h
  * Since: 0.9.2
  **/
 HB_EXTERN void
 hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
 				       hb_font_get_glyph_v_origin_func_t func,
 				       void *user_data, hb_destroy_func_t destroy);
 
 /**
+ * hb_font_funcs_set_glyph_h_kerning_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ * 
+ *
+ * Since: 0.9.2
+ **/
+HB_EXTERN void
+hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
+					hb_font_get_glyph_h_kerning_func_t func,
+					void *user_data, hb_destroy_func_t destroy);
+
+/**
  * hb_font_funcs_set_glyph_extents_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
  * @destroy:
  *
  * 
  *
@@ -464,16 +485,20 @@ HB_EXTERN hb_bool_t
 hb_font_get_glyph_h_origin (hb_font_t *font,
 			    hb_codepoint_t glyph,
 			    hb_position_t *x, hb_position_t *y);
 HB_EXTERN hb_bool_t
 hb_font_get_glyph_v_origin (hb_font_t *font,
 			    hb_codepoint_t glyph,
 			    hb_position_t *x, hb_position_t *y);
 
+HB_EXTERN hb_position_t
+hb_font_get_glyph_h_kerning (hb_font_t *font,
+			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
+
 HB_EXTERN hb_bool_t
 hb_font_get_glyph_extents (hb_font_t *font,
 			   hb_codepoint_t glyph,
 			   hb_glyph_extents_t *extents);
 
 HB_EXTERN hb_bool_t
 hb_font_get_glyph_contour_point (hb_font_t *font,
 				 hb_codepoint_t glyph, unsigned int point_index,
@@ -526,16 +551,22 @@ hb_font_add_glyph_origin_for_direction (
 					hb_direction_t direction,
 					hb_position_t *x, hb_position_t *y);
 HB_EXTERN void
 hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
 					     hb_codepoint_t glyph,
 					     hb_direction_t direction,
 					     hb_position_t *x, hb_position_t *y);
 
+HB_EXTERN void
+hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
+					 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+					 hb_direction_t direction,
+					 hb_position_t *x, hb_position_t *y);
+
 HB_EXTERN hb_bool_t
 hb_font_get_glyph_extents_for_origin (hb_font_t *font,
 				      hb_codepoint_t glyph,
 				      hb_direction_t direction,
 				      hb_glyph_extents_t *extents);
 
 HB_EXTERN hb_bool_t
 hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
--- a/gfx/harfbuzz/src/hb-font.hh
+++ b/gfx/harfbuzz/src/hb-font.hh
@@ -46,17 +46,17 @@
   HB_FONT_FUNC_IMPLEMENT (nominal_glyphs) \
   HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
   HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
   HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
   HB_FONT_FUNC_IMPLEMENT (glyph_h_advances) \
   HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \
   HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
   HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
-  HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning)) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
   HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning)) \
   HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
   HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
   HB_FONT_FUNC_IMPLEMENT (glyph_name) \
   HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
   /* ^--- Add new callbacks here */
 
 struct hb_font_funcs_t
--- a/gfx/harfbuzz/src/hb-ft.cc
+++ b/gfx/harfbuzz/src/hb-ft.cc
@@ -24,16 +24,18 @@
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Red Hat Author(s): Behdad Esfahbod
  * Google Author(s): Behdad Esfahbod
  */
 
 #include "hb.hh"
 
+#ifdef HAVE_FREETYPE
+
 #include "hb-ft.h"
 
 #include "hb-font.hh"
 #include "hb-machinery.hh"
 #include "hb-cache.hh"
 
 #include FT_ADVANCES_H
 #include FT_MULTIPLE_MASTERS_H
@@ -341,16 +343,35 @@ hb_ft_get_glyph_v_origin (hb_font_t *fon
   if (font->x_scale < 0)
     *x = -*x;
   if (font->y_scale < 0)
     *y = -*y;
 
   return true;
 }
 
+#ifndef HB_NO_OT_SHAPE_FALLBACK
+static hb_position_t
+hb_ft_get_glyph_h_kerning (hb_font_t *font,
+			   void *font_data,
+			   hb_codepoint_t left_glyph,
+			   hb_codepoint_t right_glyph,
+			   void *user_data HB_UNUSED)
+{
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  FT_Vector kerningv;
+
+  FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED;
+  if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv))
+    return 0;
+
+  return kerningv.x;
+}
+#endif
+
 static hb_bool_t
 hb_ft_get_glyph_extents (hb_font_t *font,
 			 void *font_data,
 			 hb_codepoint_t glyph,
 			 hb_glyph_extents_t *extents,
 			 void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
@@ -492,16 +513,20 @@ static struct hb_ft_font_funcs_lazy_load
     //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr);
     hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ft_get_nominal_glyphs, nullptr, nullptr);
     hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr);
     hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr);
     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
     hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
+#ifndef HB_NO_OT_SHAPE_FALLBACK
+    hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
+#endif
+    //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, nullptr, nullptr);
     hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr);
     hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr);
     hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
     hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
 
     hb_font_funcs_make_immutable (funcs);
 
 #if HB_USE_ATEXIT
@@ -849,8 +874,11 @@ hb_ft_font_set_funcs (hb_font_t *font)
 #endif
 
   ft_face->generic.data = blob;
   ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
 
   _hb_ft_font_set_funcs (font, ft_face, true);
   hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING);
 }
+
+
+#endif
--- a/gfx/harfbuzz/src/hb-glib.cc
+++ b/gfx/harfbuzz/src/hb-glib.cc
@@ -23,16 +23,18 @@
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Red Hat Author(s): Behdad Esfahbod
  * Google Author(s): Behdad Esfahbod
  */
 
 #include "hb.hh"
 
+#ifdef HAVE_GLIB
+
 #include "hb-glib.h"
 
 #include "hb-machinery.hh"
 
 
 /**
  * SECTION:hb-glib
  * @title: hb-glib
@@ -399,8 +401,11 @@ hb_glib_blob_create (GBytes *gbytes)
   gconstpointer data = g_bytes_get_data (gbytes, &size);
   return hb_blob_create ((const char *) data,
 			 size,
 			 HB_MEMORY_MODE_READONLY,
 			 g_bytes_ref (gbytes),
 			 _hb_g_bytes_unref);
 }
 #endif
+
+
+#endif
--- a/gfx/harfbuzz/src/hb-gobject-enums.cc.tmpl
+++ b/gfx/harfbuzz/src/hb-gobject-enums.cc.tmpl
@@ -22,16 +22,18 @@
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Google Author(s): Behdad Esfahbod
  */
 
 #include "hb.hh"
 
+#ifdef HAVE_GOBJECT
+
 /* g++ didn't like older gtype.h gcc-only code path. */
 #include <glib.h>
 #if !GLIB_CHECK_VERSION(2,29,16)
 #undef __GNUC__
 #undef __GNUC_MINOR__
 #define __GNUC__ 2
 #define __GNUC_MINOR__ 6
 #endif
@@ -39,16 +41,21 @@
 #include "hb-gobject.h"
 
 /*** END file-header ***/
 
 /*** BEGIN file-production ***/
 /* enumerations from "@filename@" */
 /*** END file-production ***/
 
+/*** BEGIN file-tail ***/
+
+#endif
+/*** END file-tail ***/
+
 /*** BEGIN value-header ***/
 GType
 @enum_name@_get_type ()
 {
   static gsize type_id = 0;
 
   if (g_once_init_enter (&type_id))
     {
--- a/gfx/harfbuzz/src/hb-gobject-structs.cc
+++ b/gfx/harfbuzz/src/hb-gobject-structs.cc
@@ -21,16 +21,18 @@
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Google Author(s): Behdad Esfahbod
  */
 
 #include "hb.hh"
 
+#ifdef HAVE_GOBJECT
+
 
 /**
  * SECTION:hb-gobject
  * @title: hb-gobject
  * @short_description: GObject integration
  * @include: hb-gobject.h
  *
  * Functions for using HarfBuzz with the GObject library to provide
@@ -89,8 +91,11 @@ HB_DEFINE_OBJECT_TYPE (unicode_funcs)
 HB_DEFINE_VALUE_TYPE (feature)
 HB_DEFINE_VALUE_TYPE (glyph_info)
 HB_DEFINE_VALUE_TYPE (glyph_position)
 HB_DEFINE_VALUE_TYPE (segment_properties)
 HB_DEFINE_VALUE_TYPE (user_data_key)
 
 HB_DEFINE_VALUE_TYPE (ot_math_glyph_variant)
 HB_DEFINE_VALUE_TYPE (ot_math_glyph_part)
+
+
+#endif
--- a/gfx/harfbuzz/src/hb-graphite2.cc
+++ b/gfx/harfbuzz/src/hb-graphite2.cc
@@ -21,16 +21,20 @@
  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Google Author(s): Behdad Esfahbod
  */
 
+#include "hb.hh"
+
+#ifdef HAVE_GRAPHITE2
+
 #include "hb-shaper-impl.hh"
 
 #include "hb-graphite2.h"
 
 #include <graphite2/Segment.h>
 
 #include "hb-ot-layout.h"
 
@@ -442,8 +446,11 @@ hb_bool_t
 
   if (feats) gr_featureval_destroy (feats);
   gr_seg_destroy (seg);
 
   buffer->unsafe_to_break_all ();
 
   return true;
 }
+
+
+#endif
--- a/gfx/harfbuzz/src/hb-icu.cc
+++ b/gfx/harfbuzz/src/hb-icu.cc
@@ -24,16 +24,18 @@
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Red Hat Author(s): Behdad Esfahbod
  * Google Author(s): Behdad Esfahbod
  */
 
 #include "hb.hh"
 
+#ifdef HAVE_ICU
+
 #include "hb-icu.h"
 
 #include "hb-machinery.hh"
 
 #include <unicode/uchar.h>
 #include <unicode/unorm2.h>
 #include <unicode/ustring.h>
 #include <unicode/utf16.h>
@@ -346,8 +348,11 @@ void free_static_icu_funcs ()
 }
 #endif
 
 hb_unicode_funcs_t *
 hb_icu_get_unicode_funcs ()
 {
   return static_icu_funcs.get_unconst ();
 }
+
+
+#endif
--- a/gfx/harfbuzz/src/hb-mutex.hh
+++ b/gfx/harfbuzz/src/hb-mutex.hh
@@ -101,17 +101,17 @@ typedef volatile int hb_mutex_impl_t;
 # define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
 #endif
 
 #define HB_MUTEX_INT_NIL 1 /* Warn that fallback implementation is in use. */
 typedef volatile int hb_mutex_impl_t;
 #define HB_MUTEX_IMPL_INIT	0
 #define hb_mutex_impl_init(M)	*(M) = 0
 #define hb_mutex_impl_lock(M)	HB_STMT_START { while (*(M)) HB_SCHED_YIELD (); (*(M))++; } HB_STMT_END
-#define hb_mutex_impl_unlock(M)	(*(M))--;
+#define hb_mutex_impl_unlock(M)	(*(M))--
 #define hb_mutex_impl_finish(M)	HB_STMT_START {} HB_STMT_END
 
 
 #else /* HB_NO_MT */
 
 typedef int hb_mutex_impl_t;
 #define HB_MUTEX_IMPL_INIT	0
 #define hb_mutex_impl_init(M)	HB_STMT_START {} HB_STMT_END
--- a/gfx/harfbuzz/src/hb-null.hh
+++ b/gfx/harfbuzz/src/hb-null.hh
@@ -69,17 +69,17 @@ using hb_static_size = _hb_static_size<T
 #define hb_static_size(T) hb_static_size<T>::value
 
 
 /*
  * Null()
  */
 
 extern HB_INTERNAL
-hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
+uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)];
 
 /* Generic nul-content Null objects. */
 template <typename Type>
 struct Null {
   static Type const & get_null ()
   {
     static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
     return *reinterpret_cast<Type const *> (_hb_NullPool);
@@ -123,17 +123,17 @@ struct NullHelper
 
 /* Global writable pool.  Enlarge as necessary. */
 
 /* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
  * for correct operation. It only exist to catch and divert program logic bugs instead of
  * causing bad memory access. So, races there are not actually introducing incorrectness
  * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
 extern HB_INTERNAL
-/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
+/*thread_local*/ uint64_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)];
 
 /* CRAP pool: Common Region for Access Protection. */
 template <typename Type>
 static inline Type& Crap () {
   static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
   Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
   memcpy (obj, &Null(Type), sizeof (*obj));
   return *obj;
--- a/gfx/harfbuzz/src/hb-open-type.hh
+++ b/gfx/harfbuzz/src/hb-open-type.hh
@@ -54,21 +54,21 @@ namespace OT {
 
 /* Integer types in big-endian order and no alignment requirement */
 template <typename Type, unsigned int Size>
 struct IntType
 {
   typedef Type type;
   typedef hb_conditional<hb_is_signed (Type), signed, unsigned> wide_type;
 
-  IntType<Type, Size>& operator = (wide_type i) { v = i; return *this; }
+  IntType& operator = (wide_type i) { v = i; return *this; }
   operator wide_type () const { return v; }
-  bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
-  bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
-  HB_INTERNAL static int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b)
+  bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; }
+  bool operator != (const IntType &o) const { return !(*this == o); }
+  HB_INTERNAL static int cmp (const IntType *a, const IntType *b)
   { return b->cmp (*a); }
   template <typename Type2>
   int cmp (Type2 a) const
   {
     Type b = v;
     if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
       return (int) a - (int) b;
     else
@@ -141,17 +141,17 @@ struct LONGDATETIME
   public:
   DEFINE_SIZE_STATIC (8);
 };
 
 /* Array of four uint8s (length = 32 bits) used to identify a script, language
  * system, feature, or baseline */
 struct Tag : HBUINT32
 {
-  Tag& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; }
+  Tag& operator = (hb_tag_t i) { HBUINT32::operator= (i); return *this; }
   /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
   operator const char* () const { return reinterpret_cast<const char *> (&this->v); }
   operator char* ()             { return reinterpret_cast<char *> (&this->v); }
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 /* Glyph index number, same as uint16 (length = 16 bits) */
--- a/gfx/harfbuzz/src/hb-ot-cff-common.hh
+++ b/gfx/harfbuzz/src/hb-ot-cff-common.hh
@@ -22,16 +22,17 @@
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Adobe Author(s): Michiharu Ariza
  */
 #ifndef HB_OT_CFF_COMMON_HH
 #define HB_OT_CFF_COMMON_HH
 
 #include "hb-open-type.hh"
+#include "hb-bimap.hh"
 #include "hb-ot-layout-common.hh"
 #include "hb-cff-interp-dict-common.hh"
 #include "hb-subset-plan.hh"
 
 namespace CFF {
 
 using namespace OT;
 
@@ -77,32 +78,24 @@ struct str_buff_vec_t : hb_vector_t<str_
   private:
   typedef hb_vector_t<str_buff_t> SUPER;
 };
 
 /* CFF INDEX */
 template <typename COUNT>
 struct CFFIndex
 {
-  bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */
-			  (c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
-			   c->check_array (offsets, offSize, count + 1) &&
-			   c->check_array ((const HBUINT8*)data_base (), 1, max_offset () - 1))));
-  }
-
   static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count)
   { return offSize * (count + 1); }
 
   unsigned int offset_array_size () const
   { return calculate_offset_array_size (offSize, count); }
 
-  static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count, unsigned int dataSize)
+  static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count,
+						 unsigned int dataSize)
   {
     if (count == 0)
       return COUNT::static_size;
     else
       return min_size + calculate_offset_array_size (offSize_, count) + dataSize;
   }
 
   bool serialize (hb_serialize_context_t *c, const CFFIndex &src)
@@ -194,66 +187,75 @@ struct CFFIndex
     unsigned int offset = 0;
     for (; size; size--)
       offset = (offset << 8) + *p++;
     return offset;
   }
 
   unsigned int length_at (unsigned int index) const
   {
-	if (likely ((offset_at (index + 1) >= offset_at (index)) &&
-		    (offset_at (index + 1) <= offset_at (count))))
-	  return offset_at (index + 1) - offset_at (index);
-	else
-	  return 0;
+    if (likely ((offset_at (index + 1) >= offset_at (index)) &&
+	        (offset_at (index + 1) <= offset_at (count))))
+      return offset_at (index + 1) - offset_at (index);
+    else
+      return 0;
   }
 
   const unsigned char *data_base () const
   { return (const unsigned char *)this + min_size + offset_array_size (); }
 
   unsigned int data_size () const { return HBINT8::static_size; }
 
   byte_str_t operator [] (unsigned int index) const
   {
     if (likely (index < count))
       return byte_str_t (data_base () + offset_at (index) - 1, length_at (index));
     else
-      return Null(byte_str_t);
+      return Null (byte_str_t);
   }
 
   unsigned int get_size () const
   {
-    if (this != &Null(CFFIndex))
+    if (this != &Null (CFFIndex))
     {
       if (count > 0)
 	return min_size + offset_array_size () + (offset_at (count) - 1);
       else
 	return count.static_size;  /* empty CFFIndex contains count only */
     }
     else
       return 0;
   }
 
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */
+			  (c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
+			   c->check_array (offsets, offSize, count + 1) &&
+			   c->check_array ((const HBUINT8*) data_base (), 1, max_offset () - 1))));
+  }
+
   protected:
   unsigned int max_offset () const
   {
     unsigned int max = 0;
     for (unsigned int i = 0; i < count + 1u; i++)
     {
       unsigned int off = offset_at (i);
       if (off > max) max = off;
     }
     return max;
   }
 
   public:
-  COUNT     count;	/* Number of object data. Note there are (count+1) offsets */
-  HBUINT8   offSize;      /* The byte size of each offset in the offsets array. */
-  HBUINT8   offsets[VAR]; /* The array of (count + 1) offsets into objects array (1-base). */
-  /* HBUINT8 data[VAR];      Object data */
+  COUNT		count;		/* Number of object data. Note there are (count+1) offsets */
+  HBUINT8	offSize;	/* The byte size of each offset in the offsets array. */
+  HBUINT8	offsets[VAR];	/* The array of (count + 1) offsets into objects array (1-base). */
+  /* HBUINT8 data[VAR];	Object data */
   public:
   DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets);
 };
 
 template <typename COUNT, typename TYPE>
 struct CFFIndexOf : CFFIndex<COUNT>
 {
   const byte_str_t operator [] (unsigned int index) const
@@ -288,34 +290,34 @@ struct CFFIndexOf : CFFIndex<COUNT>
       CFFIndex<COUNT>::set_offset_at (i, offset);
       offset += dataSizeArray[i];
     }
     CFFIndex<COUNT>::set_offset_at (i, offset);
 
     /* serialize data */
     for (unsigned int i = 0; i < dataArrayLen; i++)
     {
-      TYPE  *dest = c->start_embed<TYPE> ();
+      TYPE *dest = c->start_embed<TYPE> ();
       if (unlikely (dest == nullptr ||
 		    !dest->serialize (c, dataArray[i], param1, param2)))
 	return_trace (false);
     }
     return_trace (true);
   }
 
   /* in parallel to above */
   template <typename DATA, typename PARAM>
   static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
 						 const DATA *dataArray,
 						 unsigned int dataArrayLen,
 						 hb_vector_t<unsigned int> &dataSizeArray, /* OUT */
 						 const PARAM &param)
   {
     /* determine offset size */
-    unsigned int  totalDataSize = 0;
+    unsigned int totalDataSize = 0;
     for (unsigned int i = 0; i < dataArrayLen; i++)
     {
       unsigned int dataSize = TYPE::calculate_serialized_size (dataArray[i], param);
       dataSizeArray[i] = dataSize;
       totalDataSize += dataSize;
     }
     offSize_ = calcOffSize (totalDataSize);
 
@@ -329,20 +331,19 @@ struct Dict : UnsizedByteStr
   template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
   bool serialize (hb_serialize_context_t *c,
 		  const DICTVAL &dictval,
 		  OP_SERIALIZER& opszr,
 		  PARAM& param)
   {
     TRACE_SERIALIZE (this);
     for (unsigned int i = 0; i < dictval.get_count (); i++)
-    {
       if (unlikely (!opszr.serialize (c, dictval[i], param)))
 	return_trace (false);
-    }
+
     return_trace (true);
   }
 
   /* in parallel to above */
   template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
   static unsigned int calculate_serialized_size (const DICTVAL &dictval,
 						 OP_SERIALIZER& opszr,
 						 PARAM& param)
@@ -386,90 +387,35 @@ struct Dict : UnsizedByteStr
 
   static bool serialize_uint4_op (hb_serialize_context_t *c, op_code_t op, int value)
   { return serialize_int_op<HBUINT32, 0, 0x7FFFFFFF> (c, op, value, OpCode_longintdict); }
 
   static bool serialize_uint2_op (hb_serialize_context_t *c, op_code_t op, int value)
   { return serialize_int_op<HBUINT16, 0, 0x7FFF> (c, op, value, OpCode_shortint); }
 
   static bool serialize_offset4_op (hb_serialize_context_t *c, op_code_t op, int value)
-  {
-    return serialize_uint4_op (c, op, value);
-  }
+  { return serialize_uint4_op (c, op, value); }
 
   static bool serialize_offset2_op (hb_serialize_context_t *c, op_code_t op, int value)
-  {
-    return serialize_uint2_op (c, op, value);
-  }
+  { return serialize_uint2_op (c, op, value); }
 };
 
 struct TopDict : Dict {};
 struct FontDict : Dict {};
 struct PrivateDict : Dict {};
 
 struct table_info_t
 {
   void init () { offSize = offset = size = 0; }
 
   unsigned int    offset;
   unsigned int    size;
   unsigned int    offSize;
 };
 
-/* used to remap font index or SID from fullset to subset.
- * set to CFF_UNDEF_CODE if excluded from subset */
-struct remap_t : hb_vector_t<hb_codepoint_t>
-{
-  void init () { SUPER::init (); }
-
-  void fini () { SUPER::fini (); }
-
-  bool reset (unsigned int size)
-  {
-    if (unlikely (!SUPER::resize (size)))
-      return false;
-    for (unsigned int i = 0; i < length; i++)
-      (*this)[i] = CFF_UNDEF_CODE;
-    count = 0;
-    return true;
-  }
-
-  bool identity (unsigned int size)
-  {
-    if (unlikely (!SUPER::resize (size)))
-      return false;
-    unsigned int i;
-    for (i = 0; i < length; i++)
-      (*this)[i] = i;
-    count = i;
-    return true;
-  }
-
-  bool excludes (hb_codepoint_t id) const
-  { return (id < length) && ((*this)[id] == CFF_UNDEF_CODE); }
-
-  bool includes (hb_codepoint_t id) const
-  { return !excludes (id); }
-
-  unsigned int add (unsigned int i)
-  {
-    if ((*this)[i] == CFF_UNDEF_CODE)
-      (*this)[i] = count++;
-    return (*this)[i];
-  }
-
-  hb_codepoint_t get_count () const { return count; }
-
-  protected:
-  hb_codepoint_t  count;
-
-  private:
-  typedef hb_vector_t<hb_codepoint_t> SUPER;
-};
-
 template <typename COUNT>
 struct FDArray : CFFIndexOf<COUNT, FontDict>
 {
   /* used by CFF1 */
   template <typename DICTVAL, typename OP_SERIALIZER>
   bool serialize (hb_serialize_context_t *c,
 		  unsigned int offSize_,
 		  const hb_vector_t<DICTVAL> &fontDicts,
@@ -478,17 +424,17 @@ struct FDArray : CFFIndexOf<COUNT, FontD
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
     this->count = fontDicts.length;
     this->offSize = offSize_;
     if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (fontDicts.length + 1))))
       return_trace (false);
 
     /* serialize font dict offsets */
-    unsigned int  offset = 1;
+    unsigned int offset = 1;
     unsigned int fid = 0;
     for (; fid < fontDicts.length; fid++)
     {
       CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
       offset += FontDict::calculate_serialized_size (fontDicts[fid], opszr);
     }
     CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
 
@@ -503,61 +449,61 @@ struct FDArray : CFFIndexOf<COUNT, FontD
   }
 
   /* used by CFF2 */
   template <typename DICTVAL, typename OP_SERIALIZER>
   bool serialize (hb_serialize_context_t *c,
 		  unsigned int offSize_,
 		  const hb_vector_t<DICTVAL> &fontDicts,
 		  unsigned int fdCount,
-		  const remap_t &fdmap,
+		  const hb_inc_bimap_t &fdmap,
 		  OP_SERIALIZER& opszr,
 		  const hb_vector_t<table_info_t> &privateInfos)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
     this->count = fdCount;
     this->offSize = offSize_;
     if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (fdCount + 1))))
       return_trace (false);
 
     /* serialize font dict offsets */
     unsigned int  offset = 1;
     unsigned int  fid = 0;
     for (unsigned i = 0; i < fontDicts.length; i++)
-      if (fdmap.includes (i))
+      if (fdmap.has (i))
       {
       	if (unlikely (fid >= fdCount)) return_trace (false);
 	CFFIndexOf<COUNT, FontDict>::set_offset_at (fid++, offset);
 	offset += FontDict::calculate_serialized_size (fontDicts[i], opszr);
       }
     CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
 
     /* serialize font dicts */
     for (unsigned int i = 0; i < fontDicts.length; i++)
-      if (fdmap.includes (i))
+      if (fdmap.has (i))
       {
 	FontDict *dict = c->start_embed<FontDict> ();
 	if (unlikely (!dict->serialize (c, fontDicts[i], opszr, privateInfos[fdmap[i]])))
 	  return_trace (false);
       }
     return_trace (true);
   }
 
   /* in parallel to above */
   template <typename OP_SERIALIZER, typename DICTVAL>
   static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
 						 const hb_vector_t<DICTVAL> &fontDicts,
 						 unsigned int fdCount,
-						 const remap_t &fdmap,
+						 const hb_inc_bimap_t &fdmap,
 						 OP_SERIALIZER& opszr)
   {
     unsigned int dictsSize = 0;
     for (unsigned int i = 0; i < fontDicts.len; i++)
-      if (fdmap.includes (i))
+      if (fdmap.has (i))
 	dictsSize += FontDict::calculate_serialized_size (fontDicts[i], opszr);
 
     offSize_ = calcOffSize (dictsSize);
     return CFFIndex<COUNT>::calculate_serialized_size (offSize_, fdCount, dictsSize);
   }
 };
 
 /* FDSelect */
@@ -570,59 +516,57 @@ struct FDSelect0 {
     for (unsigned int i = 0; i < c->get_num_glyphs (); i++)
       if (unlikely (!fds[i].sanitize (c)))
 	return_trace (false);
 
     return_trace (true);
   }
 
   hb_codepoint_t get_fd (hb_codepoint_t glyph) const
-  {
-    return (hb_codepoint_t)fds[glyph];
-  }
+  { return (hb_codepoint_t) fds[glyph]; }
 
   unsigned int get_size (unsigned int num_glyphs) const
   { return HBUINT8::static_size * num_glyphs; }
 
   HBUINT8     fds[VAR];
 
   DEFINE_SIZE_MIN (1);
 };
 
 template <typename GID_TYPE, typename FD_TYPE>
-struct FDSelect3_4_Range {
+struct FDSelect3_4_Range
+{
   bool sanitize (hb_sanitize_context_t *c, const void * /*nullptr*/, unsigned int fdcount) const
   {
     TRACE_SANITIZE (this);
     return_trace (first < c->get_num_glyphs () && (fd < fdcount));
   }
 
   GID_TYPE    first;
   FD_TYPE     fd;
-
+  public:
   DEFINE_SIZE_STATIC (GID_TYPE::static_size + FD_TYPE::static_size);
 };
 
 template <typename GID_TYPE, typename FD_TYPE>
-struct FDSelect3_4 {
+struct FDSelect3_4
+{
   unsigned int get_size () const
   { return GID_TYPE::static_size * 2 + ranges.get_size (); }
 
   bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this) || !ranges.sanitize (c, nullptr, fdcount) ||
     		  (nRanges () == 0) || ranges[0].first != 0))
       return_trace (false);
 
     for (unsigned int i = 1; i < nRanges (); i++)
-    {
       if (unlikely (ranges[i - 1].first >= ranges[i].first))
-	  return_trace (false);
-    }
+	return_trace (false);
 
     if (unlikely (!sentinel().sanitize (c) || (sentinel() != c->get_num_glyphs ())))
       return_trace (false);
 
     return_trace (true);
   }
 
   hb_codepoint_t get_fd (hb_codepoint_t glyph) const
@@ -644,66 +588,73 @@ struct FDSelect3_4 {
   /* GID_TYPE sentinel */
 
   DEFINE_SIZE_ARRAY (GID_TYPE::static_size, ranges);
 };
 
 typedef FDSelect3_4<HBUINT16, HBUINT8> FDSelect3;
 typedef FDSelect3_4_Range<HBUINT16, HBUINT8> FDSelect3_Range;
 
-struct FDSelect {
-  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
-  {
-    TRACE_SANITIZE (this);
-
-    return_trace (likely (c->check_struct (this) && (format == 0 || format == 3) &&
-			  (format == 0)?
-			  u.format0.sanitize (c, fdcount):
-			  u.format3.sanitize (c, fdcount)));
-  }
-
+struct FDSelect
+{
   bool serialize (hb_serialize_context_t *c, const FDSelect &src, unsigned int num_glyphs)
   {
     TRACE_SERIALIZE (this);
     unsigned int size = src.get_size (num_glyphs);
     FDSelect *dest = c->allocate_size<FDSelect> (size);
     if (unlikely (dest == nullptr)) return_trace (false);
     memcpy (dest, &src, size);
     return_trace (true);
   }
 
   unsigned int calculate_serialized_size (unsigned int num_glyphs) const
   { return get_size (num_glyphs); }
 
   unsigned int get_size (unsigned int num_glyphs) const
   {
-    unsigned int size = format.static_size;
-    if (format == 0)
-      size += u.format0.get_size (num_glyphs);
-    else
-      size += u.format3.get_size ();
-    return size;
+    switch (format)
+    {
+    case 0: return format.static_size + u.format0.get_size (num_glyphs);
+    case 3: return format.static_size + u.format3.get_size ();
+    default:return 0;
+    }
   }
 
   hb_codepoint_t get_fd (hb_codepoint_t glyph) const
   {
-    if (this == &Null(FDSelect))
+    if (this == &Null (FDSelect))
       return 0;
-    if (format == 0)
-      return u.format0.get_fd (glyph);
-    else
-      return u.format3.get_fd (glyph);
+    switch (format)
+    {
+    case 0: return u.format0.get_fd (glyph);
+    case 3: return u.format3.get_fd (glyph);
+    default:return 0;
+    }
   }
 
-  HBUINT8       format;
+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+
+    switch (format)
+    {
+    case 0: return_trace (u.format0.sanitize (c, fdcount));
+    case 3: return_trace (u.format3.sanitize (c, fdcount));
+    default:return_trace (false);
+    }
+  }
+
+  HBUINT8	format;
   union {
-    FDSelect0   format0;
-    FDSelect3   format3;
+  FDSelect0	format0;
+  FDSelect3	format3;
   } u;
-
+  public:
   DEFINE_SIZE_MIN (1);
 };
 
 template <typename COUNT>
 struct Subrs : CFFIndex<COUNT>
 {
   typedef COUNT count_type;
   typedef CFFIndex<COUNT> SUPER;
--- a/gfx/harfbuzz/src/hb-ot-cff1-table.cc
+++ b/gfx/harfbuzz/src/hb-ot-cff1-table.cc
@@ -19,21 +19,23 @@
  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Adobe Author(s): Michiharu Ariza
  */
 
+#include "hb.hh"
+
+#ifndef HB_NO_CFF
+
 #include "hb-ot-cff1-table.hh"
 #include "hb-cff1-interp-cs.hh"
 
-#ifndef HB_NO_CFF
-
 using namespace CFF;
 
 /* SID to code */
 static const uint8_t standard_encoding_to_code [] =
 {
     0,   32,   33,   34,   35,   36,   37,   38,  39,   40,   41,   42,   43,   44,   45,   46,
    47,   48,   49,   50,   51,   52,   53,   54,  55,   56,   57,   58,   59,   60,   61,   62,
    63,   64,   65,   66,   67,   68,   69,   70,  71,   72,   73,   74,   75,   76,   77,   78,
@@ -386,9 +388,10 @@ bool OT::cff1::accelerator_t::get_seac_c
   {
     *base = param.base;
     *accent = param.accent;
     return true;
   }
   return false;
 }
 
+
 #endif
--- a/gfx/harfbuzz/src/hb-ot-cff1-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-cff1-table.hh
@@ -156,31 +156,18 @@ struct CFF1SuppEncData {
   HBUINT8 &nSups () { return supps.len; }
   HBUINT8 nSups () const { return supps.len; }
 
   ArrayOf<SuppEncoding, HBUINT8> supps;
 
   DEFINE_SIZE_ARRAY_SIZED (1, supps);
 };
 
-struct Encoding {
-  bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-
-    if (unlikely (!c->check_struct (this)))
-      return_trace (false);
-    unsigned int fmt = format & 0x7F;
-    if (unlikely (fmt > 1))
-      return_trace (false);
-    if (unlikely (!((fmt == 0)? u.format0.sanitize (c): u.format1.sanitize (c))))
-      return_trace (false);
-    return_trace (((format & 0x80) == 0) || suppEncData ().sanitize (c));
-  }
-
+struct Encoding
+{
   /* serialize a fullset Encoding */
   bool serialize (hb_serialize_context_t *c, const Encoding &src)
   {
     TRACE_SERIALIZE (this);
     unsigned int size = src.get_size ();
     Encoding *dest = c->allocate_size<Encoding> (size);
     if (unlikely (dest == nullptr)) return_trace (false);
     memcpy (dest, &src, size);
@@ -192,119 +179,148 @@ struct Encoding {
 		  uint8_t format,
 		  unsigned int enc_count,
 		  const hb_vector_t<code_pair_t>& code_ranges,
 		  const hb_vector_t<code_pair_t>& supp_codes)
   {
     TRACE_SERIALIZE (this);
     Encoding *dest = c->extend_min (*this);
     if (unlikely (dest == nullptr)) return_trace (false);
-    dest->format = format | ((supp_codes.length > 0)? 0x80: 0);
-    if (format == 0)
+    dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
+    switch (format) {
+    case 0:
     {
       Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
-    if (unlikely (fmt0 == nullptr)) return_trace (false);
+      if (unlikely (fmt0 == nullptr)) return_trace (false);
       fmt0->nCodes () = enc_count;
       unsigned int glyph = 0;
       for (unsigned int i = 0; i < code_ranges.length; i++)
       {
 	hb_codepoint_t code = code_ranges[i].code;
 	for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
 	  fmt0->codes[glyph++] = code++;
 	if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
 	  return_trace (false);
       }
     }
-    else
+    break;
+
+    case 1:
     {
       Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
       if (unlikely (fmt1 == nullptr)) return_trace (false);
       fmt1->nRanges () = code_ranges.length;
       for (unsigned int i = 0; i < code_ranges.length; i++)
       {
 	if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
 	  return_trace (false);
 	fmt1->ranges[i].first = code_ranges[i].code;
 	fmt1->ranges[i].nLeft = code_ranges[i].glyph;
       }
     }
-    if (supp_codes.length > 0)
+    break;
+
+    }
+
+    if (supp_codes.length)
     {
       CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
       if (unlikely (suppData == nullptr)) return_trace (false);
       suppData->nSups () = supp_codes.length;
       for (unsigned int i = 0; i < supp_codes.length; i++)
       {
 	suppData->supps[i].code = supp_codes[i].code;
 	suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */
       }
     }
+
     return_trace (true);
   }
 
   /* parallel to above: calculate the size of a subset Encoding */
   static unsigned int calculate_serialized_size (uint8_t format,
 						 unsigned int enc_count,
 						 unsigned int supp_count)
   {
-    unsigned int  size = min_size;
-    if (format == 0)
-      size += Encoding0::min_size + HBUINT8::static_size * enc_count;
-    else
-      size += Encoding1::min_size + Encoding1_Range::static_size * enc_count;
+    unsigned int size = min_size;
+    switch (format)
+    {
+    case 0: size += Encoding0::min_size + HBUINT8::static_size * enc_count; break;
+    case 1: size += Encoding1::min_size + Encoding1_Range::static_size * enc_count; break;
+    default:return 0;
+    }
     if (supp_count > 0)
       size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count;
     return size;
   }
 
   unsigned int get_size () const
   {
     unsigned int size = min_size;
-    if (table_format () == 0)
-      size += u.format0.get_size ();
-    else
-      size += u.format1.get_size ();
+    switch (table_format ())
+    {
+    case 0: size += u.format0.get_size (); break;
+    case 1: size += u.format1.get_size (); break;
+    }
     if (has_supplement ())
       size += suppEncData ().get_size ();
     return size;
   }
 
   hb_codepoint_t get_code (hb_codepoint_t glyph) const
   {
-    if (table_format () == 0)
-      return u.format0.get_code (glyph);
-    else
-      return u.format1.get_code (glyph);
+    switch (table_format ())
+    {
+    case 0: return u.format0.get_code (glyph);
+    case 1: return u.format1.get_code (glyph);
+    default:return 0;
+    }
   }
 
-  uint8_t table_format () const { return (format & 0x7F); }
-  bool  has_supplement () const { return (format & 0x80) != 0; }
+  uint8_t table_format () const { return format & 0x7F; }
+  bool  has_supplement () const { return format & 0x80; }
 
   void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
   {
     codes.resize (0);
     if (has_supplement ())
       suppEncData().get_codes (sid, codes);
   }
 
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+
+    switch (table_format ())
+    {
+    case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
+    case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
+    default:return_trace (false);
+    }
+    return_trace (likely (!has_supplement () || suppEncData ().sanitize (c)));
+  }
+
   protected:
   const CFF1SuppEncData &suppEncData () const
   {
-    if ((format & 0x7F) == 0)
-      return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
-    else
-      return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
+    switch (table_format ())
+    {
+    case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
+    case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
+    default:return Null (CFF1SuppEncData);
+    }
   }
 
   public:
-  HBUINT8       format;
-
+  HBUINT8	format;
   union {
-    Encoding0   format0;
-    Encoding1   format1;
+  Encoding0	format0;
+  Encoding1	format1;
   } u;
   /* CFF1SuppEncData  suppEncData; */
 
   DEFINE_SIZE_MIN (1);
 };
 
 /* Charset */
 struct Charset0 {
@@ -428,33 +444,18 @@ struct Charset1_2 {
   DEFINE_SIZE_ARRAY (0, ranges);
 };
 
 typedef Charset1_2<HBUINT8>     Charset1;
 typedef Charset1_2<HBUINT16>    Charset2;
 typedef Charset_Range<HBUINT8>  Charset1_Range;
 typedef Charset_Range<HBUINT16> Charset2_Range;
 
-struct Charset {
-  bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-
-    if (unlikely (!c->check_struct (this)))
-      return_trace (false);
-    if (format == 0)
-      return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
-    else if (format == 1)
-      return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
-    else if (likely (format == 2))
-      return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
-    else
-      return_trace (false);
-  }
-
+struct Charset
+{
   /* serialize a fullset Charset */
   bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
   {
     TRACE_SERIALIZE (this);
     unsigned int size = src.get_size (num_glyphs);
     Charset *dest = c->allocate_size<Charset> (size);
     if (unlikely (dest == nullptr)) return_trace (false);
     memcpy (dest, &src, size);
@@ -466,157 +467,179 @@ struct Charset {
 		  uint8_t format,
 		  unsigned int num_glyphs,
 		  const hb_vector_t<code_pair_t>& sid_ranges)
   {
     TRACE_SERIALIZE (this);
     Charset *dest = c->extend_min (*this);
     if (unlikely (dest == nullptr)) return_trace (false);
     dest->format = format;
-    if (format == 0)
+    switch (format)
+    {
+    case 0:
     {
       Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
-    if (unlikely (fmt0 == nullptr)) return_trace (false);
+      if (unlikely (fmt0 == nullptr)) return_trace (false);
       unsigned int glyph = 0;
       for (unsigned int i = 0; i < sid_ranges.length; i++)
       {
 	hb_codepoint_t sid = sid_ranges[i].code;
 	for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
 	  fmt0->sids[glyph++] = sid++;
       }
     }
-    else if (format == 1)
+    break;
+
+    case 1:
     {
       Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
       if (unlikely (fmt1 == nullptr)) return_trace (false);
       for (unsigned int i = 0; i < sid_ranges.length; i++)
       {
       	if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
 	  return_trace (false);
 	fmt1->ranges[i].first = sid_ranges[i].code;
 	fmt1->ranges[i].nLeft = sid_ranges[i].glyph;
       }
     }
-    else /* format 2 */
+    break;
+
+    case 2:
     {
       Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
       if (unlikely (fmt2 == nullptr)) return_trace (false);
       for (unsigned int i = 0; i < sid_ranges.length; i++)
       {
       	if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
 	  return_trace (false);
 	fmt2->ranges[i].first = sid_ranges[i].code;
 	fmt2->ranges[i].nLeft = sid_ranges[i].glyph;
       }
     }
+    break;
+
+    }
     return_trace (true);
   }
 
   /* parallel to above: calculate the size of a subset Charset */
-  static unsigned int calculate_serialized_size (
-			uint8_t format,
-			unsigned int count)
+  static unsigned int calculate_serialized_size (uint8_t format,
+						 unsigned int count)
   {
-    unsigned int  size = min_size;
-    if (format == 0)
-      size += Charset0::min_size + HBUINT16::static_size * (count - 1);
-    else if (format == 1)
-      size += Charset1::min_size + Charset1_Range::static_size * count;
-    else
-      size += Charset2::min_size + Charset2_Range::static_size * count;
-
-    return size;
+    switch (format)
+    {
+    case 0: return min_size + Charset0::min_size + HBUINT16::static_size * (count - 1);
+    case 1: return min_size + Charset1::min_size + Charset1_Range::static_size * count;
+    case 2: return min_size + Charset2::min_size + Charset2_Range::static_size * count;
+    default:return 0;
+    }
   }
 
   unsigned int get_size (unsigned int num_glyphs) const
   {
-    unsigned int size = min_size;
-    if (format == 0)
-      size += u.format0.get_size (num_glyphs);
-    else if (format == 1)
-      size += u.format1.get_size (num_glyphs);
-    else
-      size += u.format2.get_size (num_glyphs);
-    return size;
+    switch (format)
+    {
+    case 0: return min_size + u.format0.get_size (num_glyphs);
+    case 1: return min_size + u.format1.get_size (num_glyphs);
+    case 2: return min_size + u.format2.get_size (num_glyphs);
+    default:return 0;
+    }
   }
 
   hb_codepoint_t get_sid (hb_codepoint_t glyph) const
   {
-    if (format == 0)
-      return u.format0.get_sid (glyph);
-    else if (format == 1)
-      return u.format1.get_sid (glyph);
-    else
-      return u.format2.get_sid (glyph);
+    switch (format)
+    {
+    case 0: return u.format0.get_sid (glyph);
+    case 1: return u.format1.get_sid (glyph);
+    case 2: return u.format2.get_sid (glyph);
+    default:return 0;
+    }
   }
 
   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
   {
-    if (format == 0)
-      return u.format0.get_glyph (sid, num_glyphs);
-    else if (format == 1)
-      return u.format1.get_glyph (sid, num_glyphs);
-    else
-      return u.format2.get_glyph (sid, num_glyphs);
+    switch (format)
+    {
+    case 0: return u.format0.get_glyph (sid, num_glyphs);
+    case 1: return u.format1.get_glyph (sid, num_glyphs);
+    case 2: return u.format2.get_glyph (sid, num_glyphs);
+    default:return 0;
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+
+    switch (format)
+    {
+    case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
+    case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
+    case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
+    default:return_trace (false);
+    }
   }
 
   HBUINT8       format;
   union {
     Charset0    format0;
     Charset1    format1;
     Charset2    format2;
   } u;
 
   DEFINE_SIZE_MIN (1);
 };
 
 struct CFF1StringIndex : CFF1Index
 {
   bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
-		  unsigned int offSize_, const remap_t &sidmap)
+		  unsigned int offSize_, const hb_inc_bimap_t &sidmap)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely ((strings.count == 0) || (sidmap.get_count () == 0)))
+    if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0)))
     {
       if (unlikely (!c->extend_min (this->count)))
 	return_trace (false);
       count = 0;
       return_trace (true);
     }
 
     byte_str_array_t bytesArray;
     bytesArray.init ();
-    if (!bytesArray.resize (sidmap.get_count ()))
+    if (!bytesArray.resize (sidmap.get_population ()))
       return_trace (false);
     for (unsigned int i = 0; i < strings.count; i++)
     {
       hb_codepoint_t  j = sidmap[i];
       if (j != CFF_UNDEF_CODE)
 	bytesArray[j] = strings[i];
     }
 
     bool result = CFF1Index::serialize (c, offSize_, bytesArray);
     bytesArray.fini ();
     return_trace (result);
   }
 
   /* in parallel to above */
-  unsigned int calculate_serialized_size (unsigned int &offSize_ /*OUT*/, const remap_t &sidmap) const
+  unsigned int calculate_serialized_size (unsigned int &offSize_ /*OUT*/, const hb_inc_bimap_t &sidmap) const
   {
     offSize_ = 0;
-    if ((count == 0) || (sidmap.get_count () == 0))
+    if ((count == 0) || (sidmap.get_population () == 0))
       return count.static_size;
 
     unsigned int dataSize = 0;
     for (unsigned int i = 0; i < count; i++)
       if (sidmap[i] != CFF_UNDEF_CODE)
 	dataSize += length_at (i);
 
     offSize_ = calcOffSize(dataSize);
-    return CFF1Index::calculate_serialized_size (offSize_, sidmap.get_count (), dataSize);
+    return CFF1Index::calculate_serialized_size (offSize_, sidmap.get_population (), dataSize);
   }
 };
 
 struct cff1_top_dict_interp_env_t : num_interp_env_t
 {
   cff1_top_dict_interp_env_t ()
     : num_interp_env_t(), prev_offset(0), last_offset(0) {}
 
--- a/gfx/harfbuzz/src/hb-ot-cff2-table.cc
+++ b/gfx/harfbuzz/src/hb-ot-cff2-table.cc
@@ -19,21 +19,23 @@
  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Adobe Author(s): Michiharu Ariza
  */
 
+#include "hb.hh"
+
+#ifndef HB_NO_OT_FONT_CFF
+
 #include "hb-ot-cff2-table.hh"
 #include "hb-cff2-interp-cs.hh"
 
-#ifndef HB_NO_OT_FONT_CFF
-
 using namespace CFF;
 
 struct extents_param_t
 {
   void init ()
   {
     path_open = false;
     min_x.set_int (INT_MAX);
@@ -137,9 +139,10 @@ bool OT::cff2::accelerator_t::get_extent
   {
     extents->y_bearing = (int32_t)param.max_y.ceil ();
     extents->height = (int32_t)param.min_y.floor () - extents->y_bearing;
   }
 
   return true;
 }
 
+
 #endif
--- a/gfx/harfbuzz/src/hb-ot-cff2-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-cff2-table.hh
@@ -46,72 +46,76 @@ typedef CFF2Index         CFF2CharString
 typedef FDArray<HBUINT32> CFF2FDArray;
 typedef Subrs<HBUINT32>   CFF2Subrs;
 
 typedef FDSelect3_4<HBUINT32, HBUINT16> FDSelect4;
 typedef FDSelect3_4_Range<HBUINT32, HBUINT16> FDSelect4_Range;
 
 struct CFF2FDSelect
 {
-  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
-  {
-    TRACE_SANITIZE (this);
-
-    return_trace (likely (c->check_struct (this) && (format == 0 || format == 3 || format == 4) &&
-			  (format == 0)?
-			  u.format0.sanitize (c, fdcount):
-			    ((format == 3)?
-			    u.format3.sanitize (c, fdcount):
-			    u.format4.sanitize (c, fdcount))));
-  }
-
   bool serialize (hb_serialize_context_t *c, const CFF2FDSelect &src, unsigned int num_glyphs)
   {
     TRACE_SERIALIZE (this);
     unsigned int size = src.get_size (num_glyphs);
     CFF2FDSelect *dest = c->allocate_size<CFF2FDSelect> (size);
     if (unlikely (dest == nullptr)) return_trace (false);
     memcpy (dest, &src, size);
     return_trace (true);
   }
 
   unsigned int calculate_serialized_size (unsigned int num_glyphs) const
   { return get_size (num_glyphs); }
 
   unsigned int get_size (unsigned int num_glyphs) const
   {
-    unsigned int size = format.static_size;
-    if (format == 0)
-      size += u.format0.get_size (num_glyphs);
-    else if (format == 3)
-      size += u.format3.get_size ();
-    else
-      size += u.format4.get_size ();
-    return size;
+    switch (format)
+    {
+    case 0: return format.static_size + u.format0.get_size (num_glyphs);
+    case 3: return format.static_size + u.format3.get_size ();
+    case 4: return format.static_size + u.format4.get_size ();
+    default:return 0;
+    }
   }
 
   hb_codepoint_t get_fd (hb_codepoint_t glyph) const
   {
-    if (this == &Null(CFF2FDSelect))
+    if (this == &Null (CFF2FDSelect))
       return 0;
-    if (format == 0)
-      return u.format0.get_fd (glyph);
-    else if (format == 3)
-      return u.format3.get_fd (glyph);
-    else
-      return u.format4.get_fd (glyph);
+
+    switch (format)
+    {
+    case 0: return u.format0.get_fd (glyph);
+    case 3: return u.format3.get_fd (glyph);
+    case 4: return u.format4.get_fd (glyph);
+    default:return 0;
+    }
   }
 
-  HBUINT8       format;
+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+
+    switch (format)
+    {
+    case 0: return_trace (u.format0.sanitize (c, fdcount));
+    case 3: return_trace (u.format3.sanitize (c, fdcount));
+    case 4: return_trace (u.format4.sanitize (c, fdcount));
+    default:return_trace (false);
+    }
+  }
+
+  HBUINT8	format;
   union {
-    FDSelect0   format0;
-    FDSelect3   format3;
-    FDSelect4   format4;
+  FDSelect0	format0;
+  FDSelect3	format3;
+  FDSelect4	format4;
   } u;
-
+  public:
   DEFINE_SIZE_MIN (2);
 };
 
 struct CFF2VariationStore
 {
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
--- a/gfx/harfbuzz/src/hb-ot-cmap-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-cmap-table.hh
@@ -751,63 +751,71 @@ struct CmapSubtableFormat14
 struct CmapSubtable
 {
   /* Note: We intentionally do NOT implement subtable formats 2 and 8. */
 
   bool get_glyph (hb_codepoint_t codepoint,
 		  hb_codepoint_t *glyph) const
   {
     switch (u.format) {
+#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
     case  0: return u.format0 .get_glyph (codepoint, glyph);
-    case  4: return u.format4 .get_glyph (codepoint, glyph);
     case  6: return u.format6 .get_glyph (codepoint, glyph);
     case 10: return u.format10.get_glyph (codepoint, glyph);
+#endif
+    case  4: return u.format4 .get_glyph (codepoint, glyph);
     case 12: return u.format12.get_glyph (codepoint, glyph);
     case 13: return u.format13.get_glyph (codepoint, glyph);
     case 14:
     default: return false;
     }
   }
   void collect_unicodes (hb_set_t *out) const
   {
     switch (u.format) {
+#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
     case  0: u.format0 .collect_unicodes (out); return;
-    case  4: u.format4 .collect_unicodes (out); return;
     case  6: u.format6 .collect_unicodes (out); return;
     case 10: u.format10.collect_unicodes (out); return;
+#endif
+    case  4: u.format4 .collect_unicodes (out); return;
     case 12: u.format12.collect_unicodes (out); return;
     case 13: u.format13.collect_unicodes (out); return;
     case 14:
     default: return;
     }
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
     switch (u.format) {
+#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
     case  0: return_trace (u.format0 .sanitize (c));
-    case  4: return_trace (u.format4 .sanitize (c));
     case  6: return_trace (u.format6 .sanitize (c));
     case 10: return_trace (u.format10.sanitize (c));
+#endif
+    case  4: return_trace (u.format4 .sanitize (c));
     case 12: return_trace (u.format12.sanitize (c));
     case 13: return_trace (u.format13.sanitize (c));
     case 14: return_trace (u.format14.sanitize (c));
     default:return_trace (true);
     }
   }
 
   public:
   union {
   HBUINT16		format;		/* Format identifier */
+#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
   CmapSubtableFormat0	format0;
-  CmapSubtableFormat4	format4;
   CmapSubtableFormat6	format6;
   CmapSubtableFormat10	format10;
+#endif
+  CmapSubtableFormat4	format4;
   CmapSubtableFormat12	format12;
   CmapSubtableFormat13	format13;
   CmapSubtableFormat14	format14;
   } u;
   public:
   DEFINE_SIZE_UNION (2, format);
 };
 
@@ -843,28 +851,39 @@ struct cmap
 {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
 
   struct subset_plan
   {
     size_t final_size () const
     {
       return 4 // header
-	  +  8 * 3 // 3 EncodingRecord
+	  +  8 * num_enc_records
 	  +  CmapSubtableFormat4::get_sub_table_size (this->format4_segments)
 	  +  CmapSubtableFormat12::get_sub_table_size (this->format12_groups);
     }
 
+    unsigned int num_enc_records;
+    bool has_unicode_bmp;
+    bool has_unicode_ucs4;
+    bool has_ms_bmp;
+    bool has_ms_ucs4;
     hb_sorted_vector_t<CmapSubtableFormat4::segment_plan> format4_segments;
     hb_sorted_vector_t<CmapSubtableLongGroup> format12_groups;
   };
 
   bool _create_plan (const hb_subset_plan_t *plan,
 		     subset_plan *cmap_plan) const
   {
+    cmap_plan->has_unicode_bmp = find_subtable (0, 3);
+    cmap_plan->has_unicode_ucs4 = find_subtable (0, 4);
+    cmap_plan->has_ms_bmp = find_subtable (3, 1);
+    cmap_plan->has_ms_ucs4 = find_subtable (3, 10);
+    cmap_plan->num_enc_records = cmap_plan->has_unicode_bmp + cmap_plan->has_unicode_ucs4 + cmap_plan->has_ms_bmp + cmap_plan->has_ms_ucs4;
+  
     if (unlikely (!CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments)))
       return false;
 
     if (!find_subtable (12)) return true;
     return CmapSubtableFormat12::create_sub_table_plan (plan, &cmap_plan->format12_groups);
   }
 
   bool _subset (const hb_subset_plan_t *plan,
@@ -877,54 +896,88 @@ struct cmap
     cmap *table = c.start_serialize<cmap> ();
     if (unlikely (!c.extend_min (*table)))
     {
       return false;
     }
 
     table->version = 0;
 
-    if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ cmap_subset_plan.format12_groups ? 3 : 2))) return false;
+    if (unlikely (!table->encodingRecord.serialize (&c, cmap_subset_plan.num_enc_records))) return false;
 
     // TODO(grieger): Convert the below to a for loop
+    int enc_index = 0;
+    int unicode_bmp_index = 0;
+    int unicode_ucs4_index = 0;
+    int ms_bmp_index = 0;
+    int ms_ucs4_index = 0;
 
     // Format 4, Plat 0 Encoding Record
-    EncodingRecord &format4_plat0_rec = table->encodingRecord[0];
-    format4_plat0_rec.platformID = 0; // Unicode
-    format4_plat0_rec.encodingID = 3;
+    if (cmap_subset_plan.has_unicode_bmp)
+    {
+      unicode_bmp_index = enc_index;
+      EncodingRecord &format4_plat0_rec = table->encodingRecord[enc_index++];
+      format4_plat0_rec.platformID = 0; // Unicode
+      format4_plat0_rec.encodingID = 3;
+    }
+
+    // Format 12, Plat 0 Encoding Record
+    if (cmap_subset_plan.has_unicode_ucs4)
+    {
+      unicode_ucs4_index = enc_index;
+      EncodingRecord &format12_rec = table->encodingRecord[enc_index++];
+      format12_rec.platformID = 0; // Unicode
+      format12_rec.encodingID = 4; // Unicode UCS-4
+    }
 
     // Format 4, Plat 3 Encoding Record
-    EncodingRecord &format4_plat3_rec = table->encodingRecord[1];
-    format4_plat3_rec.platformID = 3; // Windows
-    format4_plat3_rec.encodingID = 1; // Unicode BMP
+    if (cmap_subset_plan.has_ms_bmp)
+    {
+      ms_bmp_index = enc_index;
+      EncodingRecord &format4_plat3_rec = table->encodingRecord[enc_index++];
+      format4_plat3_rec.platformID = 3; // Windows
+      format4_plat3_rec.encodingID = 1; // Unicode BMP
+    }
 
-    // Format 12 Encoding Record
-    if (cmap_subset_plan.format12_groups)
+    // Format 12, Plat 3 Encoding Record
+    if (cmap_subset_plan.has_ms_ucs4)
     {
-      EncodingRecord &format12_rec = table->encodingRecord[2];
+      ms_ucs4_index = enc_index;
+      EncodingRecord &format12_rec = table->encodingRecord[enc_index++];
       format12_rec.platformID = 3; // Windows
       format12_rec.encodingID = 10; // Unicode UCS-4
     }
 
     // Write out format 4 sub table
     {
-      CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, table);
-      format4_plat3_rec.subtable = (unsigned int) format4_plat0_rec.subtable;
+      if (unlikely (!cmap_subset_plan.has_unicode_bmp && !cmap_subset_plan.has_ms_bmp)) return false;
+      EncodingRecord &format4_rec = cmap_subset_plan.has_unicode_bmp?
+				     table->encodingRecord[unicode_bmp_index]:
+				     table->encodingRecord[ms_bmp_index];
+      CmapSubtable &subtable = format4_rec.subtable.serialize (&c, table);
+      if (cmap_subset_plan.has_unicode_bmp && cmap_subset_plan.has_ms_bmp)
+      	table->encodingRecord[ms_bmp_index].subtable = (unsigned int) format4_rec.subtable;
       subtable.u.format = 4;
 
       CmapSubtableFormat4 &format4 = subtable.u.format4;
       if (unlikely (!format4.serialize (&c, plan, cmap_subset_plan.format4_segments)))
 	return false;
     }
 
     // Write out format 12 sub table.
     if (cmap_subset_plan.format12_groups)
     {
-      EncodingRecord &format12_rec = table->encodingRecord[2];
+      if (unlikely (!cmap_subset_plan.has_unicode_ucs4 && !cmap_subset_plan.has_ms_ucs4)) return false;
+      EncodingRecord &format12_rec = cmap_subset_plan.has_unicode_ucs4?
+				     table->encodingRecord[unicode_ucs4_index]:
+				     table->encodingRecord[ms_ucs4_index];
+
       CmapSubtable &subtable = format12_rec.subtable.serialize (&c, table);
+      if (cmap_subset_plan.has_unicode_ucs4 && cmap_subset_plan.has_ms_ucs4)
+      	table->encodingRecord[ms_ucs4_index].subtable = (unsigned int) format12_rec.subtable;
       subtable.u.format = 12;
 
       CmapSubtableFormat12 &format12 = subtable.u.format12;
       if (unlikely (!format12.serialize (&c, cmap_subset_plan.format12_groups)))
 	return false;
     }
 
     c.end_serialize ();
--- a/gfx/harfbuzz/src/hb-ot-color.cc
+++ b/gfx/harfbuzz/src/hb-ot-color.cc
@@ -20,30 +20,31 @@
  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Google Author(s): Sascha Brawer, Behdad Esfahbod
  */
 
-#include "hb-open-type.hh"
+#include "hb.hh"
+
+#ifndef HB_NO_COLOR
+
+#include "hb-ot.h"
+
 #include "hb-ot-color-cbdt-table.hh"
 #include "hb-ot-color-colr-table.hh"
 #include "hb-ot-color-cpal-table.hh"
 #include "hb-ot-color-sbix-table.hh"
 #include "hb-ot-color-svg-table.hh"
-#include "hb-ot-face.hh"
-#include "hb-ot.h"
 
 #include <stdlib.h>
 #include <string.h>
 
-#include "hb-ot-layout.hh"
-
 
 /**
  * SECTION:hb-ot-color
  * @title: hb-ot-color
  * @short_description: OpenType Color Fonts
  * @include: hb-ot.h
  *
  * Functions for fetching color-font information from OpenType font faces.
@@ -65,38 +66,32 @@
  *
  * Return value: true if data found, false otherwise
  *
  * Since: 2.1.0
  */
 hb_bool_t
 hb_ot_color_has_palettes (hb_face_t *face)
 {
-#ifdef HB_NO_COLOR
-  return false;
-#endif
   return face->table.CPAL->has_data ();
 }
 
 /**
  * hb_ot_color_palette_get_count:
  * @face: #hb_face_t to work upon
  *
  * Fetches the number of color palettes in a face.
  *
  * Return value: the number of palettes found
  *
  * Since: 2.1.0
  */
 unsigned int
 hb_ot_color_palette_get_count (hb_face_t *face)
 {
-#ifdef HB_NO_COLOR
-  return 0;
-#endif
   return face->table.CPAL->get_palette_count ();
 }
 
 /**
  * hb_ot_color_palette_get_name_id:
  * @face: #hb_face_t to work upon
  * @palette_index: The index of the color palette 
  *
@@ -110,19 +105,16 @@ hb_ot_color_palette_get_count (hb_face_t
  * If the requested palette has no name the result is #HB_OT_NAME_ID_INVALID.
  *
  * Since: 2.1.0
  */
 hb_ot_name_id_t
 hb_ot_color_palette_get_name_id (hb_face_t *face,
 				 unsigned int palette_index)
 {
-#ifdef HB_NO_COLOR
-  return HB_OT_NAME_ID_INVALID;
-#endif
   return face->table.CPAL->get_palette_name_id (palette_index);
 }
 
 /**
  * hb_ot_color_palette_color_get_name_id:
  * @face: #hb_face_t to work upon
  * @color_index: The index of the color
  *
@@ -135,19 +127,16 @@ hb_ot_color_palette_get_name_id (hb_face
  * Return value: the Name ID found for the color.
  *
  * Since: 2.1.0
  */
 hb_ot_name_id_t
 hb_ot_color_palette_color_get_name_id (hb_face_t *face,
 				       unsigned int color_index)
 {
-#ifdef HB_NO_COLOR
-  return HB_OT_NAME_ID_INVALID;
-#endif
   return face->table.CPAL->get_color_name_id (color_index);
 }
 
 /**
  * hb_ot_color_palette_get_flags:
  * @face: #hb_face_t to work upon
  * @palette_index: The index of the color palette
  *
@@ -156,19 +145,16 @@ hb_ot_color_palette_color_get_name_id (h
  * Return value: the #hb_ot_color_palette_flags_t of the requested color palette
  *
  * Since: 2.1.0
  */
 hb_ot_color_palette_flags_t
 hb_ot_color_palette_get_flags (hb_face_t *face,
 			       unsigned int palette_index)
 {
-#ifdef HB_NO_COLOR
-  return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
-#endif
   return face->table.CPAL->get_palette_flags (palette_index);
 }
 
 /**
  * hb_ot_color_palette_get_colors:
  * @face: #hb_face_t to work upon
  * @palette_index: the index of the color palette to query
  * @start_offset: offset of the first color to retrieve
@@ -190,21 +176,16 @@ hb_ot_color_palette_get_flags (hb_face_t
  */
 unsigned int
 hb_ot_color_palette_get_colors (hb_face_t     *face,
 				unsigned int   palette_index,
 				unsigned int   start_offset,
 				unsigned int  *colors_count  /* IN/OUT.  May be NULL. */,
 				hb_color_t    *colors        /* OUT.     May be NULL. */)
 {
-#ifdef HB_NO_COLOR
-  if (colors_count)
-    *colors_count = 0;
-  return 0;
-#endif
   return face->table.CPAL->get_palette_colors (palette_index, start_offset, colors_count, colors);
 }
 
 
 /*
  * COLR
  */
 
@@ -216,19 +197,16 @@ hb_ot_color_palette_get_colors (hb_face_
  *
  * Return value: true if data found, false otherwise
  *
  * Since: 2.1.0
  */
 hb_bool_t
 hb_ot_color_has_layers (hb_face_t *face)
 {
-#ifdef HB_NO_COLOR
-  return false;
-#endif
   return face->table.COLR->has_data ();
 }
 
 /**
  * hb_ot_color_glyph_get_layers:
  * @face: #hb_face_t to work upon
  * @glyph: The glyph index to query
  * @start_offset: offset of the first layer to retrieve
@@ -245,21 +223,16 @@ hb_ot_color_has_layers (hb_face_t *face)
  */
 unsigned int
 hb_ot_color_glyph_get_layers (hb_face_t           *face,
 			      hb_codepoint_t       glyph,
 			      unsigned int         start_offset,
 			      unsigned int        *layer_count, /* IN/OUT.  May be NULL. */
 			      hb_ot_color_layer_t *layers /* OUT.     May be NULL. */)
 {
-#ifdef HB_NO_COLOR
-  if (layer_count)
-    *layer_count = 0;
-  return 0;
-#endif
   return face->table.COLR->get_glyph_layers (glyph, start_offset, layer_count, layers);
 }
 
 
 /*
  * SVG
  */
 
@@ -271,19 +244,16 @@ hb_ot_color_glyph_get_layers (hb_face_t 
  *
  * Return value: true if data found, false otherwise.
  *
  * Since: 2.1.0
  */
 hb_bool_t
 hb_ot_color_has_svg (hb_face_t *face)
 {
-#ifdef HB_NO_COLOR
-  return false;
-#endif
   return face->table.SVG->has_data ();
 }
 
 /**
  * hb_ot_color_glyph_reference_svg:
  * @face: #hb_face_t to work upon
  * @glyph: a svg glyph index
  *
@@ -291,19 +261,16 @@ hb_ot_color_has_svg (hb_face_t *face)
  *
  * Return value: (transfer full): An #hb_blob_t containing the SVG document of the glyph, if available
  *
  * Since: 2.1.0
  */
 hb_blob_t *
 hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph)
 {
-#ifdef HB_NO_COLOR
-  return hb_blob_get_empty ();
-#endif
   return face->table.SVG->reference_blob_for_glyph (glyph);
 }
 
 
 /*
  * PNG: CBDT or sbix
  */
 
@@ -315,19 +282,16 @@ hb_ot_color_glyph_reference_svg (hb_face
  *
  * Return value: true if data found, false otherwise
  *
  * Since: 2.1.0
  */
 hb_bool_t
 hb_ot_color_has_png (hb_face_t *face)
 {
-#ifdef HB_NO_COLOR
-  return false;
-#endif
   return face->table.CBDT->has_data () || face->table.sbix->has_data ();
 }
 
 /**
  * hb_ot_color_glyph_reference_png:
  * @font: #hb_font_t to work upon
  * @glyph: a glyph index
  *
@@ -337,22 +301,21 @@ hb_ot_color_has_png (hb_face_t *face)
  *
  * Return value: (transfer full): An #hb_blob_t containing the PNG image for the glyph, if available
  *
  * Since: 2.1.0
  */
 hb_blob_t *
 hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t  glyph)
 {
-#ifdef HB_NO_COLOR
-  return hb_blob_get_empty ();
-#endif
-
   hb_blob_t *blob = hb_blob_get_empty ();
 
   if (font->face->table.sbix->has_data ())
     blob = font->face->table.sbix->reference_png (font, glyph, nullptr, nullptr, nullptr);
 
   if (!blob->length && font->face->table.CBDT->has_data ())
     blob = font->face->table.CBDT->reference_png (font, glyph);
 
   return blob;
 }
+
+
+#endif
new file mode 100644
--- /dev/null
+++ b/gfx/harfbuzz/src/hb-ot-face-table-list.hh
@@ -0,0 +1,126 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2012,2013  Google, Inc.
+ * Copyright © 2019, Facebook Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ * Facebook Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_FACE_TABLE_LIST_HH
+#define HB_OT_FACE_TABLE_LIST_HH
+#endif /* HB_OT_FACE_TABLE_LIST_HH */ /* Dummy header guards */
+
+#ifndef HB_OT_ACCELERATOR
+#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
+#define _HB_OT_ACCELERATOR_UNDEF
+#endif
+
+
+/* This lists font tables that the hb_face_t will contain and lazily
+ * load.  Don't add a table unless it's used though.  This is not
+ * exactly free. */
+
+/* v--- Add new tables in the right place here. */
+
+
+/* OpenType fundamentals. */
+HB_OT_TABLE (OT, head)
+#if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT)
+HB_OT_ACCELERATOR (OT, cmap)
+#endif
+HB_OT_ACCELERATOR (OT, hmtx)
+HB_OT_TABLE (OT, OS2)
+#ifndef HB_NO_OT_FONT_GLYPH_NAMES
+HB_OT_ACCELERATOR (OT, post)
+#endif
+#ifndef HB_NO_NAME
+HB_OT_ACCELERATOR (OT, name)
+#endif
+#ifndef HB_NO_STAT
+HB_OT_TABLE (OT, STAT)
+#endif
+
+/* Vertical layout. */
+HB_OT_ACCELERATOR (OT, vmtx)
+
+/* TrueType outlines. */
+HB_OT_ACCELERATOR (OT, glyf)
+
+/* CFF outlines. */
+#ifndef HB_NO_CFF
+HB_OT_ACCELERATOR (OT, cff1)
+HB_OT_ACCELERATOR (OT, cff2)
+HB_OT_TABLE (OT, VORG)
+#endif
+
+/* OpenType variations. */
+#ifndef HB_NO_VAR
+HB_OT_TABLE (OT, fvar)
+HB_OT_TABLE (OT, avar)
+HB_OT_TABLE (OT, MVAR)
+#endif
+
+/* Legacy kern. */
+#ifndef HB_NO_OT_KERN
+HB_OT_TABLE (OT, kern)
+#endif
+
+/* OpenType shaping. */
+HB_OT_ACCELERATOR (OT, GDEF)
+HB_OT_ACCELERATOR (OT, GSUB)
+HB_OT_ACCELERATOR (OT, GPOS)
+//HB_OT_TABLE (OT, BASE)
+//HB_OT_TABLE (OT, JSTF)
+
+/* AAT shaping. */
+#ifndef HB_NO_AAT
+HB_OT_TABLE (AAT, morx)
+HB_OT_TABLE (AAT, mort)
+HB_OT_TABLE (AAT, kerx)
+HB_OT_TABLE (AAT, ankr)
+HB_OT_TABLE (AAT, trak)
+HB_OT_TABLE (AAT, lcar)
+HB_OT_TABLE (AAT, ltag)
+HB_OT_TABLE (AAT, feat)
+#endif
+
+/* OpenType color fonts. */
+#ifndef HB_NO_COLOR
+HB_OT_TABLE (OT, COLR)
+HB_OT_TABLE (OT, CPAL)
+HB_OT_ACCELERATOR (OT, CBDT)
+HB_OT_ACCELERATOR (OT, sbix)
+HB_OT_ACCELERATOR (OT, SVG)
+#endif
+
+/* OpenType math. */
+#ifndef HB_NO_MATH
+HB_OT_TABLE (OT, MATH)
+#endif
+
+
+#ifdef _HB_OT_ACCELERATOR_UNDEF
+#undef HB_OT_ACCELERATOR
+#endif
--- a/gfx/harfbuzz/src/hb-ot-face.cc
+++ b/gfx/harfbuzz/src/hb-ot-face.cc
@@ -41,21 +41,17 @@
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
 
 
 void hb_ot_face_t::init0 (hb_face_t *face)
 {
   this->face = face;
 #define HB_OT_TABLE(Namespace, Type) Type.init0 ();
-#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
-  HB_OT_TABLES
-#undef HB_OT_ACCELERATOR
+#include "hb-ot-face-table-list.hh"
 #undef HB_OT_TABLE
 }
 void hb_ot_face_t::fini ()
 {
 #define HB_OT_TABLE(Namespace, Type) Type.fini ();
-#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
-  HB_OT_TABLES
-#undef HB_OT_ACCELERATOR
+#include "hb-ot-face-table-list.hh"
 #undef HB_OT_TABLE
 }
--- a/gfx/harfbuzz/src/hb-ot-face.hh
+++ b/gfx/harfbuzz/src/hb-ot-face.hh
@@ -33,88 +33,42 @@
 
 #include "hb-machinery.hh"
 
 
 /*
  * hb_ot_face_t
  */
 
-#define HB_OT_TABLES \
-    /* OpenType fundamentals. */ \
-    HB_OT_TABLE(OT, head) \
-    HB_OT_ACCELERATOR(OT, cmap) \
-    HB_OT_ACCELERATOR(OT, hmtx) \
-    HB_OT_ACCELERATOR(OT, vmtx) \
-    HB_OT_ACCELERATOR(OT, post) \
-    HB_OT_TABLE(OT, kern) \
-    HB_OT_ACCELERATOR(OT, glyf) \
-    HB_OT_ACCELERATOR(OT, cff1) \
-    HB_OT_ACCELERATOR(OT, cff2) \
-    HB_OT_TABLE(OT, VORG) \
-    HB_OT_ACCELERATOR(OT, name) \
-    HB_OT_TABLE(OT, OS2) \
-    HB_OT_TABLE(OT, STAT) \
-    /* OpenType shaping. */ \
-    HB_OT_ACCELERATOR(OT, GDEF) \
-    HB_OT_ACCELERATOR(OT, GSUB) \
-    HB_OT_ACCELERATOR(OT, GPOS) \
-    HB_OT_TABLE(OT, BASE) \
-    HB_OT_TABLE(OT, JSTF) \
-    /* AAT shaping. */ \
-    HB_OT_TABLE(AAT, mort) \
-    HB_OT_TABLE(AAT, morx) \
-    HB_OT_TABLE(AAT, kerx) \
-    HB_OT_TABLE(AAT, ankr) \
-    HB_OT_TABLE(AAT, trak) \
-    HB_OT_TABLE(AAT, lcar) \
-    HB_OT_TABLE(AAT, ltag) \
-    HB_OT_TABLE(AAT, feat) \
-    /* OpenType variations. */ \
-    HB_OT_TABLE(OT, fvar) \
-    HB_OT_TABLE(OT, avar) \
-    HB_OT_TABLE(OT, MVAR) \
-    /* OpenType math. */ \
-    HB_OT_TABLE(OT, MATH) \
-    /* OpenType color fonts. */ \
-    HB_OT_TABLE(OT, COLR) \
-    HB_OT_TABLE(OT, CPAL) \
-    HB_OT_ACCELERATOR(OT, CBDT) \
-    HB_OT_ACCELERATOR(OT, sbix) \
-    HB_OT_ACCELERATOR(OT, SVG) \
-    /* */
-
 /* Declare tables. */
 #define HB_OT_TABLE(Namespace, Type) namespace Namespace { struct Type; }
 #define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type##_accelerator_t)
-HB_OT_TABLES
+#include "hb-ot-face-table-list.hh"
 #undef HB_OT_ACCELERATOR
 #undef HB_OT_TABLE
 
 struct hb_ot_face_t
 {
   HB_INTERNAL void init0 (hb_face_t *face);
   HB_INTERNAL void fini ();
 
 #define HB_OT_TABLE_ORDER(Namespace, Type) \
     HB_PASTE (ORDER_, HB_PASTE (Namespace, HB_PASTE (_, Type)))
   enum order_t
   {
     ORDER_ZERO,
 #define HB_OT_TABLE(Namespace, Type) HB_OT_TABLE_ORDER (Namespace, Type),
-#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
-    HB_OT_TABLES
-#undef HB_OT_ACCELERATOR
+#include "hb-ot-face-table-list.hh"
 #undef HB_OT_TABLE
   };
 
   hb_face_t *face; /* MUST be JUST before the lazy loaders. */
 #define HB_OT_TABLE(Namespace, Type) \
   hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
 #define HB_OT_ACCELERATOR(Namespace, Type) \
   hb_face_lazy_loader_t<Namespace::Type##_accelerator_t, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
-  HB_OT_TABLES
+#include "hb-ot-face-table-list.hh"
 #undef HB_OT_ACCELERATOR
 #undef HB_OT_TABLE
 };
 
 
 #endif /* HB_OT_FACE_HH */
--- a/gfx/harfbuzz/src/hb-ot-font.cc
+++ b/gfx/harfbuzz/src/hb-ot-font.cc
@@ -21,28 +21,29 @@
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
  */
 
 #include "hb.hh"
 
+#ifndef HB_NO_OT_FONT
+
 #include "hb-ot.h"
 
 #include "hb-font.hh"
 #include "hb-machinery.hh"
 #include "hb-ot-face.hh"
 
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-glyf-table.hh"
 #include "hb-ot-cff1-table.hh"
 #include "hb-ot-cff2-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-stat-table.hh" // Just so we compile it; unused otherwise.
 #include "hb-ot-vorg-table.hh"
 #include "hb-ot-color-cbdt-table.hh"
 #include "hb-ot-color-sbix-table.hh"
 
 
@@ -144,22 +145,24 @@ hb_ot_get_glyph_v_origin (hb_font_t *fon
 			  hb_position_t *x,
 			  hb_position_t *y,
 			  void *user_data HB_UNUSED)
 {
   const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
 
   *x = font->get_glyph_h_advance (glyph) / 2;
 
+#ifndef HB_NO_OT_FONT_CFF
   const OT::VORG &VORG = *ot_face->VORG;
   if (VORG.has_data ())
   {
     *y = font->em_scale_y (VORG.get_y_origin (glyph));
     return true;
   }
+#endif
 
   hb_glyph_extents_t extents = {0};
   if (ot_face->glyf->get_extents (glyph, &extents))
   {
     const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
     hb_position_t tsb = vmtx.get_side_bearing (glyph);
     *y = font->em_scale_y (extents.y_bearing + tsb);
     return true;
@@ -197,37 +200,38 @@ hb_ot_get_glyph_extents (hb_font_t *font
   // TODO Hook up side-bearings variations.
   extents->x_bearing = font->em_scale_x (extents->x_bearing);
   extents->y_bearing = font->em_scale_y (extents->y_bearing);
   extents->width     = font->em_scale_x (extents->width);
   extents->height    = font->em_scale_y (extents->height);
   return ret;
 }
 
+#ifndef HB_NO_OT_FONT_GLYPH_NAMES
 static hb_bool_t
 hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
                       void *font_data,
                       hb_codepoint_t glyph,
                       char *name, unsigned int size,
                       void *user_data HB_UNUSED)
 {
   const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
   return ot_face->post->get_glyph_name (glyph, name, size);
 }
-
 static hb_bool_t
 hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
                            void *font_data,
                            const char *name, int len,
                            hb_codepoint_t *glyph,
                            void *user_data HB_UNUSED)
 {
   const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
   return ot_face->post->get_glyph_from_name (name, len, glyph);
 }
+#endif
 
 static hb_bool_t
 hb_ot_get_font_h_extents (hb_font_t *font,
 			  void *font_data,
 			  hb_font_extents_t *metrics,
 			  void *user_data HB_UNUSED)
 {
   const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
@@ -270,18 +274,20 @@ static struct hb_ot_font_funcs_lazy_load
     hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr);
     hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
     hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
     hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, 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_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);
+#ifndef HB_NO_OT_FONT_GLYPH_NAMES
     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);
+#endif
 
     hb_font_funcs_make_immutable (funcs);
 
 #if HB_USE_ATEXIT
     atexit (free_static_ot_funcs);
 #endif
 
     return funcs;
@@ -311,8 +317,11 @@ static hb_font_funcs_t *
 void
 hb_ot_font_set_funcs (hb_font_t *font)
 {
   hb_font_set_funcs (font,
 		     _hb_ot_get_font_funcs (),
 		     &font->face->table,
 		     nullptr);
 }
+
+
+#endif
--- a/gfx/harfbuzz/src/hb-ot-glyf-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-glyf-table.hh
@@ -175,17 +175,17 @@ struct glyf
   _populate_subset_glyphs (const hb_subset_plan_t * plan,
 			   hb_vector_t<SubsetGlyph> * glyphs /* OUT */) const
   {
     OT::glyf::accelerator_t glyf;
     glyf.init (plan->source);
 
     + hb_range (plan->num_output_glyphs ())
     | hb_map ([&] (hb_codepoint_t new_gid) {
-      SubsetGlyph subset_glyph;
+      SubsetGlyph subset_glyph = {0};
       subset_glyph.new_gid = new_gid;
 
       // should never fail: all old gids should be mapped
       if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid)) return subset_glyph;
 
       subset_glyph.source_glyph = glyf.bytes_for_glyph ((const char *) this, subset_glyph.old_gid);
       if (plan->drop_hints) subset_glyph.drop_hints (glyf);
       else subset_glyph.dest_start = subset_glyph.source_glyph;
--- a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
@@ -81,84 +81,81 @@ struct hmtxvmtx
     table->numberOfLongMetrics = num_hmetrics;
 
     bool result = plan->add_table (H::tableTag, dest_blob);
     hb_blob_destroy (dest_blob);
 
     return result;
   }
 
-  bool subset (hb_subset_plan_t *plan) const
+  template<typename Iterator,
+           hb_requires (hb_is_iterator (Iterator))>
+  void serialize (hb_serialize_context_t *c, 
+                  Iterator it, 
+                  unsigned num_advances)
   {
-    typename T::accelerator_t _mtx;
-    _mtx.init (plan->source);
-
-    /* All the trailing glyphs with the same advance can use one LongMetric
-     * and just keep LSB */
-    unsigned int num_output_glyphs = plan->num_output_glyphs ();
-    unsigned int num_advances = _mtx.num_advances_for_subset (plan);
-
-    /* alloc the new table */
-    size_t dest_sz = num_advances * 4
-		  + (num_output_glyphs - num_advances) * 2;
-    void *dest = (void *) malloc (dest_sz);
-    if (unlikely (!dest))
-    {
-      return false;
-    }
-    DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in src has %d advances, %d lsbs", HB_UNTAG(T::tableTag), _mtx.num_advances, _mtx.num_metrics - _mtx.num_advances);
-    DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes",
-              HB_UNTAG(T::tableTag), num_advances, num_output_glyphs - num_advances, (unsigned int) dest_sz);
-
-    // Copy everything over
-    char * dest_pos = (char *) dest;
+    unsigned idx = 0;
+    + it
+    | hb_apply ([c, &idx, num_advances] (const hb_item_type<Iterator>& _)
+                {
+                  if (idx < num_advances) 
+                  {
+                    LongMetric lm;
+                    lm.advance = _.first;
+                    lm.sb = _.second;
+                    if (unlikely (!c->embed<LongMetric> (&lm))) return;
+                  } 
+                  else 
+                  {
+                    FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size);
+                    if (unlikely (!sb)) return;
+                    *sb = _.second;
+                  }
+                  idx++;
+                })
+    ;
+  }
 
-    bool failed = false;
-    for (unsigned int i = 0; i < num_output_glyphs; i++)
-    {
-      unsigned int side_bearing = 0;
-      unsigned int advance = 0;
-      hb_codepoint_t old_gid;
-      if (plan->old_gid_for_new_gid (i, &old_gid))
-      {
-        // Glyph is not an empty glyph so copy advance and side bearing
-        // from the input font.
-        side_bearing = _mtx.get_side_bearing (old_gid);
-        advance = _mtx.get_advance (old_gid);
-      }
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
 
-      bool has_advance = i < num_advances;
-      if (has_advance)
-      {
-        ((LongMetric *) dest_pos)->advance = advance;
-        ((LongMetric *) dest_pos)->sb = side_bearing;
-      }
-      else
-      {
-        *((FWORD *) dest_pos) = side_bearing;
-      }
-      dest_pos += (has_advance ? 4 : 2);
-    }
+    T *table_prime = c->serializer->start_embed <T> ();
+    if (unlikely (!table_prime)) return_trace (false);
+    
+    accelerator_t _mtx;
+    _mtx.init (c->plan->source);
+    unsigned num_advances = _mtx.num_advances_for_subset (c->plan);
+    
+    auto it = 
+    + hb_range (c->plan->num_output_glyphs ())
+    | hb_map ([c, &_mtx] (unsigned _)
+	{
+	  hb_codepoint_t old_gid;
+	  if (c->plan->old_gid_for_new_gid (_, &old_gid))
+            return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid));
+          else
+	    return hb_pair (0u, 0u);
+	})
+    ;
+
+    table_prime->serialize (c->serializer, it, num_advances);
+
     _mtx.fini ();
 
+    if (unlikely (c->serializer->ran_out_of_room || c->serializer->in_error ()))
+      return_trace (false);
+
     // Amend header num hmetrics
-    if (failed || unlikely (!subset_update_header (plan, num_advances)))
+    if (unlikely (!subset_update_header (c->plan, num_advances)))
     {
-      free (dest);
-      return false;
+      return_trace (false);
     }
 
-    hb_blob_t *result = hb_blob_create ((const char *)dest,
-                                        dest_sz,
-                                        HB_MEMORY_MODE_READONLY,
-                                        dest,
-                                        free);
-    bool success = plan->add_table (T::tableTag, result);
-    hb_blob_destroy (result);
-    return success;
+    return_trace (true);
   }
 
   struct accelerator_t
   {
     friend struct hmtxvmtx;
 
     void init (hb_face_t *face,
                unsigned int default_advance_ = 0)
--- a/gfx/harfbuzz/src/hb-ot-layout-common.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-common.hh
@@ -494,46 +494,49 @@ struct FeatureParamsCharacterVariants
   public:
   DEFINE_SIZE_ARRAY (14, characters);
 };
 
 struct FeatureParams
 {
   bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
   {
+#ifdef HB_NO_LAYOUT_FEATURE_PARAMS
+    return true;
+#endif
     TRACE_SANITIZE (this);
     if (tag == HB_TAG ('s','i','z','e'))
       return_trace (u.size.sanitize (c));
     if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
       return_trace (u.stylisticSet.sanitize (c));
     if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
       return_trace (u.characterVariants.sanitize (c));
     return_trace (true);
   }
 
+#ifndef HB_NO_LAYOUT_FEATURE_PARAMS
   const FeatureParamsSize& get_size_params (hb_tag_t tag) const
   {
     if (tag == HB_TAG ('s','i','z','e'))
       return u.size;
     return Null (FeatureParamsSize);
   }
-
   const FeatureParamsStylisticSet& get_stylistic_set_params (hb_tag_t tag) const
   {
     if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
       return u.stylisticSet;
     return Null (FeatureParamsStylisticSet);
   }
-
   const FeatureParamsCharacterVariants& get_character_variants_params (hb_tag_t tag) const
   {
     if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
       return u.characterVariants;
     return Null (FeatureParamsCharacterVariants);
   }
+#endif
 
   private:
   union {
   FeatureParamsSize			size;
   FeatureParamsStylisticSet		stylisticSet;
   FeatureParamsCharacterVariants	characterVariants;
   } u;
   public:
@@ -1742,21 +1745,21 @@ struct VarData
    return delta;
   }
 
   void get_scalars (int *coords, unsigned int coord_count,
                     const VarRegionList &regions,
                     float *scalars /*OUT */,
                     unsigned int num_scalars) const
   {
-    assert (num_scalars == regionIndices.len);
-   for (unsigned int i = 0; i < num_scalars; i++)
-   {
-     scalars[i] = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
-   }
+    unsigned count = hb_min (num_scalars, regionIndices.len);
+    for (unsigned int i = 0; i < count; i++)
+      scalars[i] = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+    for (unsigned int i = count; i < num_scalars; i++)
+      scalars[i] = 0.f;
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  regionIndices.sanitize (c) &&
 		  shortCount <= regionIndices.len &&
@@ -1774,49 +1777,63 @@ struct VarData
   DEFINE_SIZE_ARRAY (6, regionIndices);
 };
 
 struct VariationStore
 {
   float get_delta (unsigned int outer, unsigned int inner,
 		   const int *coords, unsigned int coord_count) const
   {
+#ifdef HB_NO_VAR
+    return 0.f;
+#endif
+
     if (unlikely (outer >= dataSets.len))
-      return 0.;
+      return 0.f;
 
     return (this+dataSets[outer]).get_delta (inner,
 					     coords, coord_count,
 					     this+regions);
   }
 
   float get_delta (unsigned int index,
 		   const int *coords, unsigned int coord_count) const
   {
     unsigned int outer = index >> 16;
     unsigned int inner = index & 0xFFFF;
     return get_delta (outer, inner, coords, coord_count);
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
+#ifdef HB_NO_VAR
+    return true;
+#endif
+
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  format == 1 &&
 		  regions.sanitize (c, this) &&
 		  dataSets.sanitize (c, this));
   }
 
   unsigned int get_region_index_count (unsigned int ivs) const
   { return (this+dataSets[ivs]).get_region_index_count (); }
 
   void get_scalars (unsigned int ivs,
 		    int *coords, unsigned int coord_count,
 		    float *scalars /*OUT*/,
 		    unsigned int num_scalars) const
   {
+#ifdef HB_NO_VAR
+    for (unsigned i = 0; i < num_scalars; i++)
+      scalars[i] = 0.f;
+    return;
+#endif
+
     (this+dataSets[ivs]).get_scalars (coords, coord_count, this+regions,
                                       &scalars[0], num_scalars);
   }
 
   protected:
   HBUINT16				format;
   LOffsetTo<VarRegionList>		regions;
   LOffsetArrayOf<VarData>		dataSets;
@@ -2147,56 +2164,70 @@ struct DeviceHeader
 };
 
 struct Device
 {
   hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
   {
     switch (u.b.format)
     {
+#ifndef HB_NO_HINTING
     case 1: case 2: case 3:
       return u.hinting.get_x_delta (font);
+#endif
+#ifndef HB_NO_VAR
     case 0x8000:
       return u.variation.get_x_delta (font, store);
+#endif
     default:
       return 0;
     }
   }
   hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
   {
     switch (u.b.format)
     {
     case 1: case 2: case 3:
+#ifndef HB_NO_HINTING
       return u.hinting.get_y_delta (font);
+#endif
+#ifndef HB_NO_VAR
     case 0x8000:
       return u.variation.get_y_delta (font, store);
+#endif
     default:
       return 0;
     }
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.b.format.sanitize (c)) return_trace (false);
     switch (u.b.format) {
+#ifndef HB_NO_HINTING
     case 1: case 2: case 3:
       return_trace (u.hinting.sanitize (c));
+#endif
+#ifndef HB_NO_VAR
     case 0x8000:
       return_trace (u.variation.sanitize (c));
+#endif
     default:
       return_trace (true);
     }
   }
 
   protected:
   union {
   DeviceHeader		b;
   HintingDevice		hinting;
+#ifndef HB_NO_VAR
   VariationDevice	variation;
+#endif
   } u;
   public:
   DEFINE_SIZE_UNION (6, b);
 };
 
 
 } /* namespace OT */
 
--- a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
@@ -262,16 +262,23 @@ struct AnchorFormat1
 };
 
 struct AnchorFormat2
 {
   void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
 		   float *x, float *y) const
   {
     hb_font_t *font = c->font;
+
+#ifdef HB_NO_HINTING
+    *x = font->em_fscale_x (xCoordinate);
+    *y = font->em_fscale_y (yCoordinate);
+    return;
+#endif
+
     unsigned int x_ppem = font->x_ppem;
     unsigned int y_ppem = font->y_ppem;
     hb_position_t cx = 0, cy = 0;
     bool ret;
 
     ret = (x_ppem || y_ppem) &&
 	  font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
     *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
--- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh
@@ -2656,29 +2656,36 @@ struct GSUBGPOS
 
   unsigned int get_lookup_count () const
   { return (this+lookupList).len; }
   const Lookup& get_lookup (unsigned int i) const
   { return (this+lookupList)[i]; }
 
   bool find_variations_index (const int *coords, unsigned int num_coords,
 			      unsigned int *index) const
-  { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
-	   .find_index (coords, num_coords, index); }
+  {
+#ifdef HB_NOVAR
+    return false;
+#endif
+    return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
+	    .find_index (coords, num_coords, index);
+  }
   const Feature& get_feature_variation (unsigned int feature_index,
 					unsigned int variations_index) const
   {
+#ifndef HB_NO_VAR
     if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
 	version.to_int () >= 0x00010001u)
     {
       const Feature *feature = (this+featureVars).find_substitute (variations_index,
 								   feature_index);
       if (feature)
 	return *feature;
     }
+#endif
     return get_feature (feature_index);
   }
 
   template <typename TLookup>
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->embed (*this);
@@ -2690,39 +2697,48 @@ struct GSUBGPOS
     typedef OffsetListOf<TLookup> TLookupList;
     /* TODO Use intersects() to count how many subtables survive? */
     CastR<OffsetTo<TLookupList>> (out->lookupList)
       .serialize_subset (c,
 			 CastR<OffsetTo<TLookupList>> (lookupList),
 			 this,
 			 out);
 
+#ifndef HB_NO_VAR
     if (version.to_int () >= 0x00010001u)
      out->featureVars.serialize_copy (c->serializer, featureVars, this, out);
+#endif
 
     return_trace (true);
   }
 
   unsigned int get_size () const
   {
     return min_size +
 	   (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
   }
 
   template <typename TLookup>
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     typedef OffsetListOf<TLookup> TLookupList;
-    return_trace (version.sanitize (c) &&
-		  likely (version.major == 1) &&
-		  scriptList.sanitize (c, this) &&
-		  featureList.sanitize (c, this) &&
-		  CastR<OffsetTo<TLookupList>> (lookupList).sanitize (c, this) &&
-		  (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
+    if (unlikely (!(version.sanitize (c) &&
+		    likely (version.major == 1) &&
+		    scriptList.sanitize (c, this) &&
+		    featureList.sanitize (c, this) &&
+		    CastR<OffsetTo<TLookupList>> (lookupList).sanitize (c, this))))
+      return_trace (false);
+
+#ifndef HB_NO_VAR
+    if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
+      return_trace (false);
+#endif
+
+    return_trace (true);
   }
 
   template <typename T>
   struct accelerator_t
   {
     void init (hb_face_t *face)
     {
       this->table = hb_sanitize_context_t().reference_table<T> (face);
--- a/gfx/harfbuzz/src/hb-ot-layout.cc
+++ b/gfx/harfbuzz/src/hb-ot-layout.cc
@@ -57,50 +57,49 @@
  * Functions for querying OpenType Layout features in the font face.
  **/
 
 
 /*
  * kern
  */
 
+#ifndef HB_NO_OT_KERN
 /**
  * hb_ot_layout_has_kerning:
  * @face: The #hb_face_t to work on
  *
  * Tests whether a face includes any kerning data in the 'kern' table.
  * Does NOT test for kerning lookups in the GPOS table.
  *
  * Return value: true if data found, false otherwise
  *
  **/
 bool
 hb_ot_layout_has_kerning (hb_face_t *face)
 {
   return face->table.kern->has_data ();
 }
 
-
 /**
  * hb_ot_layout_has_machine_kerning:
  * @face: The #hb_face_t to work on
  *
  * Tests whether a face includes any state-machine kerning in the 'kern' table.
  * Does NOT examine the GPOS table.
  *
  * Return value: true if data found, false otherwise
  *
  **/
 bool
 hb_ot_layout_has_machine_kerning (hb_face_t *face)
 {
   return face->table.kern->has_state_machine ();
 }
 
-
 /**
  * hb_ot_layout_has_cross_kerning:
  * @face: The #hb_face_t to work on
  *
  * Tests whether a face has any cross-stream kerning (i.e., kerns
  * that make adjustments perpendicular to the direction of the text
  * flow: Y adjustments in horizontal text or X adjustments in 
  * vertical text) in the 'kern' table.
@@ -123,16 +122,17 @@ hb_ot_layout_kern (const hb_ot_shape_pla
 {
   hb_blob_t *blob = font->face->table.kern.get_blob ();
   const AAT::kern& kern = *blob->as<AAT::kern> ();
 
   AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
 
   kern.apply (&c);
 }
+#endif
 
 
 /*
  * GDEF
  */
 
 bool
 OT::GDEF::is_blacklisted (hb_blob_t *blob,
@@ -306,16 +306,17 @@ void
 hb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
 				  hb_ot_layout_glyph_class_t  klass,
 				  hb_set_t                   *glyphs /* OUT */)
 {
   return face->table.GDEF->table->get_glyphs_in_class (klass, glyphs);
 }
 
 
+#ifndef HB_NO_LAYOUT_UNUSED
 /**
  * hb_ot_layout_get_attach_points:
  * @face: The #hb_face_t to work on
  * @glyph: The #hb_codepoint_t code point to query
  * @start_offset: offset of the first attachment point to retrieve
  * @point_count: (inout) (allow-none): Input = the maximum number of attachment points to return;
  *               Output = the actual number of attachment points returned (may be zero)
  * @point_array: (out) (array length=point_count): The array of attachment points found for the query
@@ -328,29 +329,21 @@ hb_ot_layout_get_glyphs_in_class (hb_fac
  **/
 unsigned int
 hb_ot_layout_get_attach_points (hb_face_t      *face,
 				hb_codepoint_t  glyph,
 				unsigned int    start_offset,
 				unsigned int   *point_count /* IN/OUT */,
 				unsigned int   *point_array /* OUT */)
 {
-#ifdef HB_NO_LAYOUT_UNUSED
-  if (point_count)
-    *point_count = 0;
-  return 0;
-#endif
-
   return face->table.GDEF->table->get_attach_points (glyph,
 						     start_offset,
 						     point_count,
 						     point_array);
 }
-
-
 /**
  * hb_ot_layout_get_ligature_carets:
  * @font: The #hb_font_t to work on
  * @direction: The #hb_direction_t text direction to use
  * @glyph: The #hb_codepoint_t code point to query
  * @start_offset: offset of the first caret position to retrieve
  * @caret_count: (inout) (allow-none): Input = the maximum number of caret positions to return;
  *               Output = the actual number of caret positions returned (may be zero)
@@ -363,45 +356,44 @@ hb_ot_layout_get_attach_points (hb_face_
 unsigned int
 hb_ot_layout_get_ligature_carets (hb_font_t      *font,
 				  hb_direction_t  direction,
 				  hb_codepoint_t  glyph,
 				  unsigned int    start_offset,
 				  unsigned int   *caret_count /* IN/OUT */,
 				  hb_position_t  *caret_array /* OUT */)
 {
-#ifdef HB_NO_LAYOUT_UNUSED
-  if (caret_count)
-    *caret_count = 0;
-  return 0;
-#endif
-
   unsigned int result_caret_count = 0;
   unsigned int result = font->face->table.GDEF->table->get_lig_carets (font, direction, glyph, start_offset, &result_caret_count, caret_array);
   if (result)
   {
     if (caret_count) *caret_count = result_caret_count;
   }
+#ifndef HB_NO_AAT
   else
     result = font->face->table.lcar->get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
+#endif
   return result;
 }
+#endif
 
 
 /*
  * GSUB/GPOS
  */
 
 bool
 OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED,
 			  hb_face_t *face) const
 {
 #ifdef HB_NO_OT_LAYOUT_BLACKLIST
   return false;
 #endif
+
+#ifndef HB_NO_SHAPE_AAT
   /* Mac OS X prefers morx over GSUB.  It also ships with various Indic fonts,
    * all by 'MUTF' foundry (Tamil MN, Tamil Sangam MN, etc.), that have broken
    * GSUB/GPOS tables.  Some have GSUB with zero scripts, those are ignored by
    * our morx/GSUB preference code.  But if GSUB has non-zero scripts, we tend
    * to prefer it over morx because we want to be consistent with other OpenType
    * shapers.
    *
    * To work around broken Indic Mac system fonts, we ignore GSUB table if
@@ -409,16 +401,17 @@ OT::GSUB::is_blacklisted (hb_blob_t *blo
    *
    * https://github.com/harfbuzz/harfbuzz/issues/1410
    * https://github.com/harfbuzz/harfbuzz/issues/1348
    * https://github.com/harfbuzz/harfbuzz/issues/1391
    */
   if (unlikely (face->table.OS2->achVendID == HB_TAG ('M','U','T','F') &&
 		face->table.morx->has_data ()))
     return true;
+#endif
 
   return false;
 }
 
 bool
 OT::GPOS::is_blacklisted (hb_blob_t *blob HB_UNUSED,
 			  hb_face_t *face HB_UNUSED) const
 {
@@ -1205,16 +1198,17 @@ hb_ot_layout_collect_lookups (hb_face_t 
   hb_ot_layout_collect_features (face, table_tag, scripts, languages, features, &feature_indexes);
 
   for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID;
        hb_set_next (&feature_indexes, &feature_index);)
     g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes);
 }
 
 
+#ifndef HB_NO_LAYOUT_COLLECT_GLYPHS
 /**
  * hb_ot_layout_lookup_collect_glyphs:
  * @face: #hb_face_t to work upon
  * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
  * @lookup_index: The index of the feature lookup to query
  * @glyphs_before: (out): Array of glyphs preceding the substitution range
  * @glyphs_input: (out): Array of input glyphs that would be substituted by the lookup
  * @glyphs_after: (out): Array of glyphs following the substition range
@@ -1251,16 +1245,17 @@ hb_ot_layout_lookup_collect_glyphs (hb_f
     case HB_OT_TAG_GPOS:
     {
       const OT::PosLookup& l = face->table.GPOS->table->get_lookup (lookup_index);
       l.collect_glyphs (&c);
       return;
     }
   }
 }
+#endif
 
 
 /* Variations support */
 
 
 /**
  * hb_ot_layout_table_find_feature_variations:
  * @face: #hb_face_t to work upon
@@ -1559,16 +1554,17 @@ hb_ot_layout_position_finish_advances (h
  **/
 void
 hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
 {
   OT::GPOS::position_finish_offsets (font, buffer);
 }
 
 
+#ifndef HB_NO_LAYOUT_FEATURE_PARAMS
 /**
  * hb_ot_layout_get_size_params:
  * @face: #hb_face_t to work upon
  * @design_size: (out): The design size of the face
  * @subfamily_id: (out): The identifier of the face within the font subfamily
  * @subfamily_name_id: (out): The ‘name’ table name ID of the face within the font subfamily
  * @range_start: (out): The minimum size of the recommended size range for the face
  * @range_end: (out): The maximum size of the recommended size range for the face
@@ -1621,18 +1617,16 @@ hb_ot_layout_get_size_params (hb_face_t 
   if (design_size) *design_size = 0;
   if (subfamily_id) *subfamily_id = 0;
   if (subfamily_name_id) *subfamily_name_id = HB_OT_NAME_ID_INVALID;
   if (range_start) *range_start = 0;
   if (range_end) *range_end = 0;
 
   return false;
 }
-
-
 /**
  * hb_ot_layout_feature_get_name_ids:
  * @face: #hb_face_t to work upon
  * @table_tag: table tag to query, "GSUB" or "GPOS".
  * @feature_index: index of feature to query.
  * @label_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
  *            for a user-interface label for this feature. (May be NULL.)
  * @tooltip_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
@@ -1697,18 +1691,16 @@ hb_ot_layout_feature_get_name_ids (hb_fa
 
   if (label_id) *label_id = HB_OT_NAME_ID_INVALID;
   if (tooltip_id) *tooltip_id = HB_OT_NAME_ID_INVALID;
   if (sample_id) *sample_id = HB_OT_NAME_ID_INVALID;
   if (num_named_parameters) *num_named_parameters = 0;
   if (first_param_id) *first_param_id = HB_OT_NAME_ID_INVALID;
   return false;
 }
-
-
 /**
  * hb_ot_layout_feature_get_characters:
  * @face: #hb_face_t to work upon
  * @table_tag: table tag to query, "GSUB" or "GPOS".
  * @feature_index: index of feature to query.
  * @start_offset: offset of the first character to retrieve
  * @char_count: (inout) (allow-none): Input = the maximum number of characters to return;
  *              Output = the actual number of characters returned (may be zero)
@@ -1752,16 +1744,17 @@ hb_ot_layout_feature_get_characters (hb_
   {
     len = hb_min (cv_params.characters.len - start_offset, *char_count);
     for (unsigned int i = 0; i < len; ++i)
       characters[i] = cv_params.characters[start_offset + i];
   }
   if (char_count) *char_count = len;
   return cv_params.characters.len;
 }
+#endif
 
 
 /*
  * Parts of different types are implemented here such that they have direct
  * access to GSUB/GPOS lookups.
  */
 
 
@@ -1936,32 +1929,26 @@ void
 hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
 				const OT::SubstLookup &lookup,
 				const OT::hb_ot_layout_lookup_accelerator_t &accel)
 {
   apply_string<GSUBProxy> (c, lookup, accel);
 }
 
 #if 0
-static const OT::BASE& _get_base (hb_face_t *face)
-{
-  return *face->table.BASE;
-}
-
 hb_bool_t
 hb_ot_layout_get_baseline (hb_font_t               *font,
 			   hb_ot_layout_baseline_t  baseline,
 			   hb_direction_t           direction,
 			   hb_tag_t                 script_tag,
 			   hb_tag_t                 language_tag,
 			   hb_position_t           *coord        /* OUT.  May be NULL. */)
 {
-  const OT::BASE &base = _get_base (font->face);
-  bool result = base.get_baseline (font, baseline, direction, script_tag,
-				   language_tag, coord);
+  bool result = font->face->table.BASE->get_baseline (font, baseline, direction, script_tag,
+						      language_tag, coord);
 
   /* TODO: Simulate https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags#ideographic-em-box */
   if (!result && coord) *coord = 0;
 
   if (coord) *coord = font->em_scale_dir (*coord, direction);
 
   return result;
 }
--- a/gfx/harfbuzz/src/hb-ot-math.cc
+++ b/gfx/harfbuzz/src/hb-ot-math.cc
@@ -19,19 +19,20 @@
  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Igalia Author(s): Frédéric Wang
  */
 
-#include "hb-open-type.hh"
+#include "hb.hh"
 
-#include "hb-ot-face.hh"
+#ifndef HB_NO_MATH
+
 #include "hb-ot-math-table.hh"
 
 
 /**
  * SECTION:hb-ot-math
  * @title: hb-ot-math
  * @short_description: OpenType Math information
  * @include: hb-ot.h
@@ -57,20 +58,16 @@
  *
  * Return value: true if the table is found, false otherwise
  *
  * Since: 1.3.3
  **/
 hb_bool_t
 hb_ot_math_has_data (hb_face_t *face)
 {
-#ifdef HB_NO_MATH
-  return false;
-#endif
-
   return face->table.MATH->has_data ();
 }
 
 /**
  * hb_ot_math_get_constant:
  * @font: #hb_font_t to work upon
  * @constant: #hb_ot_math_constant_t the constant to retrieve
  *
@@ -85,20 +82,16 @@ hb_ot_math_has_data (hb_face_t *face)
  * Return value: the requested constant or zero
  *
  * Since: 1.3.3
  **/
 hb_position_t
 hb_ot_math_get_constant (hb_font_t *font,
 			 hb_ot_math_constant_t constant)
 {
-#ifdef HB_NO_MATH
-  return 0;
-#endif
-
   return font->face->table.MATH->get_constant(constant, font);
 }
 
 /**
  * hb_ot_math_get_glyph_italics_correction:
  * @font: #hb_font_t to work upon
  * @glyph: The glyph index from which to retrieve the value
  *
@@ -108,20 +101,16 @@ hb_ot_math_get_constant (hb_font_t *font
   * Return value: the italics correction of the glyph or zero
  *
  * Since: 1.3.3
  **/
 hb_position_t
 hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
 					 hb_codepoint_t glyph)
 {
-#ifdef HB_NO_MATH
-  return 0;
-#endif
-
   return font->face->table.MATH->get_glyph_info().get_italics_correction (glyph, font);
 }
 
 /**
  * hb_ot_math_get_glyph_top_accent_attachment:
  * @font: #hb_font_t to work upon
  * @glyph: The glyph index from which to retrieve the value
  *
@@ -138,20 +127,16 @@ hb_ot_math_get_glyph_italics_correction 
  *               width of @glyph
  *
  * Since: 1.3.3
  **/
 hb_position_t
 hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
 					    hb_codepoint_t glyph)
 {
-#ifdef HB_NO_MATH
-  return 0;
-#endif
-
   return font->face->table.MATH->get_glyph_info().get_top_accent_attachment (glyph, font);
 }
 
 /**
  * hb_ot_math_is_glyph_extended_shape:
  * @face: #hb_face_t to work upon
  * @glyph: The glyph index to test
  *
@@ -160,20 +145,16 @@ hb_ot_math_get_glyph_top_accent_attachme
  * Return value: true if the glyph is an extended shape, false otherwise
  *
  * Since: 1.3.3
  **/
 hb_bool_t
 hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
 				    hb_codepoint_t glyph)
 {
-#ifdef HB_NO_MATH
-  return false;
-#endif
-
   return face->table.MATH->get_glyph_info().is_extended_shape (glyph);
 }
 
 /**
  * hb_ot_math_get_glyph_kerning:
  * @font: #hb_font_t to work upon
  * @glyph: The glyph index from which to retrieve the value
  * @kern: The #hb_ot_math_kern_t from which to retrieve the value
@@ -192,20 +173,16 @@ hb_ot_math_is_glyph_extended_shape (hb_f
  * Since: 1.3.3
  **/
 hb_position_t
 hb_ot_math_get_glyph_kerning (hb_font_t *font,
 			      hb_codepoint_t glyph,
 			      hb_ot_math_kern_t kern,
 			      hb_position_t correction_height)
 {
-#ifdef HB_NO_MATH
-  return 0;
-#endif
-
   return font->face->table.MATH->get_glyph_info().get_kerning (glyph,
 							       kern,
 							       correction_height,
 							       font);
 }
 
 /**
  * hb_ot_math_get_glyph_variants:
@@ -233,22 +210,16 @@ hb_ot_math_get_glyph_kerning (hb_font_t 
 unsigned int
 hb_ot_math_get_glyph_variants (hb_font_t *font,
 			       hb_codepoint_t glyph,
 			       hb_direction_t direction,
 			       unsigned int start_offset,
 			       unsigned int *variants_count, /* IN/OUT */
 			       hb_ot_math_glyph_variant_t *variants /* OUT */)
 {
-#ifdef HB_NO_MATH
-  if (variants_count)
-    *variants_count = 0;
-  return 0;
-#endif
-
   return font->face->table.MATH->get_variants().get_glyph_variants (glyph, direction, font,
 								    start_offset,
 								    variants_count,
 								    variants);
 }
 
 /**
  * hb_ot_math_get_min_connector_overlap:
@@ -267,20 +238,16 @@ hb_ot_math_get_glyph_variants (hb_font_t
  * Return value: requested minimum connector overlap or zero
  *
  * Since: 1.3.3
  **/
 hb_position_t
 hb_ot_math_get_min_connector_overlap (hb_font_t *font,
 				      hb_direction_t direction)
 {
-#ifdef HB_NO_MATH
-  return 0;
-#endif
-
   return font->face->table.MATH->get_variants().get_min_connector_overlap (direction, font);
 }
 
 /**
  * hb_ot_math_get_glyph_assembly:
  * @font: #hb_font_t to work upon
  * @glyph: The index of the glyph to stretch
  * @direction: direction of the stretching (horizontal or vertical)
@@ -308,22 +275,19 @@ unsigned int
 hb_ot_math_get_glyph_assembly (hb_font_t *font,
 			       hb_codepoint_t glyph,
 			       hb_direction_t direction,
 			       unsigned int start_offset,
 			       unsigned int *parts_count, /* IN/OUT */
 			       hb_ot_math_glyph_part_t *parts, /* OUT */
 			       hb_position_t *italics_correction /* OUT */)
 {
-#ifdef HB_NO_MATH
-  if (parts_count)
-    *parts_count = 0;
-  return 0;
-#endif
-
   return font->face->table.MATH->get_variants().get_glyph_parts (glyph,
 								 direction,
 								 font,
 								 start_offset,
 								 parts_count,
 								 parts,
 								 italics_correction);
 }
+
+
+#endif
--- a/gfx/harfbuzz/src/hb-ot-maxp-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-maxp-table.hh
@@ -89,49 +89,45 @@ struct maxp
     if (version.major == 1)
     {
       const maxpV1Tail &v1 = StructAfter<maxpV1Tail> (*this);
       return_trace (v1.sanitize (c));
     }
     return_trace (likely (version.major == 0 && version.minor == 0x5000u));
   }
 
-  bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_context_t *c) const
   {
-    hb_blob_t *maxp_blob = hb_sanitize_context_t().reference_table<maxp> (plan->source);
-    hb_blob_t *maxp_prime_blob = hb_blob_copy_writable_or_fail (maxp_blob);
-    hb_blob_destroy (maxp_blob);
+    TRACE_SUBSET (this);
+    maxp *maxp_prime = c->serializer->embed (this);
+    if (unlikely (!maxp_prime)) return_trace (false);
 
-    if (unlikely (!maxp_prime_blob)) {
-      return false;
+    maxp_prime->numGlyphs = c->plan->num_output_glyphs ();
+    if (maxp_prime->version.major == 1)
+    {
+      const maxpV1Tail *src_v1 = &StructAfter<maxpV1Tail> (*this);
+      maxpV1Tail *dest_v1 = c->serializer->embed<maxpV1Tail> (src_v1);
+      if (unlikely (!dest_v1)) return_trace (false);
+
+      if (c->plan->drop_hints)
+        drop_hint_fields (dest_v1);
     }
-    maxp *maxp_prime = (maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
 
-    maxp_prime->set_num_glyphs (plan->num_output_glyphs ());
-    if (plan->drop_hints)
-      drop_hint_fields (plan, maxp_prime);
-
-    bool result = plan->add_table (HB_OT_TAG_maxp, maxp_prime_blob);
-    hb_blob_destroy (maxp_prime_blob);
-    return result;
+    return_trace (true);
   }
 
-  static void drop_hint_fields (hb_subset_plan_t *plan HB_UNUSED, maxp *maxp_prime)
+  static void drop_hint_fields (maxpV1Tail* dest_v1)
   {
-    if (maxp_prime->version.major == 1)
-    {
-      maxpV1Tail &v1 = StructAfter<maxpV1Tail> (*maxp_prime);
-      v1.maxZones = 1;
-      v1.maxTwilightPoints = 0;
-      v1.maxStorage = 0;
-      v1.maxFunctionDefs = 0;
-      v1.maxInstructionDefs = 0;
-      v1.maxStackElements = 0;
-      v1.maxSizeOfInstructions = 0;
-    }
+    dest_v1->maxZones = 1;
+    dest_v1->maxTwilightPoints = 0;
+    dest_v1->maxStorage = 0;
+    dest_v1->maxFunctionDefs = 0;
+    dest_v1->maxInstructionDefs = 0;
+    dest_v1->maxStackElements = 0;
+    dest_v1->maxSizeOfInstructions = 0;
   }
 
   protected:
   FixedVersion<>version;		/* Version of the maxp table (0.5 or 1.0),
 					 * 0x00005000u or 0x00010000u. */
   HBUINT16	numGlyphs;		/* The number of glyphs in the font. */
 /*maxpV1Tail	v1Tail[VAR]; */
   public:
--- a/gfx/harfbuzz/src/hb-ot-name-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-name-table.hh
@@ -58,17 +58,17 @@ struct NameRecord
     if (p == 3)
       return _hb_ot_name_language_for_ms_code (l);
 
     if (p == 1)
       return _hb_ot_name_language_for_mac_code (l);
 
 #ifndef HB_NO_OT_NAME_LANGUAGE_AAT
     if (p == 0)
-      return _hb_aat_language_get (face, l);
+      return face->table.ltag->get_language (l);
 #endif
 
 #endif
     return HB_LANGUAGE_INVALID;
   }
 
   uint16_t score () const
   {
--- a/gfx/harfbuzz/src/hb-ot-name.cc
+++ b/gfx/harfbuzz/src/hb-ot-name.cc
@@ -21,19 +21,20 @@
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Google Author(s): Behdad Esfahbod
  */
 
 #include "hb.hh"
 
+#ifndef HB_NO_NAME
+
 #include "hb-ot-name-table.hh"
 
-#include "hb-ot-face.hh"
 #include "hb-utf.hh"
 
 
 /**
  * SECTION:hb-ot-name
  * @title: hb-ot-name
  * @short_description: OpenType font name information
  * @include: hb-ot.h
@@ -53,21 +54,16 @@
  *
  * Returns: (out) (transfer none) (array length=num_entries): Array of available name entries.
  * Since: 2.1.0
  **/
 const hb_ot_name_entry_t *
 hb_ot_name_list_names (hb_face_t    *face,
 		       unsigned int *num_entries /* OUT */)
 {
-#ifdef HB_NO_NAME
-  if (num_entries)
-    *num_entries = 0;
-  return 0;
-#endif
   const OT::name_accelerator_t &name = *face->table.name;
   if (num_entries) *num_entries = name.names.length;
   return (const hb_ot_name_entry_t *) name.names;
 }
 
 
 template <typename in_utf_t, typename out_utf_t>
 static inline unsigned int
@@ -167,21 +163,16 @@ hb_ot_name_get_utf (hb_face_t       *fac
  **/
 unsigned int
 hb_ot_name_get_utf8 (hb_face_t       *face,
 		     hb_ot_name_id_t  name_id,
 		     hb_language_t    language,
 		     unsigned int    *text_size /* IN/OUT */,
 		     char            *text      /* OUT */)
 {
-#ifdef HB_NO_NAME
-  if (text_size)
-    *text_size = 0;
-  return 0;
-#endif
   return hb_ot_name_get_utf<hb_utf8_t> (face, name_id, language, text_size,
 					(hb_utf8_t::codepoint_t *) text);
 }
 
 /**
  * hb_ot_name_get_utf16:
  * @face: font face.
  * @name_id: OpenType name identifier to fetch.
@@ -199,21 +190,16 @@ hb_ot_name_get_utf8 (hb_face_t       *fa
  **/
 unsigned int
 hb_ot_name_get_utf16 (hb_face_t       *face,
 		      hb_ot_name_id_t  name_id,
 		      hb_language_t    language,
 		      unsigned int    *text_size /* IN/OUT */,
 		      uint16_t        *text      /* OUT */)
 {
-#ifdef HB_NO_NAME
-  if (text_size)
-    *text_size = 0;
-  return 0;
-#endif
   return hb_ot_name_get_utf<hb_utf16_t> (face, name_id, language, text_size, text);
 }
 
 /**
  * hb_ot_name_get_utf32:
  * @face: font face.
  * @name_id: OpenType name identifier to fetch.
  * @language: language to fetch the name for.
@@ -230,15 +216,13 @@ hb_ot_name_get_utf16 (hb_face_t       *f
  **/
 unsigned int
 hb_ot_name_get_utf32 (hb_face_t       *face,
 		      hb_ot_name_id_t  name_id,
 		      hb_language_t    language,
 		      unsigned int    *text_size /* IN/OUT */,
 		      uint32_t        *text      /* OUT */)
 {
-#ifdef HB_NO_NAME
-  if (text_size)
-    *text_size = 0;
-  return 0;
-#endif
   return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text);
 }
+
+
+#endif
--- a/gfx/harfbuzz/src/hb-ot-os2-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-os2-table.hh
@@ -140,65 +140,60 @@ struct OS2
     case FWIDTH_NORMAL:		return 100.f;
     case FWIDTH_SEMI_EXPANDED:	return 112.5f;
     case FWIDTH_EXPANDED:	return 125.f;
     case FWIDTH_EXTRA_EXPANDED:	return 150.f;
     case FWIDTH_ULTRA_EXPANDED:	return 200.f;
     }
   }
 
-  bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_context_t *c) const
   {
-    hb_blob_t *os2_blob = hb_sanitize_context_t ().reference_table<OS2> (plan->source);
-    hb_blob_t *os2_prime_blob = hb_blob_create_sub_blob (os2_blob, 0, -1);
-    // TODO(grieger): move to hb_blob_copy_writable_or_fail
-    hb_blob_destroy (os2_blob);
-
-    OS2 *os2_prime = (OS2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
-    if (unlikely (!os2_prime)) {
-      hb_blob_destroy (os2_prime_blob);
-      return false;
-    }
+    TRACE_SUBSET (this);
+    OS2 *os2_prime = c->serializer->embed (this);
+    if (unlikely (!os2_prime)) return_trace (false);
 
     uint16_t min_cp, max_cp;
-    find_min_and_max_codepoint (plan->unicodes, &min_cp, &max_cp);
+    find_min_and_max_codepoint (c->plan->unicodes, &min_cp, &max_cp);
     os2_prime->usFirstCharIndex = min_cp;
     os2_prime->usLastCharIndex = max_cp;
 
-    _update_unicode_ranges (plan->unicodes, os2_prime->ulUnicodeRange);
-    bool result = plan->add_table (HB_OT_TAG_OS2, os2_prime_blob);
+    _update_unicode_ranges (c->plan->unicodes, os2_prime->ulUnicodeRange);
 
-    hb_blob_destroy (os2_prime_blob);
-    return result;
+    return_trace (true);
   }
 
   void _update_unicode_ranges (const hb_set_t *codepoints,
 			       HBUINT32 ulUnicodeRange[4]) const
   {
+    HBUINT32	newBits[4];
     for (unsigned int i = 0; i < 4; i++)
-      ulUnicodeRange[i] = 0;
+      newBits[i] = 0;
 
     hb_codepoint_t cp = HB_SET_VALUE_INVALID;
     while (codepoints->next (&cp)) {
       unsigned int bit = _hb_ot_os2_get_unicode_range_bit (cp);
       if (bit < 128)
       {
 	unsigned int block = bit / 32;
 	unsigned int bit_in_block = bit % 32;
 	unsigned int mask = 1 << bit_in_block;
-	ulUnicodeRange[block] = ulUnicodeRange[block] | mask;
+	newBits[block] = newBits[block] | mask;
       }
       if (cp >= 0x10000 && cp <= 0x110000)
       {
 	/* the spec says that bit 57 ("Non Plane 0") implies that there's
 	   at least one codepoint beyond the BMP; so I also include all
 	   the non-BMP codepoints here */
-	ulUnicodeRange[1] = ulUnicodeRange[1] | (1 << 25);
+	newBits[1] = newBits[1] | (1 << 25);
       }
     }
+
+    for (unsigned int i = 0; i < 4; i++)
+      ulUnicodeRange[i] = ulUnicodeRange[i] & newBits[i]; // set bits only if set in the original
   }
 
   static void find_min_and_max_codepoint (const hb_set_t *codepoints,
 						 uint16_t *min_cp, /* OUT */
 						 uint16_t *max_cp  /* OUT */)
   {
     *min_cp = codepoints->get_min ();
     *max_cp = codepoints->get_max ();
@@ -213,16 +208,25 @@ struct OS2
     TRAD_FARSI_FONT_PAGE	= 0xBB00, // Traditional Farsi Windows 3.1 font page
     THAI_FONT_PAGE		= 0xDE00  // Thai Windows 3.1 font page
   };
 
   // https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681
   font_page_t get_font_page () const
   { return (font_page_t) (version == 0 ? fsSelection & 0xFF00 : 0); }
 
+  unsigned get_size () const
+  {
+    unsigned result = min_size;
+    if (version >= 1) result += v1X.get_size ();
+    if (version >= 2) result += v2X.get_size ();
+    if (version >= 5) result += v5X.get_size ();
+    return result;
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this))) return_trace (false);
     if (unlikely (version >= 1 && !v1X.sanitize (c))) return_trace (false);
     if (unlikely (version >= 2 && !v2X.sanitize (c))) return_trace (false);
     if (unlikely (version >= 5 && !v5X.sanitize (c))) return_trace (false);
     return_trace (true);
--- a/gfx/harfbuzz/src/hb-ot-post-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-post-table.hh
@@ -68,36 +68,35 @@ struct postV2Tail
   public:
   DEFINE_SIZE_ARRAY (2, glyphNameIndex);
 };
 
 struct post
 {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_post;
 
-  bool subset (hb_subset_plan_t *plan) const
+  void serialize (hb_serialize_context_t *c) const
   {
-    unsigned int post_prime_length;
-    hb_blob_t *post_blob = hb_sanitize_context_t ().reference_table<post>(plan->source);
-    hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::min_size);
-    post *post_prime = (post *) hb_blob_get_data_writable (post_prime_blob, &post_prime_length);
-    hb_blob_destroy (post_blob);
+    post *post_prime = c->allocate_min<post> ();
+    if (unlikely (!post_prime))  return;
+
+    memcpy (post_prime, this, post::min_size);
+    post_prime->version.major = 3; // Version 3 does not have any glyph names.
+  }
 
-    if (unlikely (!post_prime || post_prime_length != post::min_size))
-    {
-      hb_blob_destroy (post_prime_blob);
-      DEBUG_MSG(SUBSET, nullptr, "Invalid source post table with length %d.", post_prime_length);
-      return false;
-    }
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    post *post_prime = c->serializer->start_embed<post> ();
+    if (unlikely (!post_prime)) return_trace (false);
 
-    post_prime->version.major = 3; // Version 3 does not have any glyph names.
-    bool result = plan->add_table (HB_OT_TAG_post, post_prime_blob);
-    hb_blob_destroy (post_prime_blob);
+    serialize (c->serializer);
+    if (c->serializer->in_error () || c->serializer->ran_out_of_room) return_trace (false);
 
-    return result;
+    return_trace (true);
   }
 
   struct accelerator_t
   {
     void init (hb_face_t *face)
     {
       index_to_offset.init ();
 
@@ -153,28 +152,28 @@ struct post
       if (unlikely (!gids))
       {
 	gids = (uint16_t *) malloc (count * sizeof (gids[0]));
 	if (unlikely (!gids))
 	  return false; /* Anything better?! */
 
 	for (unsigned int i = 0; i < count; i++)
 	  gids[i] = i;
-	hb_sort_r (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
+	hb_qsort (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
 
 	if (unlikely (!gids_sorted_by_name.cmpexch (nullptr, gids)))
 	{
 	  free (gids);
 	  goto retry;
 	}
       }
 
       hb_bytes_t st (name, len);
-      const uint16_t *gid = (const uint16_t *) hb_bsearch_r (hb_addressof (st), gids, count,
-							     sizeof (gids[0]), cmp_key, (void *) this);
+      const uint16_t *gid = (const uint16_t *) hb_bsearch (hb_addressof (st), gids, count,
+							   sizeof (gids[0]), cmp_key, (void *) this);
       if (gid)
       {
 	*glyph = *gid;
 	return true;
       }
 
       return false;
     }
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.hh
@@ -354,17 +354,17 @@ set_indic_properties (hb_glyph_info_t &i
     /* 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 == 0x1133Bu || u == 0x1133Cu)) cat = OT_N;
 
   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/harfbuzz/harfbuzz/issues/538 */
   else if (unlikely (u == 0x09FCu)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/1613 */
   else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
   else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
 				    cat = OT_PLACEHOLDER;
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
@@ -31,41 +31,41 @@
 
 #include "hb.hh"
 
 
 #line 36 "hb-ot-shape-complex-myanmar-machine.hh"
 static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
 	1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 
 	3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, 
-	3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 5u, 29u, 
-	5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 
-	3u, 29u, 1u, 16u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
-	3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 1u, 32u, 
-	1u, 32u, 8u, 8u, 0
+	3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
+	5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 
+	3u, 29u, 3u, 29u, 1u, 16u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
+	3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 
+	3u, 29u, 1u, 32u, 1u, 32u, 8u, 8u, 0
 };
 
 static const char _myanmar_syllable_machine_key_spans[] = {
 	32, 28, 25, 4, 25, 23, 21, 21, 
 	27, 27, 27, 27, 16, 27, 27, 27, 
-	27, 27, 28, 27, 27, 27, 27, 25, 
-	4, 25, 23, 21, 21, 27, 27, 27, 
-	27, 16, 28, 27, 27, 27, 27, 27, 
-	28, 27, 27, 27, 27, 28, 27, 32, 
-	32, 1
+	27, 27, 28, 27, 27, 27, 27, 27, 
+	25, 4, 25, 23, 21, 21, 27, 27, 
+	27, 27, 16, 28, 27, 27, 27, 27, 
+	27, 28, 27, 27, 27, 27, 27, 28, 
+	27, 32, 32, 1
 };
 
 static const short _myanmar_syllable_machine_index_offsets[] = {
 	0, 33, 62, 88, 93, 119, 143, 165, 
 	187, 215, 243, 271, 299, 316, 344, 372, 
 	400, 428, 456, 485, 513, 541, 569, 597, 
-	623, 628, 654, 678, 700, 722, 750, 778, 
-	806, 834, 851, 880, 908, 936, 964, 992, 
-	1020, 1049, 1077, 1105, 1133, 1161, 1190, 1218, 
-	1251, 1284
+	625, 651, 656, 682, 706, 728, 750, 778, 
+	806, 834, 862, 879, 908, 936, 964, 992, 
+	1020, 1048, 1077, 1105, 1133, 1161, 1189, 1217, 
+	1246, 1274, 1307, 1340
 };
 
 static const char _myanmar_syllable_machine_indicies[] = {
 	1, 1, 2, 3, 4, 4, 0, 5, 
 	0, 6, 1, 0, 0, 0, 0, 7, 
 	0, 8, 9, 0, 10, 11, 12, 13, 
 	14, 15, 16, 17, 18, 19, 20, 1, 
 	0, 22, 23, 24, 24, 21, 25, 21, 
@@ -121,167 +121,174 @@ static const char _myanmar_syllable_mach
 	21, 25, 21, 26, 21, 21, 21, 21, 
 	21, 21, 21, 21, 21, 21, 21, 21, 
 	21, 21, 32, 21, 34, 21, 36, 21, 
 	22, 21, 24, 24, 21, 25, 21, 26, 
 	21, 21, 21, 21, 21, 21, 21, 21, 
 	21, 21, 21, 21, 21, 21, 32, 33, 
 	34, 35, 36, 43, 21, 22, 21, 24, 
 	24, 21, 25, 21, 26, 21, 21, 21, 
-	21, 21, 21, 21, 43, 21, 21, 28, 
+	21, 21, 21, 21, 21, 21, 21, 28, 
 	21, 30, 21, 32, 33, 34, 35, 36, 
 	21, 22, 21, 24, 24, 21, 25, 21, 
 	26, 21, 21, 21, 21, 21, 21, 21, 
 	43, 21, 21, 28, 21, 21, 21, 32, 
 	33, 34, 35, 36, 21, 22, 21, 24, 
 	24, 21, 25, 21, 26, 21, 21, 21, 
-	21, 21, 21, 21, 43, 21, 21, 28, 
+	21, 21, 21, 21, 44, 21, 21, 28, 
 	29, 30, 21, 32, 33, 34, 35, 36, 
-	21, 22, 23, 24, 24, 21, 25, 21, 
+	21, 22, 21, 24, 24, 21, 25, 21, 
 	26, 21, 21, 21, 21, 21, 21, 21, 
-	27, 21, 21, 28, 29, 30, 31, 32, 
-	33, 34, 35, 36, 21, 45, 45, 44, 
-	5, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 46, 44, 44, 44, 44, 44, 
-	44, 14, 44, 44, 44, 18, 44, 45, 
-	45, 44, 5, 44, 45, 45, 44, 5, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	14, 44, 44, 44, 18, 44, 47, 44, 
-	45, 45, 44, 5, 44, 14, 44, 44, 
-	44, 44, 44, 44, 44, 48, 44, 44, 
-	44, 44, 44, 44, 14, 44, 45, 45, 
-	44, 5, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 48, 44, 44, 44, 44, 
-	44, 44, 14, 44, 45, 45, 44, 5, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	14, 44, 2, 44, 45, 45, 44, 5, 
-	44, 6, 44, 44, 44, 44, 44, 44, 
-	44, 49, 44, 44, 49, 44, 44, 44, 
-	14, 50, 44, 44, 18, 44, 2, 44, 
-	45, 45, 44, 5, 44, 6, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 14, 44, 44, 44, 
-	18, 44, 2, 44, 45, 45, 44, 5, 
-	44, 6, 44, 44, 44, 44, 44, 44, 
-	44, 49, 44, 44, 44, 44, 44, 44, 
-	14, 50, 44, 44, 18, 44, 2, 44, 
-	45, 45, 44, 5, 44, 6, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 14, 50, 44, 44, 
-	18, 44, 51, 51, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 51, 44, 2, 3, 45, 45, 44, 
-	5, 44, 6, 44, 44, 44, 44, 44, 
-	44, 44, 8, 44, 44, 10, 11, 12, 
-	13, 14, 15, 16, 17, 18, 19, 44, 
-	2, 44, 45, 45, 44, 5, 44, 6, 
-	44, 44, 44, 44, 44, 44, 44, 8, 
-	44, 44, 10, 11, 12, 13, 14, 15, 
-	16, 17, 18, 44, 2, 44, 45, 45, 
-	44, 5, 44, 6, 44, 44, 44, 44, 
-	44, 44, 44, 52, 44, 44, 44, 44, 
-	44, 44, 14, 15, 16, 17, 18, 44, 
-	2, 44, 45, 45, 44, 5, 44, 6, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 14, 15, 
-	16, 17, 18, 44, 2, 44, 45, 45, 
-	44, 5, 44, 6, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 14, 15, 16, 44, 18, 44, 
-	2, 44, 45, 45, 44, 5, 44, 6, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 14, 44, 
-	16, 44, 18, 44, 2, 44, 45, 45, 
-	44, 5, 44, 6, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 14, 15, 16, 17, 18, 52, 
-	44, 2, 44, 45, 45, 44, 5, 44, 
-	6, 44, 44, 44, 44, 44, 44, 44, 
-	52, 44, 44, 10, 44, 12, 44, 14, 
-	15, 16, 17, 18, 44, 2, 44, 45, 
-	45, 44, 5, 44, 6, 44, 44, 44, 
-	44, 44, 44, 44, 52, 44, 44, 10, 
-	44, 44, 44, 14, 15, 16, 17, 18, 
-	44, 2, 44, 45, 45, 44, 5, 44, 
-	6, 44, 44, 44, 44, 44, 44, 44, 
-	52, 44, 44, 10, 11, 12, 44, 14, 
-	15, 16, 17, 18, 44, 2, 3, 45, 
-	45, 44, 5, 44, 6, 44, 44, 44, 
-	44, 44, 44, 44, 8, 44, 44, 10, 
+	21, 21, 21, 28, 29, 30, 21, 32, 
+	33, 34, 35, 36, 21, 22, 23, 24, 
+	24, 21, 25, 21, 26, 21, 21, 21, 
+	21, 21, 21, 21, 27, 21, 21, 28, 
+	29, 30, 31, 32, 33, 34, 35, 36, 
+	21, 46, 46, 45, 5, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 47, 45, 
+	45, 45, 45, 45, 45, 14, 45, 45, 
+	45, 18, 45, 46, 46, 45, 5, 45, 
+	46, 46, 45, 5, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 14, 45, 45, 45, 
+	18, 45, 48, 45, 46, 46, 45, 5, 
+	45, 14, 45, 45, 45, 45, 45, 45, 
+	45, 49, 45, 45, 45, 45, 45, 45, 
+	14, 45, 46, 46, 45, 5, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 49, 
+	45, 45, 45, 45, 45, 45, 14, 45, 
+	46, 46, 45, 5, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 14, 45, 2, 45, 
+	46, 46, 45, 5, 45, 6, 45, 45, 
+	45, 45, 45, 45, 45, 50, 45, 45, 
+	50, 45, 45, 45, 14, 51, 45, 45, 
+	18, 45, 2, 45, 46, 46, 45, 5, 
+	45, 6, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	14, 45, 45, 45, 18, 45, 2, 45, 
+	46, 46, 45, 5, 45, 6, 45, 45, 
+	45, 45, 45, 45, 45, 50, 45, 45, 
+	45, 45, 45, 45, 14, 51, 45, 45, 
+	18, 45, 2, 45, 46, 46, 45, 5, 
+	45, 6, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	14, 51, 45, 45, 18, 45, 52, 52, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 52, 45, 2, 
+	3, 46, 46, 45, 5, 45, 6, 45, 
+	45, 45, 45, 45, 45, 45, 8, 45, 
+	45, 10, 11, 12, 13, 14, 15, 16, 
+	17, 18, 19, 45, 2, 45, 46, 46, 
+	45, 5, 45, 6, 45, 45, 45, 45, 
+	45, 45, 45, 8, 45, 45, 10, 11, 
+	12, 13, 14, 15, 16, 17, 18, 45, 
+	2, 45, 46, 46, 45, 5, 45, 6, 
+	45, 45, 45, 45, 45, 45, 45, 53, 
+	45, 45, 45, 45, 45, 45, 14, 15, 
+	16, 17, 18, 45, 2, 45, 46, 46, 
+	45, 5, 45, 6, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 14, 15, 16, 17, 18, 45, 
+	2, 45, 46, 46, 45, 5, 45, 6, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 14, 15, 
+	16, 45, 18, 45, 2, 45, 46, 46, 
+	45, 5, 45, 6, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 14, 45, 16, 45, 18, 45, 
+	2, 45, 46, 46, 45, 5, 45, 6, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 14, 15, 
+	16, 17, 18, 53, 45, 2, 45, 46, 
+	46, 45, 5, 45, 6, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 10, 
+	45, 12, 45, 14, 15, 16, 17, 18, 
+	45, 2, 45, 46, 46, 45, 5, 45, 
+	6, 45, 45, 45, 45, 45, 45, 45, 
+	53, 45, 45, 10, 45, 45, 45, 14, 
+	15, 16, 17, 18, 45, 2, 45, 46, 
+	46, 45, 5, 45, 6, 45, 45, 45, 
+	45, 45, 45, 45, 54, 45, 45, 10, 
+	11, 12, 45, 14, 15, 16, 17, 18, 
+	45, 2, 45, 46, 46, 45, 5, 45, 
+	6, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 10, 11, 12, 45, 14, 
+	15, 16, 17, 18, 45, 2, 3, 46, 
+	46, 45, 5, 45, 6, 45, 45, 45, 
+	45, 45, 45, 45, 8, 45, 45, 10, 
 	11, 12, 13, 14, 15, 16, 17, 18, 
-	44, 22, 23, 24, 24, 21, 25, 21, 
+	45, 22, 23, 24, 24, 21, 25, 21, 
 	26, 21, 21, 21, 21, 21, 21, 21, 
-	53, 21, 21, 28, 29, 30, 31, 32, 
-	33, 34, 35, 36, 37, 21, 22, 54, 
+	55, 21, 21, 28, 29, 30, 31, 32, 
+	33, 34, 35, 36, 37, 21, 22, 56, 
 	24, 24, 21, 25, 21, 26, 21, 21, 
 	21, 21, 21, 21, 21, 27, 21, 21, 
 	28, 29, 30, 31, 32, 33, 34, 35, 
-	36, 21, 1, 1, 2, 3, 45, 45, 
-	44, 5, 44, 6, 1, 44, 44, 44, 
-	44, 1, 44, 8, 44, 44, 10, 11, 
+	36, 21, 1, 1, 2, 3, 46, 46, 
+	45, 5, 45, 6, 1, 45, 45, 45, 
+	45, 1, 45, 8, 45, 45, 10, 11, 
 	12, 13, 14, 15, 16, 17, 18, 19, 
-	44, 1, 44, 1, 1, 55, 55, 55, 
-	55, 55, 55, 55, 55, 1, 55, 55, 
-	55, 55, 1, 55, 55, 55, 55, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 1, 55, 56, 55, 0
+	45, 1, 45, 1, 1, 57, 57, 57, 
+	57, 57, 57, 57, 57, 1, 57, 57, 
+	57, 57, 1, 57, 57, 57, 57, 57, 
+	57, 57, 57, 57, 57, 57, 57, 57, 
+	57, 57, 1, 57, 58, 57, 0
 };
 
 static const char _myanmar_syllable_machine_trans_targs[] = {
-	0, 1, 23, 33, 0, 24, 30, 45, 
-	35, 48, 36, 41, 42, 43, 26, 38, 
-	39, 40, 29, 44, 49, 0, 2, 12, 
+	0, 1, 24, 34, 0, 25, 31, 47, 
+	36, 50, 37, 42, 43, 44, 27, 39, 
+	40, 41, 30, 46, 51, 0, 2, 12, 
 	0, 3, 9, 13, 14, 19, 20, 21, 
-	5, 16, 17, 18, 8, 22, 4, 6, 
-	7, 10, 11, 15, 0, 0, 25, 27, 
-	28, 31, 32, 34, 37, 46, 47, 0, 
-	0
+	5, 16, 17, 18, 8, 23, 4, 6, 
+	7, 10, 11, 15, 22, 0, 0, 26, 
+	28, 29, 32, 33, 35, 38, 45, 48, 
+	49, 0, 0
 };
 
 static const char _myanmar_syllable_machine_trans_actions[] = {
 	3, 0, 0, 0, 4, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 5, 0, 0, 
 	6, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 7, 8, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 9, 
-	10
+	0, 0, 0, 0, 0, 7, 8, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 9, 10
 };
 
 static const char _myanmar_syllable_machine_to_state_actions[] = {
 	1, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0
+	0, 0, 0, 0
 };
 
 static const char _myanmar_syllable_machine_from_state_actions[] = {
 	2, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0
+	0, 0, 0, 0
 };
 
 static const short _myanmar_syllable_machine_eof_trans[] = {
 	0, 22, 22, 22, 22, 22, 22, 22, 
 	22, 22, 22, 22, 22, 22, 22, 22, 
-	22, 22, 22, 22, 22, 22, 22, 45, 
-	45, 45, 45, 45, 45, 45, 45, 45, 
-	45, 45, 45, 45, 45, 45, 45, 45, 
-	45, 45, 45, 45, 45, 22, 22, 45, 
-	56, 56
+	22, 22, 22, 22, 22, 22, 22, 22, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 22, 
+	22, 46, 58, 58
 };
 
 static const int myanmar_syllable_machine_start = 0;
 static const int myanmar_syllable_machine_first_final = 0;
 static const int myanmar_syllable_machine_error = -1;
 
 static const int myanmar_syllable_machine_en_main = 0;
 
@@ -304,47 +311,47 @@ static const int myanmar_syllable_machin
 
 static void
 find_syllables (hb_buffer_t *buffer)
 {
   unsigned int p, pe, eof, ts, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 313 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 320 "hb-ot-shape-complex-myanmar-machine.hh"
 	{
 	cs = myanmar_syllable_machine_start;
 	ts = 0;
 	te = 0;
 	act = 0;
 	}
 
 #line 114 "hb-ot-shape-complex-myanmar-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
   unsigned int syllable_serial = 1;
   
-#line 329 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 336 "hb-ot-shape-complex-myanmar-machine.hh"
 	{
 	int _slen;
 	int _trans;
 	const unsigned char *_keys;
 	const char *_inds;
 	if ( p == pe )
 		goto _test_eof;
 _resume:
 	switch ( _myanmar_syllable_machine_from_state_actions[cs] ) {
 	case 2:
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 343 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 350 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 	_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
 	_inds = _myanmar_syllable_machine_indicies + _myanmar_syllable_machine_index_offsets[cs];
 
 	_slen = _myanmar_syllable_machine_key_spans[cs];
 	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].myanmar_category()) &&
 		( info[p].myanmar_category()) <= _keys[1] ?
@@ -384,26 +391,26 @@ find_syllables (hb_buffer_t *buffer)
 	case 7:
 #line 89 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p;p--;{ found_syllable (broken_cluster); }}
 	break;
 	case 9:
 #line 90 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p;p--;{ found_syllable (non_myanmar_cluster); }}
 	break;
-#line 393 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 400 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 _again:
 	switch ( _myanmar_syllable_machine_to_state_actions[cs] ) {
 	case 1:
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 402 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 409 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 	if ( ++p != pe )
 		goto _resume;
 	_test_eof: {}
 	if ( p == eof )
 	{
 	if ( _myanmar_syllable_machine_eof_trans[cs] > 0 ) {
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.rl
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.rl
@@ -64,17 +64,17 @@ Ra   = 16;
 P    = 31;
 CS   = 19;
 
 j = ZWJ|ZWNJ;			# Joiners
 k = (Ra As H);			# Kinzi
 
 c = C|Ra;			# is_consonant
 
-medial_group = MY? MR? MW? MH? As?;
+medial_group = MY? As? MR? ((MW MH? | MH) As?)?;
 main_vowel_group = (VPre.VS?)* VAbv* VBlw* A* (DB As?)?;
 post_vowel_group = VPst MH? As* VAbv* A* (DB As?)?;
 pwo_tone_group = PT A* DB? As?;
 
 complex_syllable_tail = As* medial_group main_vowel_group post_vowel_group* pwo_tone_group* V* j?;
 syllable_tail = (H (c|IV).VS?)* (H | complex_syllable_tail);
 
 consonant_syllable =	(k|CS)? (c|IV|D|GB).VS? syllable_tail;
--- a/gfx/harfbuzz/src/hb-ot-shape.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape.cc
@@ -93,31 +93,40 @@ hb_ot_shape_planner_t::hb_ot_shape_plann
 
 void
 hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t           &plan,
 				const hb_ot_shape_plan_key_t &key)
 {
   plan.props = props;
   plan.shaper = shaper;
   map.compile (plan.map, key);
+#ifndef HB_NO_SHAPE_AAT
   if (apply_morx)
     aat_map.compile (plan.aat_map);
+#endif
 
+#ifndef HB_NO_OT_SHAPE_FRACTIONS
   plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
   plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r'));
   plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m'));
   plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
+#endif
+
   plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
   hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (props.direction) ?
 		      HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n');
+#ifndef HB_NO_OT_KERN
   plan.kern_mask = plan.map.get_mask (kern_tag);
+  plan.requested_kerning = !!plan.kern_mask;
+#endif
+#ifndef HB_NO_SHAPE_AAT
   plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k'));
+  plan.requested_tracking = !!plan.trak_mask;
+#endif
 
-  plan.requested_kerning = !!plan.kern_mask;
-  plan.requested_tracking = !!plan.trak_mask;
   bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX;
   bool disable_gpos = plan.shaper->gpos_tag &&
 		      plan.shaper->gpos_tag != plan.map.chosen_script[1];
 
   /*
    * Decide who provides glyph classes. GDEF or Unicode.
    */
 
@@ -147,50 +156,61 @@ hb_ot_shape_planner_t::compile (hb_ot_sh
 #ifndef HB_NO_SHAPE_AAT
   else if (hb_aat_layout_has_positioning (face))
     plan.apply_kerx = true;
 #endif
 
   if (!plan.apply_kerx && !has_gpos_kern)
   {
     /* Apparently Apple applies kerx if GPOS kern was not applied. */
-    if (0)
-      ;
 #ifndef HB_NO_SHAPE_AAT
-    else if (hb_aat_layout_has_positioning (face))
+    if (hb_aat_layout_has_positioning (face))
       plan.apply_kerx = true;
+    else
 #endif
-    else if (hb_ot_layout_has_kerning (face))
+#ifndef HB_NO_OT_KERN
+    if (hb_ot_layout_has_kerning (face))
       plan.apply_kern = true;
+#endif
   }
 
   plan.zero_marks = script_zero_marks &&
 		    !plan.apply_kerx &&
-		    (!plan.apply_kern || !hb_ot_layout_has_machine_kerning (face));
+		    (!plan.apply_kern
+#ifndef HB_NO_OT_KERN
+		     || !hb_ot_layout_has_machine_kerning (face)
+#endif
+		    );
   plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
 
   plan.adjust_mark_positioning_when_zeroing = !plan.apply_gpos &&
 					      !plan.apply_kerx &&
-					      (!plan.apply_kern || !hb_ot_layout_has_cross_kerning (face));
+					      (!plan.apply_kern
+#ifndef HB_NO_OT_KERN
+					       || !hb_ot_layout_has_cross_kerning (face)
+#endif
+					      );
 
   plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing &&
 				   script_fallback_mark_positioning;
 
 #ifndef HB_NO_SHAPE_AAT
   /* Currently we always apply trak. */
   plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
 #endif
 }
 
 bool
 hb_ot_shape_plan_t::init0 (hb_face_t                     *face,
 			   const hb_shape_plan_key_t     *key)
 {
   map.init ();
+#ifndef HB_NO_SHAPE_AAT
   aat_map.init ();
+#endif
 
   hb_ot_shape_planner_t planner (face,
 				 &key->props);
 
   hb_ot_shape_collect_features (&planner,
 				key->user_features,
 				key->num_user_features);
 
@@ -208,44 +228,54 @@ hb_ot_shape_plan_t::init0 (hb_face_t    
 
 void
 hb_ot_shape_plan_t::fini ()
 {
   if (shaper->data_destroy)
     shaper->data_destroy (const_cast<void *> (data));
 
   map.fini ();
+#ifndef HB_NO_SHAPE_AAT
   aat_map.fini ();
+#endif
 }
 
 void
 hb_ot_shape_plan_t::substitute (hb_font_t   *font,
 				hb_buffer_t *buffer) const
 {
+#ifndef HB_NO_SHAPE_AAT
   if (unlikely (apply_morx))
     hb_aat_layout_substitute (this, font, buffer);
   else
+#endif
     map.substitute (this, font, buffer);
 }
 
 void
 hb_ot_shape_plan_t::position (hb_font_t   *font,
 			      hb_buffer_t *buffer) const
 {
   if (this->apply_gpos)
     map.position (this, font, buffer);
+#ifndef HB_NO_SHAPE_AAT
   else if (this->apply_kerx)
     hb_aat_layout_position (this, font, buffer);
+#endif
+#ifndef HB_NO_OT_KERN
   else if (this->apply_kern)
     hb_ot_layout_kern (this, font, buffer);
+#endif
   else
     _hb_ot_shape_fallback_kern (this, font, buffer);
 
+#ifndef HB_NO_SHAPE_AAT
   if (this->apply_trak)
     hb_aat_layout_track (this, font, buffer);
+#endif
 }
 
 
 static const hb_ot_map_feature_t
 common_features[] =
 {
   {HB_TAG('c','c','m','p'), F_GLOBAL},
   {HB_TAG('l','o','c','l'), F_GLOBAL},
@@ -287,28 +317,32 @@ hb_ot_shape_collect_features (hb_ot_shap
       break;
     case HB_DIRECTION_TTB:
     case HB_DIRECTION_BTT:
     case HB_DIRECTION_INVALID:
     default:
       break;
   }
 
+#ifndef HB_NO_OT_SHAPE_FRACTIONS
   /* Automatic fractions. */
   map->add_feature (HB_TAG ('f','r','a','c'));
   map->add_feature (HB_TAG ('n','u','m','r'));
   map->add_feature (HB_TAG ('d','n','o','m'));
+#endif
 
   /* Random! */
   map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE);
 
+#ifndef HB_NO_SHAPE_AAT
   /* Tracking.  We enable dummy feature here just to allow disabling
    * AAT 'trak' table using features.
    * https://github.com/harfbuzz/harfbuzz/issues/1303 */
   map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK);
+#endif
 
   map->enable_feature (HB_TAG ('H','A','R','F'));
 
   if (planner->shaper->collect_features)
     planner->shaper->collect_features (planner);
 
   map->enable_feature (HB_TAG ('B','U','Z','Z'));
 
@@ -331,25 +365,27 @@ hb_ot_shape_collect_features (hb_ot_shap
   {
     const hb_feature_t *feature = &user_features[i];
     map->add_feature (feature->tag,
 		      (feature->start == HB_FEATURE_GLOBAL_START &&
 		       feature->end == HB_FEATURE_GLOBAL_END) ?  F_GLOBAL : F_NONE,
 		      feature->value);
   }
 
+#ifndef HB_NO_SHAPE_AAT
   if (planner->apply_morx)
   {
     hb_aat_map_builder_t *aat_map = &planner->aat_map;
     for (unsigned int i = 0; i < num_user_features; i++)
     {
       const hb_feature_t *feature = &user_features[i];
       aat_map->add_feature (feature->tag, feature->value);
     }
   }
+#endif
 
   if (planner->shaper->override_features)
     planner->shaper->override_features (planner);
 }
 
 
 /*
  * shaper face data
@@ -564,16 +600,20 @@ hb_ot_mirror_chars (const hb_ot_shape_co
     else
       info[i].codepoint = codepoint;
   }
 }
 
 static inline void
 hb_ot_shape_setup_masks_fraction (const hb_ot_shape_context_t *c)
 {
+#ifdef HB_NO_OT_SHAPE_FRACTIONS
+  return;
+#endif
+
   if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
       !c->plan->has_frac)
     return;
 
   hb_buffer_t *buffer = c->buffer;
 
   hb_mask_t pre_mask, post_mask;
   if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
@@ -774,18 +814,20 @@ hb_ot_substitute_pre (const hb_ot_shape_
 
   hb_ot_substitute_complex (c);
 }
 
 static inline void
 hb_ot_substitute_post (const hb_ot_shape_context_t *c)
 {
   hb_ot_hide_default_ignorables (c->buffer, c->font);
+#ifndef HB_NO_SHAPE_AAT
   if (c->plan->apply_morx)
     hb_aat_layout_remove_deleted_glyphs (c->buffer);
+#endif
 
   if (c->plan->shaper->postprocess_glyphs)
     c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
 }
 
 
 /*
  * Position
@@ -909,18 +951,20 @@ hb_ot_position_complex (const hb_ot_shap
       case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
       case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
 	break;
     }
 
   /* Finish off.  Has to follow a certain order. */
   hb_ot_layout_position_finish_advances (c->font, c->buffer);
   hb_ot_zero_width_default_ignorables (c->buffer);
+#ifndef HB_NO_SHAPE_AAT
   if (c->plan->apply_morx)
     hb_aat_layout_zero_width_deleted_glyphs (c->buffer);
+#endif
   hb_ot_layout_position_finish_offsets (c->font, c->buffer);
 
   /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
   if (c->font->has_glyph_h_origin_func ())
     for (unsigned int i = 0; i < count; i++)
       c->font->subtract_glyph_h_origin (info[i].codepoint,
 					&pos[i].x_offset,
 					&pos[i].y_offset);
--- a/gfx/harfbuzz/src/hb-ot-shape.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape.hh
@@ -60,32 +60,62 @@ struct hb_shape_plan_key_t;
 
 struct hb_ot_shape_plan_t
 {
   hb_segment_properties_t props;
   const struct hb_ot_complex_shaper_t *shaper;
   hb_ot_map_t map;
   hb_aat_map_t aat_map;
   const void *data;
+#ifndef HB_NO_OT_SHAPE_FRACTIONS
   hb_mask_t frac_mask, numr_mask, dnom_mask;
+#else
+  static constexpr hb_mask_t frac_mask = 0;
+  static constexpr hb_mask_t numr_mask = 0;
+  static constexpr hb_mask_t dnom_mask = 0;
+#endif
   hb_mask_t rtlm_mask;
+#ifndef HB_NO_OT_KERN
   hb_mask_t kern_mask;
+#else
+  static constexpr hb_mask_t kern_mask = 0;
+#endif
+#ifndef HB_NO_SHAPE_AAT
   hb_mask_t trak_mask;
+#else
+  static constexpr hb_mask_t trak_mask = 0;
+#endif
 
+#ifndef HB_NO_OT_KERN
   bool requested_kerning : 1;
+#else
+  static constexpr bool requested_kerning = false;
+#endif
+#ifndef HB_NO_SHAPE_AAT
   bool requested_tracking : 1;
+#else
+  static constexpr bool requested_tracking = false;
+#endif
+#ifndef HB_NO_OT_SHAPE_FRACTIONS
   bool has_frac : 1;
+#else
+  static constexpr bool has_frac = false;
+#endif
   bool has_gpos_mark : 1;
   bool zero_marks : 1;
   bool fallback_glyph_classes : 1;
   bool fallback_mark_positioning : 1;
   bool adjust_mark_positioning_when_zeroing : 1;
 
   bool apply_gpos : 1;
+#ifndef HB_NO_OT_KERN
   bool apply_kern : 1;
+#else
+  static constexpr bool apply_kern = false;
+#endif
 #ifndef HB_NO_SHAPE_AAT
   bool apply_kerx : 1;
   bool apply_morx : 1;
   bool apply_trak : 1;
 #else
   static constexpr bool apply_kerx = false;
   static constexpr bool apply_morx = false;
   static constexpr bool apply_trak = false;
--- a/gfx/harfbuzz/src/hb-ot-stat-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-stat-table.hh
@@ -54,24 +54,24 @@ enum
 						 * value represents the “normal” value
 						 * for the axis and may be omitted when
 						 * composing name strings. */
   // Reserved = 0xFFFC				/* Reserved for future use — set to zero. */
 };
 
 struct AxisValueFormat1
 {
+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this)));
   }
 
-  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
-
   protected:
   HBUINT16	format;		/* Format identifier — set to 1. */
   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
 				 * identifying the axis of design variation
 				 * to which the axis value record applies.
 				 * Must be less than designAxisCount. */
   HBUINT16	flags;		/* Flags — see below for details. */
   NameID	valueNameID;	/* The name ID for entries in the 'name' table
@@ -79,24 +79,24 @@ struct AxisValueFormat1
 				 * attribute value. */
   Fixed		value;		/* A numeric value for this attribute value. */
   public:
   DEFINE_SIZE_STATIC (12);
 };
 
 struct AxisValueFormat2
 {
+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this)));
   }
 
-  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
-
   protected:
   HBUINT16	format;		/* Format identifier — set to 2. */
   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
 				 * identifying the axis of design variation
 				 * to which the axis value record applies.
 				 * Must be less than designAxisCount. */
   HBUINT16	flags;		/* Flags — see below for details. */
   NameID	valueNameID;	/* The name ID for entries in the 'name' table
@@ -108,24 +108,24 @@ struct AxisValueFormat2
   Fixed		rangeMaxValue;	/* The maximum value for a range associated
 				 * with the specified name ID. */
   public:
   DEFINE_SIZE_STATIC (20);
 };
 
 struct AxisValueFormat3
 {
+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this)));
   }
 
-  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
-
   protected:
   HBUINT16	format;		/* Format identifier — set to 3. */
   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
 				 * identifying the axis of design variation
 				 * to which the axis value record applies.
 				 * Must be less than designAxisCount. */
   HBUINT16	flags;		/* Flags — see below for details. */
   NameID	valueNameID;	/* The name ID for entries in the 'name' table
@@ -152,24 +152,24 @@ struct AxisValueRecord
 				 * applies. Must be less than designAxisCount. */
   Fixed		value;		/* A numeric value for this attribute value. */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
 struct AxisValueFormat4
 {
+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this)));
   }
 
-  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
-
   protected:
   HBUINT16	format;		/* Format identifier — set to 4. */
   HBUINT16	axisCount;	/* The total number of axes contributing to
 				 * this axis-values combination. */
   HBUINT16	flags;		/* Flags — see below for details. */
   NameID	valueNameID;	/* The name ID for entries in the 'name' table
 				 * that provide a display string for this
 				 * attribute value. */
@@ -178,41 +178,41 @@ struct AxisValueFormat4
 				 * combination of axis values, one for each
 				 * contributing axis. */
   public:
   DEFINE_SIZE_ARRAY (8, axisValues);
 };
 
 struct AxisValue
 {
+  hb_ot_name_id_t get_value_name_id () const
+  {
+    switch (u.format)
+    {
+    case 1: return u.format1.get_value_name_id ();
+    case 2: return u.format2.get_value_name_id ();
+    case 3: return u.format3.get_value_name_id ();
+    case 4: return u.format4.get_value_name_id ();
+    default:return HB_OT_NAME_ID_INVALID;
+    }
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
       return_trace (false);
 
     switch (u.format)
     {
-    case 1:  return_trace (likely (u.format1.sanitize (c)));
-    case 2:  return_trace (likely (u.format2.sanitize (c)));
-    case 3:  return_trace (likely (u.format3.sanitize (c)));
-    case 4:  return_trace (likely (u.format4.sanitize (c)));
-    default: return_trace (true);
-    }
-  }
-
-  hb_ot_name_id_t get_value_name_id () const
-  {
-    switch (u.format)
-    {
-      case 1: return u.format1.get_value_name_id ();
-      case 2: return u.format2.get_value_name_id ();
-      case 3: return u.format3.get_value_name_id ();
-      case 4: return u.format4.get_value_name_id ();
-      default: return HB_OT_NAME_ID_INVALID;
+    case 1: return_trace (u.format1.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+    case 3: return_trace (u.format3.sanitize (c));
+    case 4: return_trace (u.format4.sanitize (c));
+    default:return_trace (true);
     }
   }
 
   protected:
   union
   {
   HBUINT16		format;
   AxisValueFormat1	format1;
@@ -221,49 +221,39 @@ struct AxisValue
   AxisValueFormat4	format4;
   } u;
   public:
   DEFINE_SIZE_UNION (2, format);
 };
 
 struct StatAxisRecord
 {
+  hb_ot_name_id_t get_name_id () const { return nameID; }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this)));
   }
 
-  hb_ot_name_id_t get_name_id () const { return nameID; }
-
   protected:
   Tag		tag;		/* A tag identifying the axis of design variation. */
   NameID	nameID;		/* The name ID for entries in the 'name' table that
 				 * provide a display string for this axis. */
   HBUINT16	ordering;	/* A value that applications can use to determine
 				 * primary sorting of face names, or for ordering
 				 * of descriptors when composing family or face names. */
   public:
   DEFINE_SIZE_STATIC (8);
 };
 
 struct STAT
 {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_STAT;
 
-  bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-			  version.major == 1 &&
-                          version.minor > 0 &&
-			  designAxesOffset.sanitize (c, this, designAxisCount) &&
-			  offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets))));
-  }
-
   bool has_data () const { return version.to_int (); }
 
   unsigned get_design_axis_count () const { return designAxisCount; }
 
   hb_ot_name_id_t get_axis_record_name_id (unsigned axis_record_index) const
   {
     if (unlikely (axis_record_index >= designAxisCount)) return HB_OT_NAME_ID_INVALID;
     const StatAxisRecord &axis_record = get_design_axes ()[axis_record_index];
@@ -290,16 +280,26 @@ struct STAT
 
     + get_axis_value_offsets ()
     | hb_map (hb_add (&(this + offsetToAxisValueOffsets)))
     | hb_map (&AxisValue::get_value_name_id)
     | hb_sink (nameids_to_retain)
     ;
   }
 
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+			  version.major == 1 &&
+			  version.minor > 0 &&
+			  designAxesOffset.sanitize (c, this, designAxisCount) &&
+			  offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets))));
+  }
+
   protected:
   hb_array_t<const StatAxisRecord> const get_design_axes () const
   { return (this+designAxesOffset).as_array (designAxisCount); }
 
   hb_array_t<const OffsetTo<AxisValue>> const get_axis_value_offsets () const
   { return (this+offsetToAxisValueOffsets).as_array (axisValueCount); }
 
 
--- a/gfx/harfbuzz/src/hb-ot-tag.cc
+++ b/gfx/harfbuzz/src/hb-ot-tag.cc
@@ -140,17 +140,19 @@ hb_ot_all_tags_from_script (hb_script_t 
 			    unsigned int *count /* IN/OUT */,
 			    hb_tag_t     *tags /* OUT */)
 {
   unsigned int i = 0;
 
   hb_tag_t new_tag = hb_ot_new_tag_from_script (script);
   if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT))
   {
-    tags[i++] = new_tag | '3';
+    /* HB_SCRIPT_MYANMAR maps to 'mym2', but there is no 'mym3'. */
+    if (new_tag != HB_TAG('m','y','m','2'))
+      tags[i++] = new_tag | '3';
     if (*count > i)
       tags[i++] = new_tag;
   }
 
   if (*count > i)
   {
     hb_tag_t old_tag = hb_ot_old_tag_from_script (script);
     if (old_tag != HB_OT_TAG_DEFAULT_SCRIPT)
@@ -298,38 +300,38 @@ hb_ot_tags_from_language (const char   *
 
 static bool
 parse_private_use_subtag (const char     *private_use_subtag,
 			  unsigned int   *count,
 			  hb_tag_t       *tags,
 			  const char     *prefix,
 			  unsigned char (*normalize) (unsigned char))
 {
-  if (private_use_subtag && count && tags && *count)
-  {
-    const char *s = strstr (private_use_subtag, prefix);
-    if (s)
-    {
-      char tag[4];
-      int i;
-      s += strlen (prefix);
-      for (i = 0; i < 4 && ISALNUM (s[i]); i++)
-	tag[i] = normalize (s[i]);
-      if (i)
-      {
-	for (; i < 4; i++)
-	  tag[i] = ' ';
-	tags[0] = HB_TAG (tag[0], tag[1], tag[2], tag[3]);
-	if ((tags[0] & 0xDFDFDFDF) == HB_OT_TAG_DEFAULT_SCRIPT)
-	  tags[0] ^= ~0xDFDFDFDF;
-	*count = 1;
-	return false;
-      }
-    }
-  }
+#ifdef HB_NO_LANGUAGE_PRIVATE_SUBTAG
+  return false;
+#endif
+
+  if (!(private_use_subtag && count && tags && *count)) return false;
+
+  const char *s = strstr (private_use_subtag, prefix);
+  if (!s) return false;
+
+  char tag[4];
+  int i;
+  s += strlen (prefix);
+  for (i = 0; i < 4 && ISALNUM (s[i]); i++)
+    tag[i] = normalize (s[i]);
+  if (!i) return false;
+
+  for (; i < 4; i++)
+    tag[i] = ' ';
+  tags[0] = HB_TAG (tag[0], tag[1], tag[2], tag[3]);
+  if ((tags[0] & 0xDFDFDFDF) == HB_OT_TAG_DEFAULT_SCRIPT)
+    tags[0] ^= ~0xDFDFDFDF;
+  *count = 1;
   return true;
 }
 
 /**
  * hb_ot_tags_from_script_and_language:
  * @script: an #hb_script_t to convert.
  * @language: an #hb_language_t to convert.
  * @script_count: (allow-none): maximum number of script tags to retrieve (IN)
@@ -387,18 +389,18 @@ hb_ot_tags_from_script_and_language (hb_
 	    limit = s - 1;
 	  }
 	}
       }
       if (!limit)
 	limit = s;
     }
 
-    needs_script = parse_private_use_subtag (private_use_subtag, script_count, script_tags, "-hbsc", TOLOWER);
-    needs_language = parse_private_use_subtag (private_use_subtag, language_count, language_tags, "-hbot", TOUPPER);
+    needs_script = !parse_private_use_subtag (private_use_subtag, script_count, script_tags, "-hbsc", TOLOWER);
+    needs_language = !parse_private_use_subtag (private_use_subtag, language_count, language_tags, "-hbot", TOUPPER);
 
     if (needs_language && language_count && language_tags && *language_count)
       hb_ot_tags_from_language (lang_str, limit, language_count, language_tags);
   }
 
   if (needs_script && script_count && script_tags && *script_count)
     hb_ot_all_tags_from_script (script, script_count, script_tags);
 }
--- a/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh
@@ -72,19 +72,19 @@ struct MVAR
 				  valueRecordCount,
 				  valueRecordSize));
   }
 
   float get_var (hb_tag_t tag,
 		 const int *coords, unsigned int coord_count) const
   {
     const VariationValueRecord *record;
-    record = (VariationValueRecord *) bsearch (&tag, valuesZ.arrayZ,
-					       valueRecordCount, valueRecordSize,
-					       tag_compare);
+    record = (VariationValueRecord *) hb_bsearch (&tag, valuesZ.arrayZ,
+						  valueRecordCount, valueRecordSize,
+						  tag_compare);
     if (!record)
       return 0.;
 
     return (this+varStore).get_delta (record->varIdx, coords, coord_count);
   }
 
 protected:
   static int tag_compare (const void *pa, const void *pb)
--- a/gfx/harfbuzz/src/hb-ot-var.cc
+++ b/gfx/harfbuzz/src/hb-ot-var.cc
@@ -19,23 +19,25 @@
  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-open-type.hh"
+#include "hb.hh"
 
-#include "hb-ot-face.hh"
+#ifndef HB_NO_VAR
+
+#include "hb-ot-var.h"
+
 #include "hb-ot-var-avar-table.hh"
 #include "hb-ot-var-fvar-table.hh"
 #include "hb-ot-var-mvar-table.hh"
-#include "hb-ot-var.h"
 
 
 /**
  * SECTION:hb-ot-var
  * @title: hb-ot-var
  * @short_description: OpenType Font Variations
  * @include: hb-ot.h
  *
@@ -208,8 +210,11 @@ hb_ot_var_normalize_coords (hb_face_t   
 			    int *normalized_coords /* OUT */)
 {
   const OT::fvar &fvar = *face->table.fvar;
   for (unsigned int i = 0; i < coords_length; i++)
     normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]);
 
   face->table.avar->map_coords (normalized_coords, coords_length);
 }
+
+
+#endif
--- a/gfx/harfbuzz/src/hb-ot-vorg-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-vorg-table.hh
@@ -64,112 +64,60 @@ struct VORG
   int get_y_origin (hb_codepoint_t glyph) const
   {
     unsigned int i;
     if (!vertYOrigins.bfind (glyph, &i))
       return defaultVertOriginY;
     return vertYOrigins[i].vertOriginY;
   }
 
-  bool _subset (const hb_subset_plan_t *plan HB_UNUSED,
-		const VORG *vorg_table,
-		const hb_vector_t<VertOriginMetric> &subset_metrics,
-		unsigned int dest_sz,
-		void *dest) const
+  template <typename Iterator,
+            hb_requires (hb_is_iterator (Iterator))>
+  void serialize (hb_serialize_context_t *c,
+                  Iterator it,
+                  FWORD defaultVertOriginY)
   {
-    hb_serialize_context_t c (dest, dest_sz);
 
-    VORG *subset_table = c.start_serialize<VORG> ();
-    if (unlikely (!c.extend_min (*subset_table)))
-      return false;
-
-    subset_table->version.major = 1;
-    subset_table->version.minor = 0;
+    if (unlikely (!c->extend_min ((*this))))  return;
 
-    subset_table->defaultVertOriginY = vorg_table->defaultVertOriginY;
-    subset_table->vertYOrigins.len = subset_metrics.length;
+    this->version.major = 1;
+    this->version.minor = 0;
 
-    bool success = true;
-    if (subset_metrics.length > 0)
-    {
-      unsigned int  size = VertOriginMetric::static_size * subset_metrics.length;
-      VertOriginMetric  *metrics = c.allocate_size<VertOriginMetric> (size);
-      if (likely (metrics != nullptr))
-        memcpy (metrics, &subset_metrics[0], size);
-      else
-        success = false;
-    }
-    c.end_serialize ();
+    this->defaultVertOriginY = defaultVertOriginY;
+    this->vertYOrigins.len = it.len ();
 
-    return success;
+    + it
+    | hb_apply ([c] (const VertOriginMetric& _) { c->copy (_);})
+    ;
   }
 
-  bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_context_t *c) const
   {
-    hb_blob_t *vorg_blob = hb_sanitize_context_t().reference_table<VORG> (plan->source);
-    const VORG *vorg_table = vorg_blob->as<VORG> ();
-
-    /* count the number of glyphs to be included in the subset table */
-    hb_vector_t<VertOriginMetric> subset_metrics;
-    subset_metrics.init ();
-
-
-    hb_codepoint_t old_glyph = HB_SET_VALUE_INVALID;
-    unsigned int i = 0;
-    while (i < vertYOrigins.len
-           && plan->glyphset ()->next (&old_glyph))
-    {
-      while (old_glyph > vertYOrigins[i].glyph)
-      {
-        i++;
-        if (i >= vertYOrigins.len)
-          break;
-      }
+    TRACE_SUBSET (this);
+    VORG *vorg_prime = c->serializer->start_embed<VORG> ();
+    if (unlikely (!c->serializer->check_success (vorg_prime))) return_trace (false);
 
-      if (old_glyph == vertYOrigins[i].glyph)
-      {
-        hb_codepoint_t new_glyph;
-        if (plan->new_gid_for_old_gid (old_glyph, &new_glyph))
-        {
-          VertOriginMetric *metrics = subset_metrics.push ();
-          metrics->glyph = new_glyph;
-          metrics->vertOriginY = vertYOrigins[i].vertOriginY;
-        }
-      }
-    }
+    auto it =
+    + vertYOrigins.as_array ()
+    | hb_filter (c->plan->glyphset (), &VertOriginMetric::glyph)
+    | hb_map ([&] (const VertOriginMetric& _)
+              {
+                hb_codepoint_t new_glyph = HB_SET_VALUE_INVALID;
+                c->plan->new_gid_for_old_gid (_.glyph, &new_glyph);
 
-    /* alloc the new table */
-    unsigned int dest_sz = VORG::min_size + VertOriginMetric::static_size * subset_metrics.length;
-    void *dest = (void *) malloc (dest_sz);
-    if (unlikely (!dest))
-    {
-      subset_metrics.fini ();
-      hb_blob_destroy (vorg_blob);
-      return false;
-    }
+                VertOriginMetric metric;
+                metric.glyph = new_glyph;
+                metric.vertOriginY = _.vertOriginY;
+                return metric;
+              })
+    ;
 
     /* serialize the new table */
-    if (!_subset (plan, vorg_table, subset_metrics, dest_sz, dest))
-    {
-      subset_metrics.fini ();
-      free (dest);
-      hb_blob_destroy (vorg_blob);
-      return false;
-    }
-
-    hb_blob_t *result = hb_blob_create ((const char *)dest,
-                                        dest_sz,
-                                        HB_MEMORY_MODE_READONLY,
-                                        dest,
-                                        free);
-    bool success = plan->add_table (HB_OT_TAG_VORG, result);
-    hb_blob_destroy (result);
-    subset_metrics.fini ();
-    hb_blob_destroy (vorg_blob);
-    return success;
+    vorg_prime->serialize (c->serializer, it, defaultVertOriginY);
+    return_trace (true);
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                   version.major == 1 &&
                   vertYOrigins.sanitize (c));
--- a/gfx/harfbuzz/src/hb-serialize.hh
+++ b/gfx/harfbuzz/src/hb-serialize.hh
@@ -370,17 +370,17 @@ struct hb_serialize_context_t
   Type *embed (const Type &obj)
   { return embed (hb_addressof (obj)); }
 
   template <typename Type, typename ...Ts> auto
   _copy (const Type &src, hb_priority<1>, Ts&&... ds) HB_RETURN
   (Type *, src.copy (this, hb_forward<Ts> (ds)...))
 
   template <typename Type> auto
-  _copy (const Type &src, hb_priority<0>) -> decltype (&(src = src))
+  _copy (const Type &src, hb_priority<0>) -> decltype (&(hb_declval<Type> () = src))
   {
     Type *ret = this->allocate_size<Type> (sizeof (Type));
     if (unlikely (!ret)) return nullptr;
     *ret = src;
     return ret;
   }
 
   /* Like embed, but active: calls obj.operator=() or obj.copy() to transfer data
--- a/gfx/harfbuzz/src/hb-shaper-list.hh
+++ b/gfx/harfbuzz/src/hb-shaper-list.hh
@@ -42,11 +42,11 @@ HB_SHAPER_IMPLEMENT (uniscribe)
 #endif
 #ifdef HAVE_DIRECTWRITE
 HB_SHAPER_IMPLEMENT (directwrite)
 #endif
 #ifdef HAVE_CORETEXT
 HB_SHAPER_IMPLEMENT (coretext)
 #endif
 
-#ifdef HAVE_FALLBACK
+#ifndef HB_NO_FALLBACK_SHAPE
 HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */
 #endif
--- a/gfx/harfbuzz/src/hb-static.cc
+++ b/gfx/harfbuzz/src/hb-static.cc
@@ -34,18 +34,18 @@
 #include "hb-ot-layout-common.hh"
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-head-table.hh"
 #include "hb-ot-maxp-table.hh"
 
 #ifndef HB_NO_VISIBILITY
 #include "hb-ot-name-language-static.hh"
 
-hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
-/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
+uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
+/*thread_local*/ uint64_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
 
 DEFINE_NULL_NAMESPACE_BYTES (OT, Index) =  {0xFF,0xFF};
 DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
 DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00};
 DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00};
 DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF};
 /* Hand-coded because Lookup is a template.  Sad. */
 const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
--- a/gfx/harfbuzz/src/hb-subset-cff-common.cc
+++ b/gfx/harfbuzz/src/hb-subset-cff-common.cc
@@ -19,16 +19,20 @@
  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Adobe Author(s): Michiharu Ariza
  */
 
+#include "hb.hh"
+
+#ifndef HB_NO_SUBSET_CFF
+
 #include "hb-ot-cff-common.hh"
 #include "hb-ot-cff2-table.hh"
 #include "hb-subset-cff-common.hh"
 
 /* Disable FDSelect format 0 for compatibility with fonttools which doesn't seem choose it.
  * Rarely any/much smaller than format 3 anyway. */
 #define CFF_SERIALIZE_FDSELECT_0  0
 
@@ -39,43 +43,43 @@ using namespace CFF;
  * Determine an optimal FDSelect format according to a provided plan.
  *
  * Return value: FDSelect format, size, and ranges for the most compact subset FDSelect
  * along with a font index remapping table
  **/
 
 bool
 hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
-			    unsigned int fdCount,
-			    const FDSelect &src, /* IN */
-			    unsigned int &subset_fd_count /* OUT */,
-			    unsigned int &subset_fdselect_size /* OUT */,
-			    unsigned int &subset_fdselect_format /* OUT */,
-			    hb_vector_t<code_pair_t> &fdselect_ranges /* OUT */,
-			    remap_t &fdmap /* OUT */)
+			     unsigned int fdCount,
+			     const FDSelect &src, /* IN */
+			     unsigned int &subset_fd_count /* OUT */,
+			     unsigned int &subset_fdselect_size /* OUT */,
+			     unsigned int &subset_fdselect_format /* OUT */,
+			     hb_vector_t<code_pair_t> &fdselect_ranges /* OUT */,
+			     hb_inc_bimap_t &fdmap /* OUT */)
 {
   subset_fd_count = 0;
   subset_fdselect_size = 0;
   subset_fdselect_format = 0;
-  unsigned int  num_ranges = 0;
+  unsigned int num_ranges = 0;
 
   unsigned int subset_num_glyphs = plan->num_output_glyphs ();
   if (subset_num_glyphs == 0)
     return true;
 
   {
     /* use hb_set to determine the subset of font dicts */
-    hb_set_t  *set = hb_set_create ();
+    hb_set_t *set = hb_set_create ();
     if (set == &Null (hb_set_t))
       return false;
-    hb_codepoint_t  prev_fd = CFF_UNDEF_CODE;
+    hb_codepoint_t prev_fd = CFF_UNDEF_CODE;
     for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++)
     {
-      hb_codepoint_t	glyph;
-      hb_codepoint_t  	fd;
+      hb_codepoint_t glyph;
+      hb_codepoint_t fd;
       if (!plan->old_gid_for_new_gid (i, &glyph))
       {
 	/* fonttools retains FDSelect & font dicts for missing glyphs. do the same */
 	glyph = i;
       }
       fd = src.get_fd (glyph);
       set->add (fd);
 
@@ -93,27 +97,23 @@ hb_plan_subset_cff_fdselect (const hb_su
     {
       /* all font dicts belong to the subset. no need to subset FDSelect & FDArray */
       fdmap.identity (fdCount);
       hb_set_destroy (set);
     }
     else
     {
       /* create a fdmap */
-      if (!fdmap.reset (fdCount))
-      {
-	hb_set_destroy (set);
-	return false;
-      }
+      fdmap.reset ();
 
-      hb_codepoint_t  fd = CFF_UNDEF_CODE;
+      hb_codepoint_t fd = CFF_UNDEF_CODE;
       while (set->next (&fd))
 	fdmap.add (fd);
       hb_set_destroy (set);
-      if (unlikely (fdmap.get_count () != subset_fd_count))
+      if (unlikely (fdmap.get_population () != subset_fd_count))
       	return false;
     }
 
     /* update each font dict index stored as "code" in fdselect_ranges */
     for (unsigned int i = 0; i < fdselect_ranges.length; i++)
       fdselect_ranges[i].code = fdmap[fdselect_ranges[i].code];
   }
 
@@ -147,87 +147,82 @@ hb_plan_subset_cff_fdselect (const hb_su
   }
 
   return true;
 }
 
 template <typename FDSELECT3_4>
 static inline bool
 serialize_fdselect_3_4 (hb_serialize_context_t *c,
-			  const unsigned int num_glyphs,
-			  const FDSelect &src,
-			  unsigned int size,
-			  const hb_vector_t<code_pair_t> &fdselect_ranges)
+			const unsigned int num_glyphs,
+			const FDSelect &src,
+			unsigned int size,
+			const hb_vector_t<code_pair_t> &fdselect_ranges)
 {
   TRACE_SERIALIZE (this);
   FDSELECT3_4 *p = c->allocate_size<FDSELECT3_4> (size);
   if (unlikely (p == nullptr)) return_trace (false);
   p->nRanges () = fdselect_ranges.length;
   for (unsigned int i = 0; i < fdselect_ranges.length; i++)
   {
     p->ranges[i].first = fdselect_ranges[i].glyph;
     p->ranges[i].fd = fdselect_ranges[i].code;
   }
-  p->sentinel() = num_glyphs;
+  p->sentinel () = num_glyphs;
   return_trace (true);
 }
 
 /**
  * hb_serialize_cff_fdselect
  * Serialize a subset FDSelect format planned above.
  **/
 bool
 hb_serialize_cff_fdselect (hb_serialize_context_t *c,
-			  const unsigned int num_glyphs,
-			  const FDSelect &src,
-			  unsigned int fd_count,
-			  unsigned int fdselect_format,
-			  unsigned int size,
-			  const hb_vector_t<code_pair_t> &fdselect_ranges)
+			   const unsigned int num_glyphs,
+			   const FDSelect &src,
+			   unsigned int fd_count,
+			   unsigned int fdselect_format,
+			   unsigned int size,
+			   const hb_vector_t<code_pair_t> &fdselect_ranges)
 {
   TRACE_SERIALIZE (this);
-  FDSelect  *p = c->allocate_min<FDSelect> ();
+  FDSelect *p = c->allocate_min<FDSelect> ();
   if (unlikely (p == nullptr)) return_trace (false);
   p->format = fdselect_format;
   size -= FDSelect::min_size;
 
   switch (fdselect_format)
   {
 #if CFF_SERIALIZE_FDSELECT_0
-    case 0:
+  case 0:
+  {
+    FDSelect0 *p = c->allocate_size<FDSelect0> (size);
+    if (unlikely (p == nullptr)) return_trace (false);
+    unsigned int range_index = 0;
+    unsigned int fd = fdselect_ranges[range_index++].code;
+    for (unsigned int i = 0; i < num_glyphs; i++)
     {
-      FDSelect0 *p = c->allocate_size<FDSelect0> (size);
-      if (unlikely (p == nullptr)) return_trace (false);
-      unsigned int range_index = 0;
-      unsigned int  fd = fdselect_ranges[range_index++].code;
-      for (unsigned int i = 0; i < num_glyphs; i++)
+      if ((range_index < fdselect_ranges.len) &&
+	  (i >= fdselect_ranges[range_index].glyph))
       {
-	if ((range_index < fdselect_ranges.len) &&
-	    (i >= fdselect_ranges[range_index].glyph))
-	{
-	  fd = fdselect_ranges[range_index++].code;
-	}
-	p->fds[i] = fd;
+	fd = fdselect_ranges[range_index++].code;
       }
-      break;
+      p->fds[i] = fd;
     }
+    return_trace (true);
+  }
 #endif /* CFF_SERIALIZE_FDSELECT_0 */
 
-    case 3:
-      return serialize_fdselect_3_4<FDSelect3> (c,
-						num_glyphs,
-						src,
-						size,
-						fdselect_ranges);
+  case 3:
+    return serialize_fdselect_3_4<FDSelect3> (c, num_glyphs, src,
+					      size, fdselect_ranges);
+
+  case 4:
+    return serialize_fdselect_3_4<FDSelect4> (c, num_glyphs, src,
+					      size, fdselect_ranges);
 
-    case 4:
-      return serialize_fdselect_3_4<FDSelect4> (c,
-						num_glyphs,
-						src,
-						size,
-						fdselect_ranges);
+  default:
+    return_trace (false);
+  }
+}
 
-    default:
-      assert(false);
-  }
 
-  return_trace (true);
-}
+#endif
--- a/gfx/harfbuzz/src/hb-subset-cff-common.hh
+++ b/gfx/harfbuzz/src/hb-subset-cff-common.hh
@@ -536,65 +536,55 @@ struct subr_subset_param_t
   parsed_cs_str_t	*parsed_charstring;
   parsed_cs_str_vec_t	*parsed_global_subrs;
   parsed_cs_str_vec_t	*parsed_local_subrs;
   hb_set_t      *global_closure;
   hb_set_t      *local_closure;
   bool	  drop_hints;
 };
 
-struct subr_remap_t : remap_t
+struct subr_remap_t : hb_inc_bimap_t
 {
   void create (hb_set_t *closure)
   {
     /* create a remapping of subroutine numbers from old to new.
      * no optimization based on usage counts. fonttools doesn't appear doing that either.
      */
-    reset (closure->get_max () + 1);
-    for (hb_codepoint_t old_num = 0; old_num < length; old_num++)
-    {
-      if (hb_set_has (closure, old_num))
-	add (old_num);
-    }
+    
+    hb_codepoint_t old_num = HB_SET_VALUE_INVALID;
+    while (hb_set_next (closure, &old_num))
+      add (old_num);
 
-    if (get_count () < 1240)
+    if (get_population () < 1240)
       bias = 107;
-    else if (get_count () < 33900)
+    else if (get_population () < 33900)
       bias = 1131;
     else
       bias = 32768;
   }
 
-  hb_codepoint_t operator[] (unsigned int old_num) const
-  {
-    if (old_num >= length)
-      return CFF_UNDEF_CODE;
-    else
-      return remap_t::operator[] (old_num);
-  }
-
   int biased_num (unsigned int old_num) const
   {
-    hb_codepoint_t new_num = (*this)[old_num];
+    hb_codepoint_t new_num = get (old_num);
     return (int)new_num - bias;
   }
 
   protected:
   int bias;
 };
 
-struct subr_remap_ts
+struct subr_remaps_t
 {
-  subr_remap_ts ()
+  subr_remaps_t ()
   {
     global_remap.init ();
     local_remaps.init ();
   }
 
-  ~subr_remap_ts () { fini (); }
+  ~subr_remaps_t () { fini (); }
 
   void init (unsigned int fdCount)
   {
     local_remaps.resize (fdCount);
     for (unsigned int i = 0; i < fdCount; i++)
       local_remaps[i].init ();
   }
 
@@ -760,17 +750,17 @@ struct subr_subsetter_t
       if (unlikely (!encode_str (parsed_charstrings[i], fd, buffArray[i])))
 	return false;
     }
     return true;
   }
 
   bool encode_subrs (const parsed_cs_str_vec_t &subrs, const subr_remap_t& remap, unsigned int fd, str_buff_vec_t &buffArray) const
   {
-    unsigned int  count = remap.get_count ();
+    unsigned int  count = remap.get_population ();
 
     if (unlikely (!buffArray.resize (count)))
       return false;
     for (unsigned int old_num = 0; old_num < subrs.length; old_num++)
     {
       hb_codepoint_t new_num = remap[old_num];
       if (new_num != CFF_UNDEF_CODE)
       {
@@ -1000,33 +990,33 @@ struct subr_subsetter_t
   const hb_subset_plan_t	*plan;
 
   subr_closures_t		closures;
 
   parsed_cs_str_vec_t		parsed_charstrings;
   parsed_cs_str_vec_t		parsed_global_subrs;
   hb_vector_t<parsed_cs_str_vec_t>  parsed_local_subrs;
 
-  subr_remap_ts			remaps;
+  subr_remaps_t			remaps;
 
   private:
   typedef typename SUBRS::count_type subr_count_type;
 };
 
 } /* namespace CFF */
 
 HB_INTERNAL bool
 hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
 			    unsigned int fdCount,
 			    const CFF::FDSelect &src, /* IN */
 			    unsigned int &subset_fd_count /* OUT */,
 			    unsigned int &subset_fdselect_size /* OUT */,
 			    unsigned int &subset_fdselect_format /* OUT */,
 			    hb_vector_t<CFF::code_pair_t> &fdselect_ranges /* OUT */,
-			    CFF::remap_t &fdmap /* OUT */);
+			    hb_inc_bimap_t &fdmap /* OUT */);
 
 HB_INTERNAL bool
 hb_serialize_cff_fdselect (hb_serialize_context_t *c,
 			  unsigned int num_glyphs,
 			  const CFF::FDSelect &src,
 			  unsigned int fd_count,
 			  unsigned int fdselect_format,
 			  unsigned int size,
--- a/gfx/harfbuzz/src/hb-subset-cff1.cc
+++ b/gfx/harfbuzz/src/hb-subset-cff1.cc
@@ -19,44 +19,47 @@
  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Adobe Author(s): Michiharu Ariza
  */
 
+#include "hb.hh"
+
+#ifndef HB_NO_SUBSET_CFF
+
 #include "hb-open-type.hh"
 #include "hb-ot-cff1-table.hh"
 #include "hb-set.h"
+#include "hb-bimap.hh"
 #include "hb-subset-cff1.hh"
 #include "hb-subset-plan.hh"
 #include "hb-subset-cff-common.hh"
 #include "hb-cff1-interp-cs.hh"
 
-#ifndef HB_NO_SUBSET_CFF
-
 using namespace CFF;
 
-struct remap_sid_t : remap_t
+struct remap_sid_t : hb_inc_bimap_t
 {
   unsigned int add (unsigned int sid)
   {
     if ((sid != CFF_UNDEF_SID) && !is_std_std (sid))
-      return offset_sid (remap_t::add (unoffset_sid (sid)));
+      return offset_sid (hb_inc_bimap_t::add (unoffset_sid (sid)));
     else
       return sid;
   }
 
   unsigned int operator[] (unsigned int sid) const
   {
     if (is_std_std (sid) || (sid == CFF_UNDEF_SID))
       return sid;
     else
-      return offset_sid (remap_t::operator [] (unoffset_sid (sid)));
+      return offset_sid (get (unoffset_sid (sid)));
   }
 
   static const unsigned int num_std_strings = 391;
 
   static bool is_std_std (unsigned int sid) { return sid < num_std_strings; }
   static unsigned int offset_sid (unsigned int sid) { return sid + num_std_strings; }
   static unsigned int unoffset_sid (unsigned int sid) { return sid - num_std_strings; }
 };
@@ -574,32 +577,31 @@ struct cff_subset_plan {
 
     return Charset::calculate_serialized_size (
 			subset_charset_format,
 			subset_charset_format? subset_charset_ranges.length: plan->num_output_glyphs ());
   }
 
   bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc)
   {
-    if (unlikely (!sidmap.reset (acc.stringIndex->count)))
-      return false;
+    sidmap.reset ();
 
     for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
     {
       unsigned int sid = acc.topDict.nameSIDs[i];
       if (sid != CFF_UNDEF_SID)
       {
 	(void)sidmap.add (sid);
 	topDictModSIDs[i] = sidmap[sid];
       }
     }
 
     if (acc.fdArray != &Null(CFF1FDArray))
       for (unsigned int i = 0; i < orig_fdcount; i++)
-	if (fdmap.includes (i))
+	if (fdmap.has (i))
 	  (void)sidmap.add (acc.fontDicts[i].fontName);
 
     return true;
   }
 
   bool create (const OT::cff1::accelerator_subset_t &acc,
 	       hb_subset_plan_t *plan)
   {
@@ -675,17 +677,17 @@ struct cff_subset_plan {
     else
       fdmap.identity (1);
 
     /* remove unused SIDs & reassign SIDs */
     {
       /* SIDs for name strings in dicts are added before glyph names so they fit in 16-bit int range */
       if (unlikely (!collect_sids_in_dicts (acc)))
 	return false;
-      if (unlikely (sidmap.get_count () > 0x8000))	/* assumption: a dict won't reference that many strings */
+      if (unlikely (sidmap.get_population () > 0x8000))	/* assumption: a dict won't reference that many strings */
       	return false;
       if (subset_charset)
 	offsets.charsetInfo.size = plan_subset_charset (acc, plan);
 
       topdict_mod.reassignSIDs (sidmap);
     }
 
     /* String INDEX */
@@ -732,17 +734,17 @@ struct cff_subset_plan {
       if (!offsets.localSubrsInfos.resize (orig_fdcount))
 	return false;
       if (!subset_localsubrs.resize (orig_fdcount))
 	return false;
       for (unsigned int fd = 0; fd < orig_fdcount; fd++)
       {
 	subset_localsubrs[fd].init ();
 	offsets.localSubrsInfos[fd].init ();
-	if (fdmap.includes (fd))
+	if (fdmap.has (fd))
 	{
 	  if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
 	    return false;
 
 	  unsigned int dataSize = subset_localsubrs[fd].total_size ();
 	  if (dataSize > 0)
 	  {
 	    offsets.localSubrsInfos[fd].offset = final_size;
@@ -783,17 +785,17 @@ struct cff_subset_plan {
     }
 
     /* FDArray (FDIndex) */
     if (acc.fdArray != &Null(CFF1FDArray)) {
       offsets.FDArrayInfo.offset = final_size;
       cff1_font_dict_op_serializer_t fontSzr;
       unsigned int dictsSize = 0;
       for (unsigned int i = 0; i < acc.fontDicts.length; i++)
-	if (fdmap.includes (i))
+	if (fdmap.has (i))
 	  dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr);
 
       offsets.FDArrayInfo.offSize = calcOffSize (dictsSize);
       if (unlikely (offsets.FDArrayInfo.offSize > 4))
       	return false;
       final_size += CFF1Index::calculate_serialized_size (offsets.FDArrayInfo.offSize, subset_fdcount, dictsSize);
     }
 
@@ -806,17 +808,17 @@ struct cff_subset_plan {
       	return false;
       final_size += CFF1CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->num_output_glyphs (), dataSize);
     }
 
     /* private dicts & local subrs */
     offsets.privateDictInfo.offset = final_size;
     for (unsigned int i = 0; i < orig_fdcount; i++)
     {
-      if (fdmap.includes (i))
+      if (fdmap.has (i))
       {
 	bool  has_localsubrs = offsets.localSubrsInfos[i].size > 0;
 	cff_private_dict_op_serializer_t privSzr (desubroutinize, plan->drop_hints);
 	unsigned int  priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr, has_localsubrs);
 	table_info_t  privInfo = { final_size, priv_size, 0 };
 	font_dict_values_mod_t fontdict_mod;
 	if (!acc.is_CID ())
 	  fontdict_mod.init ( &Null(cff1_font_dict_values_t), CFF_UNDEF_SID, privInfo );
@@ -850,17 +852,17 @@ struct cff_subset_plan {
   unsigned int    num_glyphs;
   unsigned int    orig_fdcount;
   unsigned int    subset_fdcount;
   unsigned int    subset_fdselect_format;
   hb_vector_t<code_pair_t>   subset_fdselect_ranges;
 
   /* font dict index remap table from fullset FDArray to subset FDArray.
    * set to CFF_UNDEF_CODE if excluded from subset */
-  remap_t   fdmap;
+  hb_inc_bimap_t   fdmap;
 
   str_buff_vec_t		subset_charstrings;
   str_buff_vec_t		subset_globalsubrs;
   hb_vector_t<str_buff_vec_t>	subset_localsubrs;
   hb_vector_t<font_dict_values_mod_t>  fontdicts_mod;
 
   bool		drop_hints;
 
@@ -1027,25 +1029,25 @@ static inline bool _write_cff1 (const cf
       return false;
     }
   }
 
   /* private dicts & local subrs */
   assert (plan.offsets.privateDictInfo.offset == (unsigned) (c.head - c.start));
   for (unsigned int i = 0; i < acc.privateDicts.length; i++)
   {
-    if (plan.fdmap.includes (i))
+    if (plan.fdmap.has (i))
     {
       PrivateDict  *pd = c.start_embed<PrivateDict> ();
       if (unlikely (pd == nullptr)) return false;
       unsigned int priv_size = plan.fontdicts_mod[plan.fdmap[i]].privateDictInfo.size;
       bool result;
       cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
       /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
-      unsigned int  subroffset = (plan.offsets.localSubrsInfos[i].size > 0)? priv_size: 0;
+      unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0;
       result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
       if (unlikely (!result))
       {
 	DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
 	return false;
       }
       if (plan.offsets.localSubrsInfos[i].size > 0)
       {
@@ -1116,9 +1118,10 @@ hb_subset_cff1 (hb_subset_plan_t *plan,
   bool result = likely (acc.is_valid ()) &&
 			_hb_subset_cff1 (acc, data, plan, prime);
   hb_blob_destroy (cff_blob);
   acc.fini ();
 
   return result;
 }
 
+
 #endif
--- a/gfx/harfbuzz/src/hb-subset-cff2.cc
+++ b/gfx/harfbuzz/src/hb-subset-cff2.cc
@@ -19,26 +19,28 @@
  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Adobe Author(s): Michiharu Ariza
  */
 
+#include "hb.hh"
+
+#ifndef HB_NO_SUBSET_CFF
+
 #include "hb-open-type.hh"
 #include "hb-ot-cff2-table.hh"
 #include "hb-set.h"
 #include "hb-subset-cff2.hh"
 #include "hb-subset-plan.hh"
 #include "hb-subset-cff-common.hh"
 #include "hb-cff2-interp-cs.hh"
 
-#ifndef HB_NO_SUBSET_CFF
-
 using namespace CFF;
 
 struct cff2_sub_table_offsets_t : cff_sub_table_offsets_t
 {
   cff2_sub_table_offsets_t ()
     : cff_sub_table_offsets_t (),
       varStoreOffset (0)
   {}
@@ -323,28 +325,25 @@ struct cff2_subset_plan {
       if (!offsets.localSubrsInfos.resize (orig_fdcount))
 	return false;
       if (!subset_localsubrs.resize (orig_fdcount))
 	return false;
       for (unsigned int fd = 0; fd < orig_fdcount; fd++)
       {
 	subset_localsubrs[fd].init ();
 	offsets.localSubrsInfos[fd].init ();
-	if (fdmap.includes (fd))
-	{
-	  if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
-	    return false;
+        if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
+          return false;
 
-	  unsigned int dataSize = subset_localsubrs[fd].total_size ();
-	  if (dataSize > 0)
-	  {
-	    offsets.localSubrsInfos[fd].offset = final_size;
-	    offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
-	    offsets.localSubrsInfos[fd].size = CFF2Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
-	  }
+        unsigned int dataSize = subset_localsubrs[fd].total_size ();
+        if (dataSize > 0)
+        {
+          offsets.localSubrsInfos[fd].offset = final_size;
+          offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
+          offsets.localSubrsInfos[fd].size = CFF2Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
 	}
       }
     }
 
     /* global subrs */
     offsets.globalSubrsInfo.offset = final_size;
     final_size += offsets.globalSubrsInfo.size;
 
@@ -375,17 +374,17 @@ struct cff2_subset_plan {
       fdmap.identity (1);
 
     /* FDArray (FDIndex) */
     {
       offsets.FDArrayInfo.offset = final_size;
       cff_font_dict_op_serializer_t fontSzr;
       unsigned int dictsSize = 0;
       for (unsigned int i = 0; i < acc.fontDicts.length; i++)
-	if (fdmap.includes (i))
+	if (fdmap.has (i))
 	  dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr);
 
       offsets.FDArrayInfo.offSize = calcOffSize (dictsSize);
       final_size += CFF2Index::calculate_serialized_size (offsets.FDArrayInfo.offSize, subset_fdcount, dictsSize);
     }
 
     /* CharStrings */
     {
@@ -394,17 +393,17 @@ struct cff2_subset_plan {
       offsets.charStringsInfo.offSize = calcOffSize (dataSize);
       final_size += CFF2CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->num_output_glyphs (), dataSize);
     }
 
     /* private dicts & local subrs */
     offsets.privateDictsOffset = final_size;
     for (unsigned int i = 0; i < orig_fdcount; i++)
     {
-      if (fdmap.includes (i))
+      if (fdmap.has (i))
       {
 	bool  has_localsubrs = offsets.localSubrsInfos[i].size > 0;
 	cff_private_dict_op_serializer_t privSzr (desubroutinize, drop_hints);
 	unsigned int  priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr, has_localsubrs);
 	table_info_t  privInfo = { final_size, priv_size, 0 };
 	privateDictInfos.push (privInfo);
 	final_size += privInfo.size;
 
@@ -424,17 +423,17 @@ struct cff2_subset_plan {
   unsigned int	final_size;
   cff2_sub_table_offsets_t offsets;
 
   unsigned int    orig_fdcount;
   unsigned int    subset_fdcount;
   unsigned int    subset_fdselect_format;
   hb_vector_t<code_pair_t>   subset_fdselect_ranges;
 
-  remap_t   fdmap;
+  hb_inc_bimap_t   fdmap;
 
   str_buff_vec_t	    subset_charstrings;
   str_buff_vec_t	    subset_globalsubrs;
   hb_vector_t<str_buff_vec_t> subset_localsubrs;
   hb_vector_t<table_info_t>  privateDictInfos;
 
   bool	    drop_hints;
   bool	    desubroutinize;
@@ -534,25 +533,25 @@ static inline bool _write_cff2 (const cf
       return false;
     }
   }
 
   /* private dicts & local subrs */
   assert (plan.offsets.privateDictsOffset == (unsigned) (c.head - c.start));
   for (unsigned int i = 0; i < acc.privateDicts.length; i++)
   {
-    if (plan.fdmap.includes (i))
+    if (plan.fdmap.has (i))
     {
       PrivateDict  *pd = c.start_embed<PrivateDict> ();
       if (unlikely (pd == nullptr)) return false;
       unsigned int priv_size = plan.privateDictInfos[plan.fdmap[i]].size;
       bool result;
       cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
       /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
-      unsigned int  subroffset = (plan.offsets.localSubrsInfos[i].size > 0)? priv_size: 0;
+      unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0;
       result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
       if (unlikely (!result))
       {
 	DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
 	return false;
       }
       if (plan.offsets.localSubrsInfos[i].size > 0)
       {
@@ -624,9 +623,10 @@ hb_subset_cff2 (hb_subset_plan_t *plan,
 		_hb_subset_cff2 (acc, data, plan, prime);
 
   hb_blob_destroy (cff2_blob);
   acc.fini ();
 
   return result;
 }
 
+
 #endif
--- a/gfx/harfbuzz/src/hb-subset-plan.cc
+++ b/gfx/harfbuzz/src/hb-subset-plan.cc
@@ -189,33 +189,22 @@ static void
   | hb_sink (glyph_map)
   ;
 }
 
 static void
 _nameid_closure (hb_face_t           *face,
                  hb_set_t            *nameids)
 {
-  hb_tag_t table_tags[32];
-  unsigned count = ARRAY_LENGTH (table_tags);
-  hb_face_get_table_tags (face, 0, &count, table_tags);
-  for (unsigned int i = 0; i < count; i++)
-  {
-    hb_tag_t tag = table_tags[i];
-    switch (tag) {
-      case HB_OT_TAG_STAT:
-        face->table.STAT->collect_name_ids (nameids);
-        break;
-      case HB_OT_TAG_fvar:
-        face->table.fvar->collect_name_ids (nameids);
-        break;
-      default:
-        break;
-    }
-  }
+#ifndef HB_NO_STAT
+  face->table.STAT->collect_name_ids (nameids);
+#endif
+#ifndef HB_NO_VAR
+  face->table.fvar->collect_name_ids (nameids);
+#endif
 }
 
 /**
  * hb_subset_plan_create:
  * Computes a plan for subsetting the supplied face according
  * to a provided input. The plan describes
  * which tables and glyphs should be retained.
  *
--- a/gfx/harfbuzz/src/hb-subset.cc
+++ b/gfx/harfbuzz/src/hb-subset.cc
@@ -62,17 +62,17 @@ static inline unsigned int
 
   return 512 + (unsigned int) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
 }
 
 template<typename TableType>
 static bool
 _subset2 (hb_subset_plan_t *plan)
 {
-  bool result = true;
+  bool result = false;
   hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
   const TableType *table = source_blob->as<TableType> ();
 
   hb_tag_t tag = TableType::tableTag;
   if (source_blob->data)
   {
     hb_vector_t<char> buf;
     /* TODO Not all tables are glyph-related.  'name' table size for example should not be
@@ -167,49 +167,49 @@ static bool
       // TODO that won't work well if there is no glyf
       DEBUG_MSG(SUBSET, nullptr, "skip head, handled by glyf");
       result = true;
       break;
     case HB_OT_TAG_hhea:
       DEBUG_MSG(SUBSET, nullptr, "skip hhea handled by hmtx");
       return true;
     case HB_OT_TAG_hmtx:
-      result = _subset<const OT::hmtx> (plan);
+      result = _subset2<const OT::hmtx> (plan);
       break;
     case HB_OT_TAG_vhea:
       DEBUG_MSG(SUBSET, nullptr, "skip vhea handled by vmtx");
       return true;
     case HB_OT_TAG_vmtx:
-      result = _subset<const OT::vmtx> (plan);
+      result = _subset2<const OT::vmtx> (plan);
       break;
     case HB_OT_TAG_maxp:
-      result = _subset<const OT::maxp> (plan);
+      result = _subset2<const OT::maxp> (plan);
       break;
     case HB_OT_TAG_loca:
       DEBUG_MSG(SUBSET, nullptr, "skip loca handled by glyf");
       return true;
     case HB_OT_TAG_cmap:
       result = _subset<const OT::cmap> (plan);
       break;
     case HB_OT_TAG_OS2:
-      result = _subset<const OT::OS2> (plan);
+      result = _subset2<const OT::OS2> (plan);
       break;
     case HB_OT_TAG_post:
-      result = _subset<const OT::post> (plan);
+      result = _subset2<const OT::post> (plan);
       break;
 
 #ifndef HB_NO_SUBSET_CFF
     case HB_OT_TAG_cff1:
       result = _subset<const OT::cff1> (plan);
       break;
     case HB_OT_TAG_cff2:
       result = _subset<const OT::cff2> (plan);
       break;
     case HB_OT_TAG_VORG:
-      result = _subset<const OT::VORG> (plan);
+      result = _subset2<const OT::VORG> (plan);
       break;
 #endif
 
 #ifndef HB_NO_SUBSET_LAYOUT
     case HB_OT_TAG_GDEF:
       result = _subset2<const OT::GDEF> (plan);
       break;
     case HB_OT_TAG_GSUB:
--- a/gfx/harfbuzz/src/hb-ucd-table.hh
+++ b/gfx/harfbuzz/src/hb-ucd-table.hh
@@ -1,25 +1,24 @@
 /* == Start of generated table == */
 /*
  * The following table is generated by running:
  *
- *   ./gen-ucd-table.py ucd.nonunihan.grouped.xml
+ *   ./gen-ucd-table.py ucd.nounihan.grouped.xml
  *
  * on file with this description: Unicode 12.1.0
  */
 
 #ifndef HB_UCD_TABLE_HH
 #define HB_UCD_TABLE_HH
 
-
 #include "hb.hh"
 
 static const hb_script_t
-_hb_ucd_sc_map[138] =
+_hb_ucd_sc_map[153] =
 {
                    HB_SCRIPT_COMMON,              HB_SCRIPT_INHERITED,
                   HB_SCRIPT_UNKNOWN,                 HB_SCRIPT_ARABIC,
                  HB_SCRIPT_ARMENIAN,                HB_SCRIPT_BENGALI,
                  HB_SCRIPT_CYRILLIC,             HB_SCRIPT_DEVANAGARI,
                  HB_SCRIPT_GEORGIAN,                  HB_SCRIPT_GREEK,
                  HB_SCRIPT_GUJARATI,               HB_SCRIPT_GURMUKHI,
                    HB_SCRIPT_HANGUL,                    HB_SCRIPT_HAN,
@@ -80,19 +79,27 @@ static const hb_script_t
           HB_SCRIPT_PSALTER_PAHLAVI,                HB_SCRIPT_SIDDHAM,
                   HB_SCRIPT_TIRHUTA,            HB_SCRIPT_WARANG_CITI,
                      HB_SCRIPT_AHOM,  HB_SCRIPT_ANATOLIAN_HIEROGLYPHS,
                    HB_SCRIPT_HATRAN,                HB_SCRIPT_MULTANI,
             HB_SCRIPT_OLD_HUNGARIAN,            HB_SCRIPT_SIGNWRITING,
                     HB_SCRIPT_ADLAM,              HB_SCRIPT_BHAIKSUKI,
                   HB_SCRIPT_MARCHEN,                  HB_SCRIPT_OSAGE,
                    HB_SCRIPT_TANGUT,                   HB_SCRIPT_NEWA,
+            HB_SCRIPT_MASARAM_GONDI,                  HB_SCRIPT_NUSHU,
+                  HB_SCRIPT_SOYOMBO,       HB_SCRIPT_ZANABAZAR_SQUARE,
+                    HB_SCRIPT_DOGRA,          HB_SCRIPT_GUNJALA_GONDI,
+          HB_SCRIPT_HANIFI_ROHINGYA,                HB_SCRIPT_MAKASAR,
+              HB_SCRIPT_MEDEFAIDRIN,            HB_SCRIPT_OLD_SOGDIAN,
+                  HB_SCRIPT_SOGDIAN,                HB_SCRIPT_ELYMAIC,
+              HB_SCRIPT_NANDINAGARI, HB_SCRIPT_NYIAKENG_PUACHUE_HMONG,
+                   HB_SCRIPT_WANCHO,
 };
-static const hb_codepoint_t
-_hb_ucd_dm1_map[935] =
+static const uint16_t
+_hb_ucd_dm1_p0_map[825] =
 {
    0x003Bu, 0x004Bu, 0x0060u, 0x00B4u, 0x00B7u, 0x00C5u, 0x02B9u, 0x0300u,
    0x0301u, 0x0313u, 0x0385u, 0x0386u, 0x0388u, 0x0389u, 0x038Au, 0x038Cu,
    0x038Eu, 0x038Fu, 0x0390u, 0x03A9u, 0x03ACu, 0x03ADu, 0x03AEu, 0x03AFu,
    0x03B0u, 0x03B9u, 0x03CCu, 0x03CDu, 0x03CEu, 0x2002u, 0x2003u, 0x3008u,
    0x3009u, 0x349Eu, 0x34B9u, 0x34BBu, 0x34DFu, 0x3515u, 0x36EEu, 0x36FCu,
    0x3781u, 0x382Fu, 0x3862u, 0x387Cu, 0x38C7u, 0x38E3u, 0x391Cu, 0x393Au,
    0x3A2Eu, 0x3A6Cu, 0x3AE4u, 0x3B08u, 0x3B19u, 0x3B49u, 0x3B9Du, 0x3C18u,
@@ -187,353 +194,681 @@ static const hb_codepoint_t
    0x9415u, 0x958Bu, 0x95ADu, 0x95B7u, 0x962Eu, 0x964Bu, 0x964Du, 0x9675u,
    0x9678u, 0x967Cu, 0x9686u, 0x96A3u, 0x96B7u, 0x96B8u, 0x96C3u, 0x96E2u,
    0x96E3u, 0x96F6u, 0x96F7u, 0x9723u, 0x9732u, 0x9748u, 0x9756u, 0x97DBu,
    0x97E0u, 0x97FFu, 0x980Bu, 0x9818u, 0x9829u, 0x983Bu, 0x985Eu, 0x98E2u,
    0x98EFu, 0x98FCu, 0x9928u, 0x9929u, 0x99A7u, 0x99C2u, 0x99F1u, 0x99FEu,
    0x9A6Au, 0x9B12u, 0x9B6Fu, 0x9C40u, 0x9C57u, 0x9CFDu, 0x9D67u, 0x9DB4u,
    0x9DFAu, 0x9E1Eu, 0x9E7Fu, 0x9E97u, 0x9E9Fu, 0x9EBBu, 0x9ECEu, 0x9EF9u,
    0x9EFEu, 0x9F05u, 0x9F0Fu, 0x9F16u, 0x9F3Bu, 0x9F43u, 0x9F8Du, 0x9F8Eu,
-   0x9F9Cu,0x20122u,0x2051Cu,0x20525u,0x2054Bu,0x2063Au,0x20804u,0x208DEu,
-  0x20A2Cu,0x20B63u,0x214E4u,0x216A8u,0x216EAu,0x219C8u,0x21B18u,0x21D0Bu,
-  0x21DE4u,0x21DE6u,0x22183u,0x2219Fu,0x22331u,0x226D4u,0x22844u,0x2284Au,
-  0x22B0Cu,0x22BF1u,0x2300Au,0x232B8u,0x2335Fu,0x23393u,0x2339Cu,0x233C3u,
-  0x233D5u,0x2346Du,0x236A3u,0x238A7u,0x23A8Du,0x23AFAu,0x23CBCu,0x23D1Eu,
-  0x23ED1u,0x23F5Eu,0x23F8Eu,0x24263u,0x242EEu,0x243ABu,0x24608u,0x24735u,
-  0x24814u,0x24C36u,0x24C92u,0x24FA1u,0x24FB8u,0x25044u,0x250F2u,0x250F3u,
-  0x25119u,0x25133u,0x25249u,0x2541Du,0x25626u,0x2569Au,0x256C5u,0x2597Cu,
-  0x25AA7u,0x25BABu,0x25C80u,0x25CD0u,0x25F86u,0x261DAu,0x26228u,0x26247u,
-  0x262D9u,0x2633Eu,0x264DAu,0x26523u,0x265A8u,0x267A7u,0x267B5u,0x26B3Cu,
-  0x26C36u,0x26CD5u,0x26D6Bu,0x26F2Cu,0x26FB1u,0x270D2u,0x273CAu,0x27667u,
-  0x278AEu,0x27966u,0x27CA8u,0x27ED3u,0x27F2Fu,0x285D2u,0x285EDu,0x2872Eu,
-  0x28BFAu,0x28D77u,0x29145u,0x291DFu,0x2921Au,0x2940Au,0x29496u,0x295B6u,
-  0x29B30u,0x2A0CEu,0x2A105u,0x2A20Eu,0x2A291u,0x2A392u,0x2A600u,
+   0x9F9Cu,
+};
+static const uint16_t
+_hb_ucd_dm1_p2_map[110] =
+{
+   0x0122u, 0x051Cu, 0x0525u, 0x054Bu, 0x063Au, 0x0804u, 0x08DEu, 0x0A2Cu,
+   0x0B63u, 0x14E4u, 0x16A8u, 0x16EAu, 0x19C8u, 0x1B18u, 0x1D0Bu, 0x1DE4u,
+   0x1DE6u, 0x2183u, 0x219Fu, 0x2331u, 0x26D4u, 0x2844u, 0x284Au, 0x2B0Cu,
+   0x2BF1u, 0x300Au, 0x32B8u, 0x335Fu, 0x3393u, 0x339Cu, 0x33C3u, 0x33D5u,
+   0x346Du, 0x36A3u, 0x38A7u, 0x3A8Du, 0x3AFAu, 0x3CBCu, 0x3D1Eu, 0x3ED1u,
+   0x3F5Eu, 0x3F8Eu, 0x4263u, 0x42EEu, 0x43ABu, 0x4608u, 0x4735u, 0x4814u,
+   0x4C36u, 0x4C92u, 0x4FA1u, 0x4FB8u, 0x5044u, 0x50F2u, 0x50F3u, 0x5119u,
+   0x5133u, 0x5249u, 0x541Du, 0x5626u, 0x569Au, 0x56C5u, 0x597Cu, 0x5AA7u,
+   0x5BABu, 0x5C80u, 0x5CD0u, 0x5F86u, 0x61DAu, 0x6228u, 0x6247u, 0x62D9u,
+   0x633Eu, 0x64DAu, 0x6523u, 0x65A8u, 0x67A7u, 0x67B5u, 0x6B3Cu, 0x6C36u,
+   0x6CD5u, 0x6D6Bu, 0x6F2Cu, 0x6FB1u, 0x70D2u, 0x73CAu, 0x7667u, 0x78AEu,
+   0x7966u, 0x7CA8u, 0x7ED3u, 0x7F2Fu, 0x85D2u, 0x85EDu, 0x872Eu, 0x8BFAu,
+   0x8D77u, 0x9145u, 0x91DFu, 0x921Au, 0x940Au, 0x9496u, 0x95B6u, 0x9B30u,
+   0xA0CEu, 0xA105u, 0xA20Eu, 0xA291u, 0xA392u, 0xA600u,
+};
+static const uint32_t
+_hb_ucd_dm2_u32_map[638] =
+{
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x003Cu, 0x0338u, 0x226Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x003Du, 0x0338u, 0x2260u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x003Eu, 0x0338u, 0x226Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0300u, 0x00C0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0301u, 0x00C1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0302u, 0x00C2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0303u, 0x00C3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0304u, 0x0100u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0306u, 0x0102u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0307u, 0x0226u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0308u, 0x00C4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0309u, 0x1EA2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x030Au, 0x00C5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x030Cu, 0x01CDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x030Fu, 0x0200u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0311u, 0x0202u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0323u, 0x1EA0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0325u, 0x1E00u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0328u, 0x0104u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0042u, 0x0307u, 0x1E02u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0042u, 0x0323u, 0x1E04u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0042u, 0x0331u, 0x1E06u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x0301u, 0x0106u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x0302u, 0x0108u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x0307u, 0x010Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x030Cu, 0x010Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x0327u, 0x00C7u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x0307u, 0x1E0Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x030Cu, 0x010Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x0323u, 0x1E0Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x0327u, 0x1E10u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x032Du, 0x1E12u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x0331u, 0x1E0Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0300u, 0x00C8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0301u, 0x00C9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0302u, 0x00CAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0303u, 0x1EBCu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0304u, 0x0112u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0306u, 0x0114u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0307u, 0x0116u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0308u, 0x00CBu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0309u, 0x1EBAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x030Cu, 0x011Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x030Fu, 0x0204u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0311u, 0x0206u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0323u, 0x1EB8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0327u, 0x0228u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0328u, 0x0118u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x032Du, 0x1E18u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0330u, 0x1E1Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0046u, 0x0307u, 0x1E1Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0301u, 0x01F4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0302u, 0x011Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0304u, 0x1E20u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0306u, 0x011Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0307u, 0x0120u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x030Cu, 0x01E6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0327u, 0x0122u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0302u, 0x0124u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0307u, 0x1E22u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0308u, 0x1E26u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x030Cu, 0x021Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0323u, 0x1E24u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0327u, 0x1E28u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x032Eu, 0x1E2Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0300u, 0x00CCu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0301u, 0x00CDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0302u, 0x00CEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0303u, 0x0128u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0304u, 0x012Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0306u, 0x012Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0307u, 0x0130u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0308u, 0x00CFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0309u, 0x1EC8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x030Cu, 0x01CFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x030Fu, 0x0208u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0311u, 0x020Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0323u, 0x1ECAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0328u, 0x012Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0330u, 0x1E2Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Au, 0x0302u, 0x0134u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x0301u, 0x1E30u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x030Cu, 0x01E8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x0323u, 0x1E32u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x0327u, 0x0136u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x0331u, 0x1E34u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x0301u, 0x0139u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x030Cu, 0x013Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x0323u, 0x1E36u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x0327u, 0x013Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x032Du, 0x1E3Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x0331u, 0x1E3Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Du, 0x0301u, 0x1E3Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Du, 0x0307u, 0x1E40u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Du, 0x0323u, 0x1E42u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0300u, 0x01F8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0301u, 0x0143u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0303u, 0x00D1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0307u, 0x1E44u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x030Cu, 0x0147u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0323u, 0x1E46u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0327u, 0x0145u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x032Du, 0x1E4Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0331u, 0x1E48u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0300u, 0x00D2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0301u, 0x00D3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0302u, 0x00D4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0303u, 0x00D5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0304u, 0x014Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0306u, 0x014Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0307u, 0x022Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0308u, 0x00D6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0309u, 0x1ECEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x030Bu, 0x0150u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x030Cu, 0x01D1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x030Fu, 0x020Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0311u, 0x020Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x031Bu, 0x01A0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0323u, 0x1ECCu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0328u, 0x01EAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0050u, 0x0301u, 0x1E54u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0050u, 0x0307u, 0x1E56u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0301u, 0x0154u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0307u, 0x1E58u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x030Cu, 0x0158u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x030Fu, 0x0210u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0311u, 0x0212u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0323u, 0x1E5Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0327u, 0x0156u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0331u, 0x1E5Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0301u, 0x015Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0302u, 0x015Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0307u, 0x1E60u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x030Cu, 0x0160u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0323u, 0x1E62u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0326u, 0x0218u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0327u, 0x015Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0307u, 0x1E6Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x030Cu, 0x0164u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0323u, 0x1E6Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0326u, 0x021Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0327u, 0x0162u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x032Du, 0x1E70u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0331u, 0x1E6Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0300u, 0x00D9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0301u, 0x00DAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0302u, 0x00DBu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0303u, 0x0168u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0304u, 0x016Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0306u, 0x016Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0308u, 0x00DCu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0309u, 0x1EE6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x030Au, 0x016Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x030Bu, 0x0170u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x030Cu, 0x01D3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x030Fu, 0x0214u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0311u, 0x0216u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x031Bu, 0x01AFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0323u, 0x1EE4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0324u, 0x1E72u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0328u, 0x0172u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x032Du, 0x1E76u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0330u, 0x1E74u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0056u, 0x0303u, 0x1E7Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0056u, 0x0323u, 0x1E7Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0300u, 0x1E80u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0301u, 0x1E82u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0302u, 0x0174u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0307u, 0x1E86u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0308u, 0x1E84u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0323u, 0x1E88u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0058u, 0x0307u, 0x1E8Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0058u, 0x0308u, 0x1E8Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0300u, 0x1EF2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0301u, 0x00DDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0302u, 0x0176u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0303u, 0x1EF8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0304u, 0x0232u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0307u, 0x1E8Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0308u, 0x0178u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0309u, 0x1EF6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0323u, 0x1EF4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0301u, 0x0179u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0302u, 0x1E90u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0307u, 0x017Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x030Cu, 0x017Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0323u, 0x1E92u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0331u, 0x1E94u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0300u, 0x00E0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0301u, 0x00E1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0302u, 0x00E2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0303u, 0x00E3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0304u, 0x0101u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0306u, 0x0103u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0307u, 0x0227u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0308u, 0x00E4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0309u, 0x1EA3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x030Au, 0x00E5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x030Cu, 0x01CEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x030Fu, 0x0201u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0311u, 0x0203u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0323u, 0x1EA1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0325u, 0x1E01u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0328u, 0x0105u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0062u, 0x0307u, 0x1E03u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0062u, 0x0323u, 0x1E05u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0062u, 0x0331u, 0x1E07u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x0301u, 0x0107u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x0302u, 0x0109u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x0307u, 0x010Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x030Cu, 0x010Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x0327u, 0x00E7u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x0307u, 0x1E0Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x030Cu, 0x010Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x0323u, 0x1E0Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x0327u, 0x1E11u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x032Du, 0x1E13u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x0331u, 0x1E0Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0300u, 0x00E8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0301u, 0x00E9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0302u, 0x00EAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0303u, 0x1EBDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0304u, 0x0113u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0306u, 0x0115u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0307u, 0x0117u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0308u, 0x00EBu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0309u, 0x1EBBu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x030Cu, 0x011Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x030Fu, 0x0205u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0311u, 0x0207u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0323u, 0x1EB9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0327u, 0x0229u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0328u, 0x0119u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x032Du, 0x1E19u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0330u, 0x1E1Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0066u, 0x0307u, 0x1E1Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0301u, 0x01F5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0302u, 0x011Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0304u, 0x1E21u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0306u, 0x011Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0307u, 0x0121u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x030Cu, 0x01E7u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0327u, 0x0123u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0302u, 0x0125u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0307u, 0x1E23u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0308u, 0x1E27u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x030Cu, 0x021Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0323u, 0x1E25u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0327u, 0x1E29u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x032Eu, 0x1E2Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0331u, 0x1E96u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0300u, 0x00ECu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0301u, 0x00EDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0302u, 0x00EEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0303u, 0x0129u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0304u, 0x012Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0306u, 0x012Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0308u, 0x00EFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0309u, 0x1EC9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x030Cu, 0x01D0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x030Fu, 0x0209u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0311u, 0x020Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0323u, 0x1ECBu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0328u, 0x012Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0330u, 0x1E2Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Au, 0x0302u, 0x0135u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Au, 0x030Cu, 0x01F0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x0301u, 0x1E31u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x030Cu, 0x01E9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x0323u, 0x1E33u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x0327u, 0x0137u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x0331u, 0x1E35u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x0301u, 0x013Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x030Cu, 0x013Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x0323u, 0x1E37u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x0327u, 0x013Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x032Du, 0x1E3Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x0331u, 0x1E3Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Du, 0x0301u, 0x1E3Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Du, 0x0307u, 0x1E41u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Du, 0x0323u, 0x1E43u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0300u, 0x01F9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0301u, 0x0144u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0303u, 0x00F1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0307u, 0x1E45u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x030Cu, 0x0148u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0323u, 0x1E47u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0327u, 0x0146u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x032Du, 0x1E4Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0331u, 0x1E49u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0300u, 0x00F2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0301u, 0x00F3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0302u, 0x00F4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0303u, 0x00F5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0304u, 0x014Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0306u, 0x014Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0307u, 0x022Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0308u, 0x00F6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0309u, 0x1ECFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x030Bu, 0x0151u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x030Cu, 0x01D2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x030Fu, 0x020Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0311u, 0x020Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x031Bu, 0x01A1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0323u, 0x1ECDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0328u, 0x01EBu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0070u, 0x0301u, 0x1E55u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0070u, 0x0307u, 0x1E57u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0301u, 0x0155u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0307u, 0x1E59u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x030Cu, 0x0159u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x030Fu, 0x0211u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0311u, 0x0213u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0323u, 0x1E5Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0327u, 0x0157u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0331u, 0x1E5Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0301u, 0x015Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0302u, 0x015Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0307u, 0x1E61u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x030Cu, 0x0161u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0323u, 0x1E63u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0326u, 0x0219u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0327u, 0x015Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0307u, 0x1E6Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0308u, 0x1E97u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x030Cu, 0x0165u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0323u, 0x1E6Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0326u, 0x021Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0327u, 0x0163u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x032Du, 0x1E71u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0331u, 0x1E6Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0300u, 0x00F9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0301u, 0x00FAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0302u, 0x00FBu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0303u, 0x0169u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0304u, 0x016Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0306u, 0x016Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0308u, 0x00FCu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0309u, 0x1EE7u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x030Au, 0x016Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x030Bu, 0x0171u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x030Cu, 0x01D4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x030Fu, 0x0215u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0311u, 0x0217u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x031Bu, 0x01B0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0323u, 0x1EE5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0324u, 0x1E73u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0328u, 0x0173u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x032Du, 0x1E77u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0330u, 0x1E75u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0076u, 0x0303u, 0x1E7Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0076u, 0x0323u, 0x1E7Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0300u, 0x1E81u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0301u, 0x1E83u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0302u, 0x0175u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0307u, 0x1E87u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0308u, 0x1E85u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x030Au, 0x1E98u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0323u, 0x1E89u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0078u, 0x0307u, 0x1E8Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0078u, 0x0308u, 0x1E8Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0300u, 0x1EF3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0301u, 0x00FDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0302u, 0x0177u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0303u, 0x1EF9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0304u, 0x0233u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0307u, 0x1E8Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0308u, 0x00FFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0309u, 0x1EF7u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x030Au, 0x1E99u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0323u, 0x1EF5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0301u, 0x017Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0302u, 0x1E91u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0307u, 0x017Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x030Cu, 0x017Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0323u, 0x1E93u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0331u, 0x1E95u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00A8u, 0x0300u, 0x1FEDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00A8u, 0x0301u, 0x0385u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00A8u, 0x0342u, 0x1FC1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C2u, 0x0300u, 0x1EA6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C2u, 0x0301u, 0x1EA4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C2u, 0x0303u, 0x1EAAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C2u, 0x0309u, 0x1EA8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C4u, 0x0304u, 0x01DEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C5u, 0x0301u, 0x01FAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C6u, 0x0301u, 0x01FCu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C6u, 0x0304u, 0x01E2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C7u, 0x0301u, 0x1E08u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00CAu, 0x0300u, 0x1EC0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00CAu, 0x0301u, 0x1EBEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00CAu, 0x0303u, 0x1EC4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00CAu, 0x0309u, 0x1EC2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00CFu, 0x0301u, 0x1E2Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D4u, 0x0300u, 0x1ED2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D4u, 0x0301u, 0x1ED0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D4u, 0x0303u, 0x1ED6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D4u, 0x0309u, 0x1ED4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D5u, 0x0301u, 0x1E4Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D5u, 0x0304u, 0x022Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D5u, 0x0308u, 0x1E4Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D6u, 0x0304u, 0x022Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D8u, 0x0301u, 0x01FEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00DCu, 0x0300u, 0x01DBu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00DCu, 0x0301u, 0x01D7u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00DCu, 0x0304u, 0x01D5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00DCu, 0x030Cu, 0x01D9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E2u, 0x0300u, 0x1EA7u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E2u, 0x0301u, 0x1EA5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E2u, 0x0303u, 0x1EABu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E2u, 0x0309u, 0x1EA9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E4u, 0x0304u, 0x01DFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E5u, 0x0301u, 0x01FBu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E6u, 0x0301u, 0x01FDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E6u, 0x0304u, 0x01E3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E7u, 0x0301u, 0x1E09u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00EAu, 0x0300u, 0x1EC1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00EAu, 0x0301u, 0x1EBFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00EAu, 0x0303u, 0x1EC5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00EAu, 0x0309u, 0x1EC3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00EFu, 0x0301u, 0x1E2Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F4u, 0x0300u, 0x1ED3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F4u, 0x0301u, 0x1ED1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F4u, 0x0303u, 0x1ED7u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F4u, 0x0309u, 0x1ED5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F5u, 0x0301u, 0x1E4Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F5u, 0x0304u, 0x022Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F5u, 0x0308u, 0x1E4Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F6u, 0x0304u, 0x022Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F8u, 0x0301u, 0x01FFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00FCu, 0x0300u, 0x01DCu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00FCu, 0x0301u, 0x01D8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00FCu, 0x0304u, 0x01D6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00FCu, 0x030Cu, 0x01DAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0102u, 0x0300u, 0x1EB0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0102u, 0x0301u, 0x1EAEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0102u, 0x0303u, 0x1EB4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0102u, 0x0309u, 0x1EB2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0103u, 0x0300u, 0x1EB1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0103u, 0x0301u, 0x1EAFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0103u, 0x0303u, 0x1EB5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0103u, 0x0309u, 0x1EB3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0112u, 0x0300u, 0x1E14u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0112u, 0x0301u, 0x1E16u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0113u, 0x0300u, 0x1E15u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0113u, 0x0301u, 0x1E17u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x014Cu, 0x0300u, 0x1E50u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x014Cu, 0x0301u, 0x1E52u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x014Du, 0x0300u, 0x1E51u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x014Du, 0x0301u, 0x1E53u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x015Au, 0x0307u, 0x1E64u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x015Bu, 0x0307u, 0x1E65u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0160u, 0x0307u, 0x1E66u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0161u, 0x0307u, 0x1E67u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0168u, 0x0301u, 0x1E78u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0169u, 0x0301u, 0x1E79u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x016Au, 0x0308u, 0x1E7Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x016Bu, 0x0308u, 0x1E7Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x017Fu, 0x0307u, 0x1E9Bu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0300u, 0x1EDCu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0301u, 0x1EDAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0303u, 0x1EE0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0309u, 0x1EDEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0323u, 0x1EE2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0300u, 0x1EDDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0301u, 0x1EDBu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0303u, 0x1EE1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0309u, 0x1EDFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0323u, 0x1EE3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0300u, 0x1EEAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0301u, 0x1EE8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0303u, 0x1EEEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0309u, 0x1EECu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0323u, 0x1EF0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0300u, 0x1EEBu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0301u, 0x1EE9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0303u, 0x1EEFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0309u, 0x1EEDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0323u, 0x1EF1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01B7u, 0x030Cu, 0x01EEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01EAu, 0x0304u, 0x01ECu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01EBu, 0x0304u, 0x01EDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0226u, 0x0304u, 0x01E0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0227u, 0x0304u, 0x01E1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0228u, 0x0306u, 0x1E1Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0229u, 0x0306u, 0x1E1Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x022Eu, 0x0304u, 0x0230u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x022Fu, 0x0304u, 0x0231u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0292u, 0x030Cu, 0x01EFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0308u, 0x0301u, 0x0000u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0300u, 0x1FBAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0301u, 0x0386u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0304u, 0x1FB9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0306u, 0x1FB8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0313u, 0x1F08u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0314u, 0x1F09u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0345u, 0x1FBCu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0395u, 0x0300u, 0x1FC8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0395u, 0x0301u, 0x0388u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0395u, 0x0313u, 0x1F18u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0395u, 0x0314u, 0x1F19u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0300u, 0x1FCAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0301u, 0x0389u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0313u, 0x1F28u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0314u, 0x1F29u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0345u, 0x1FCCu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0300u, 0x1FDAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0301u, 0x038Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0304u, 0x1FD9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0306u, 0x1FD8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0308u, 0x03AAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0313u, 0x1F38u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0314u, 0x1F39u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x039Fu, 0x0300u, 0x1FF8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x039Fu, 0x0301u, 0x038Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x039Fu, 0x0313u, 0x1F48u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x039Fu, 0x0314u, 0x1F49u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A1u, 0x0314u, 0x1FECu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0300u, 0x1FEAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0301u, 0x038Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0304u, 0x1FE9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0306u, 0x1FE8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0308u, 0x03ABu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0314u, 0x1F59u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0300u, 0x1FFAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0301u, 0x038Fu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0313u, 0x1F68u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0314u, 0x1F69u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0345u, 0x1FFCu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03ACu, 0x0345u, 0x1FB4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03AEu, 0x0345u, 0x1FC4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0300u, 0x1F70u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0301u, 0x03ACu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0304u, 0x1FB1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0306u, 0x1FB0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0313u, 0x1F00u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0314u, 0x1F01u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0342u, 0x1FB6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0345u, 0x1FB3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B5u, 0x0300u, 0x1F72u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B5u, 0x0301u, 0x03ADu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B5u, 0x0313u, 0x1F10u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B5u, 0x0314u, 0x1F11u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0300u, 0x1F74u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0301u, 0x03AEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0313u, 0x1F20u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0314u, 0x1F21u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0342u, 0x1FC6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0345u, 0x1FC3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0300u, 0x1F76u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0301u, 0x03AFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0304u, 0x1FD1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0306u, 0x1FD0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0308u, 0x03CAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0313u, 0x1F30u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0314u, 0x1F31u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0342u, 0x1FD6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03BFu, 0x0300u, 0x1F78u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03BFu, 0x0301u, 0x03CCu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03BFu, 0x0313u, 0x1F40u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03BFu, 0x0314u, 0x1F41u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C1u, 0x0313u, 0x1FE4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C1u, 0x0314u, 0x1FE5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0300u, 0x1F7Au),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0301u, 0x03CDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0304u, 0x1FE1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0306u, 0x1FE0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0308u, 0x03CBu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0313u, 0x1F50u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0314u, 0x1F51u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0342u, 0x1FE6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0300u, 0x1F7Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0301u, 0x03CEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0313u, 0x1F60u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0314u, 0x1F61u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0342u, 0x1FF6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0345u, 0x1FF3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03CAu, 0x0300u, 0x1FD2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03CAu, 0x0301u, 0x0390u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03CAu, 0x0342u, 0x1FD7u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03CBu, 0x0300u, 0x1FE2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03CBu, 0x0301u, 0x03B0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03CBu, 0x0342u, 0x1FE7u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03CEu, 0x0345u, 0x1FF4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03D2u, 0x0301u, 0x03D3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03D2u, 0x0308u, 0x03D4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0406u, 0x0308u, 0x0407u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0410u, 0x0306u, 0x04D0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0410u, 0x0308u, 0x04D2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0413u, 0x0301u, 0x0403u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0415u, 0x0300u, 0x0400u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0415u, 0x0306u, 0x04D6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0415u, 0x0308u, 0x0401u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0416u, 0x0306u, 0x04C1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0416u, 0x0308u, 0x04DCu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0417u, 0x0308u, 0x04DEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0418u, 0x0300u, 0x040Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0418u, 0x0304u, 0x04E2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0418u, 0x0306u, 0x0419u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0418u, 0x0308u, 0x04E4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x041Au, 0x0301u, 0x040Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x041Eu, 0x0308u, 0x04E6u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0423u, 0x0304u, 0x04EEu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0423u, 0x0306u, 0x040Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0423u, 0x0308u, 0x04F0u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0423u, 0x030Bu, 0x04F2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0427u, 0x0308u, 0x04F4u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x042Bu, 0x0308u, 0x04F8u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x042Du, 0x0308u, 0x04ECu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0430u, 0x0306u, 0x04D1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0430u, 0x0308u, 0x04D3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0433u, 0x0301u, 0x0453u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0435u, 0x0300u, 0x0450u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0435u, 0x0306u, 0x04D7u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0435u, 0x0308u, 0x0451u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0436u, 0x0306u, 0x04C2u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0436u, 0x0308u, 0x04DDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0437u, 0x0308u, 0x04DFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0438u, 0x0300u, 0x045Du),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0438u, 0x0304u, 0x04E3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0438u, 0x0306u, 0x0439u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0438u, 0x0308u, 0x04E5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x043Au, 0x0301u, 0x045Cu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x043Eu, 0x0308u, 0x04E7u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0443u, 0x0304u, 0x04EFu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0443u, 0x0306u, 0x045Eu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0443u, 0x0308u, 0x04F1u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0443u, 0x030Bu, 0x04F3u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0447u, 0x0308u, 0x04F5u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x044Bu, 0x0308u, 0x04F9u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x044Du, 0x0308u, 0x04EDu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0456u, 0x0308u, 0x0457u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0474u, 0x030Fu, 0x0476u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0475u, 0x030Fu, 0x0477u),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x04D8u, 0x0308u, 0x04DAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x04D9u, 0x0308u, 0x04DBu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x04E8u, 0x0308u, 0x04EAu),
+   HB_CODEPOINT_ENCODE3_11_7_14 (0x04E9u, 0x0308u, 0x04EBu),
 };
 static const uint64_t
-_hb_ucd_dm2_map[1025] =
+_hb_ucd_dm2_u64_map[387] =
 {
-     HB_CODEPOINT_ENCODE3 (0x003Cu, 0x0338u, 0x226Eu),   HB_CODEPOINT_ENCODE3 (0x003Du, 0x0338u, 0x2260u),
-     HB_CODEPOINT_ENCODE3 (0x003Eu, 0x0338u, 0x226Fu),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0300u, 0x00C0u),
-     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0301u, 0x00C1u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0302u, 0x00C2u),
-     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0303u, 0x00C3u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0304u, 0x0100u),
-     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0306u, 0x0102u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0307u, 0x0226u),
-     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0308u, 0x00C4u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0309u, 0x1EA2u),
-     HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Au, 0x00C5u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Cu, 0x01CDu),
-     HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Fu, 0x0200u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0311u, 0x0202u),
-     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0323u, 0x1EA0u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0325u, 0x1E00u),
-     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0328u, 0x0104u),   HB_CODEPOINT_ENCODE3 (0x0042u, 0x0307u, 0x1E02u),
-     HB_CODEPOINT_ENCODE3 (0x0042u, 0x0323u, 0x1E04u),   HB_CODEPOINT_ENCODE3 (0x0042u, 0x0331u, 0x1E06u),
-     HB_CODEPOINT_ENCODE3 (0x0043u, 0x0301u, 0x0106u),   HB_CODEPOINT_ENCODE3 (0x0043u, 0x0302u, 0x0108u),
-     HB_CODEPOINT_ENCODE3 (0x0043u, 0x0307u, 0x010Au),   HB_CODEPOINT_ENCODE3 (0x0043u, 0x030Cu, 0x010Cu),
-     HB_CODEPOINT_ENCODE3 (0x0043u, 0x0327u, 0x00C7u),   HB_CODEPOINT_ENCODE3 (0x0044u, 0x0307u, 0x1E0Au),
-     HB_CODEPOINT_ENCODE3 (0x0044u, 0x030Cu, 0x010Eu),   HB_CODEPOINT_ENCODE3 (0x0044u, 0x0323u, 0x1E0Cu),
-     HB_CODEPOINT_ENCODE3 (0x0044u, 0x0327u, 0x1E10u),   HB_CODEPOINT_ENCODE3 (0x0044u, 0x032Du, 0x1E12u),
-     HB_CODEPOINT_ENCODE3 (0x0044u, 0x0331u, 0x1E0Eu),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0300u, 0x00C8u),
-     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0301u, 0x00C9u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0302u, 0x00CAu),
-     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0303u, 0x1EBCu),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0304u, 0x0112u),
-     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0306u, 0x0114u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0307u, 0x0116u),
-     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0308u, 0x00CBu),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0309u, 0x1EBAu),
-     HB_CODEPOINT_ENCODE3 (0x0045u, 0x030Cu, 0x011Au),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x030Fu, 0x0204u),
-     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0311u, 0x0206u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0323u, 0x1EB8u),
-     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0327u, 0x0228u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0328u, 0x0118u),
-     HB_CODEPOINT_ENCODE3 (0x0045u, 0x032Du, 0x1E18u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0330u, 0x1E1Au),
-     HB_CODEPOINT_ENCODE3 (0x0046u, 0x0307u, 0x1E1Eu),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0301u, 0x01F4u),
-     HB_CODEPOINT_ENCODE3 (0x0047u, 0x0302u, 0x011Cu),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0304u, 0x1E20u),
-     HB_CODEPOINT_ENCODE3 (0x0047u, 0x0306u, 0x011Eu),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0307u, 0x0120u),
-     HB_CODEPOINT_ENCODE3 (0x0047u, 0x030Cu, 0x01E6u),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0327u, 0x0122u),
-     HB_CODEPOINT_ENCODE3 (0x0048u, 0x0302u, 0x0124u),   HB_CODEPOINT_ENCODE3 (0x0048u, 0x0307u, 0x1E22u),
-     HB_CODEPOINT_ENCODE3 (0x0048u, 0x0308u, 0x1E26u),   HB_CODEPOINT_ENCODE3 (0x0048u, 0x030Cu, 0x021Eu),
-     HB_CODEPOINT_ENCODE3 (0x0048u, 0x0323u, 0x1E24u),   HB_CODEPOINT_ENCODE3 (0x0048u, 0x0327u, 0x1E28u),
-     HB_CODEPOINT_ENCODE3 (0x0048u, 0x032Eu, 0x1E2Au),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0300u, 0x00CCu),
-     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0301u, 0x00CDu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0302u, 0x00CEu),
-     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0303u, 0x0128u),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0304u, 0x012Au),
-     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0306u, 0x012Cu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0307u, 0x0130u),
-     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0308u, 0x00CFu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0309u, 0x1EC8u),
-     HB_CODEPOINT_ENCODE3 (0x0049u, 0x030Cu, 0x01CFu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x030Fu, 0x0208u),
-     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0311u, 0x020Au),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0323u, 0x1ECAu),
-     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0328u, 0x012Eu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0330u, 0x1E2Cu),
-     HB_CODEPOINT_ENCODE3 (0x004Au, 0x0302u, 0x0134u),   HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0301u, 0x1E30u),
-     HB_CODEPOINT_ENCODE3 (0x004Bu, 0x030Cu, 0x01E8u),   HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0323u, 0x1E32u),
-     HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0327u, 0x0136u),   HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0331u, 0x1E34u),
-     HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0301u, 0x0139u),   HB_CODEPOINT_ENCODE3 (0x004Cu, 0x030Cu, 0x013Du),
-     HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0323u, 0x1E36u),   HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0327u, 0x013Bu),
-     HB_CODEPOINT_ENCODE3 (0x004Cu, 0x032Du, 0x1E3Cu),   HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0331u, 0x1E3Au),
-     HB_CODEPOINT_ENCODE3 (0x004Du, 0x0301u, 0x1E3Eu),   HB_CODEPOINT_ENCODE3 (0x004Du, 0x0307u, 0x1E40u),
-     HB_CODEPOINT_ENCODE3 (0x004Du, 0x0323u, 0x1E42u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0300u, 0x01F8u),
-     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0301u, 0x0143u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0303u, 0x00D1u),
-     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0307u, 0x1E44u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x030Cu, 0x0147u),
-     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0323u, 0x1E46u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0327u, 0x0145u),
-     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x032Du, 0x1E4Au),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0331u, 0x1E48u),
-     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0300u, 0x00D2u),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0301u, 0x00D3u),
-     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0302u, 0x00D4u),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0303u, 0x00D5u),
-     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0304u, 0x014Cu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0306u, 0x014Eu),
-     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0307u, 0x022Eu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0308u, 0x00D6u),
-     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0309u, 0x1ECEu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Bu, 0x0150u),
-     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Cu, 0x01D1u),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Fu, 0x020Cu),
-     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0311u, 0x020Eu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x031Bu, 0x01A0u),
-     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0323u, 0x1ECCu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0328u, 0x01EAu),
-     HB_CODEPOINT_ENCODE3 (0x0050u, 0x0301u, 0x1E54u),   HB_CODEPOINT_ENCODE3 (0x0050u, 0x0307u, 0x1E56u),
-     HB_CODEPOINT_ENCODE3 (0x0052u, 0x0301u, 0x0154u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x0307u, 0x1E58u),
-     HB_CODEPOINT_ENCODE3 (0x0052u, 0x030Cu, 0x0158u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x030Fu, 0x0210u),
-     HB_CODEPOINT_ENCODE3 (0x0052u, 0x0311u, 0x0212u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x0323u, 0x1E5Au),
-     HB_CODEPOINT_ENCODE3 (0x0052u, 0x0327u, 0x0156u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x0331u, 0x1E5Eu),
-     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0301u, 0x015Au),   HB_CODEPOINT_ENCODE3 (0x0053u, 0x0302u, 0x015Cu),
-     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0307u, 0x1E60u),   HB_CODEPOINT_ENCODE3 (0x0053u, 0x030Cu, 0x0160u),
-     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0323u, 0x1E62u),   HB_CODEPOINT_ENCODE3 (0x0053u, 0x0326u, 0x0218u),
-     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0327u, 0x015Eu),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0307u, 0x1E6Au),
-     HB_CODEPOINT_ENCODE3 (0x0054u, 0x030Cu, 0x0164u),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0323u, 0x1E6Cu),
-     HB_CODEPOINT_ENCODE3 (0x0054u, 0x0326u, 0x021Au),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0327u, 0x0162u),
-     HB_CODEPOINT_ENCODE3 (0x0054u, 0x032Du, 0x1E70u),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0331u, 0x1E6Eu),
-     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0300u, 0x00D9u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0301u, 0x00DAu),
-     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0302u, 0x00DBu),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0303u, 0x0168u),
-     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0304u, 0x016Au),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0306u, 0x016Cu),
-     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0308u, 0x00DCu),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0309u, 0x1EE6u),
-     HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Au, 0x016Eu),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Bu, 0x0170u),
-     HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Cu, 0x01D3u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Fu, 0x0214u),
-     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0311u, 0x0216u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x031Bu, 0x01AFu),
-     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0323u, 0x1EE4u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0324u, 0x1E72u),
-     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0328u, 0x0172u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x032Du, 0x1E76u),
-     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0330u, 0x1E74u),   HB_CODEPOINT_ENCODE3 (0x0056u, 0x0303u, 0x1E7Cu),
-     HB_CODEPOINT_ENCODE3 (0x0056u, 0x0323u, 0x1E7Eu),   HB_CODEPOINT_ENCODE3 (0x0057u, 0x0300u, 0x1E80u),
-     HB_CODEPOINT_ENCODE3 (0x0057u, 0x0301u, 0x1E82u),   HB_CODEPOINT_ENCODE3 (0x0057u, 0x0302u, 0x0174u),
-     HB_CODEPOINT_ENCODE3 (0x0057u, 0x0307u, 0x1E86u),   HB_CODEPOINT_ENCODE3 (0x0057u, 0x0308u, 0x1E84u),
-     HB_CODEPOINT_ENCODE3 (0x0057u, 0x0323u, 0x1E88u),   HB_CODEPOINT_ENCODE3 (0x0058u, 0x0307u, 0x1E8Au),
-     HB_CODEPOINT_ENCODE3 (0x0058u, 0x0308u, 0x1E8Cu),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0300u, 0x1EF2u),
-     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0301u, 0x00DDu),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0302u, 0x0176u),
-     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0303u, 0x1EF8u),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0304u, 0x0232u),
-     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0307u, 0x1E8Eu),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0308u, 0x0178u),
-     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0309u, 0x1EF6u),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0323u, 0x1EF4u),
-     HB_CODEPOINT_ENCODE3 (0x005Au, 0x0301u, 0x0179u),   HB_CODEPOINT_ENCODE3 (0x005Au, 0x0302u, 0x1E90u),
-     HB_CODEPOINT_ENCODE3 (0x005Au, 0x0307u, 0x017Bu),   HB_CODEPOINT_ENCODE3 (0x005Au, 0x030Cu, 0x017Du),
-     HB_CODEPOINT_ENCODE3 (0x005Au, 0x0323u, 0x1E92u),   HB_CODEPOINT_ENCODE3 (0x005Au, 0x0331u, 0x1E94u),
-     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0300u, 0x00E0u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0301u, 0x00E1u),
-     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0302u, 0x00E2u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0303u, 0x00E3u),
-     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0304u, 0x0101u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0306u, 0x0103u),
-     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0307u, 0x0227u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0308u, 0x00E4u),
-     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0309u, 0x1EA3u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Au, 0x00E5u),
-     HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Cu, 0x01CEu),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Fu, 0x0201u),
-     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0311u, 0x0203u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0323u, 0x1EA1u),
-     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0325u, 0x1E01u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0328u, 0x0105u),
-     HB_CODEPOINT_ENCODE3 (0x0062u, 0x0307u, 0x1E03u),   HB_CODEPOINT_ENCODE3 (0x0062u, 0x0323u, 0x1E05u),
-     HB_CODEPOINT_ENCODE3 (0x0062u, 0x0331u, 0x1E07u),   HB_CODEPOINT_ENCODE3 (0x0063u, 0x0301u, 0x0107u),
-     HB_CODEPOINT_ENCODE3 (0x0063u, 0x0302u, 0x0109u),   HB_CODEPOINT_ENCODE3 (0x0063u, 0x0307u, 0x010Bu),
-     HB_CODEPOINT_ENCODE3 (0x0063u, 0x030Cu, 0x010Du),   HB_CODEPOINT_ENCODE3 (0x0063u, 0x0327u, 0x00E7u),
-     HB_CODEPOINT_ENCODE3 (0x0064u, 0x0307u, 0x1E0Bu),   HB_CODEPOINT_ENCODE3 (0x0064u, 0x030Cu, 0x010Fu),
-     HB_CODEPOINT_ENCODE3 (0x0064u, 0x0323u, 0x1E0Du),   HB_CODEPOINT_ENCODE3 (0x0064u, 0x0327u, 0x1E11u),
-     HB_CODEPOINT_ENCODE3 (0x0064u, 0x032Du, 0x1E13u),   HB_CODEPOINT_ENCODE3 (0x0064u, 0x0331u, 0x1E0Fu),
-     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0300u, 0x00E8u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0301u, 0x00E9u),
-     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0302u, 0x00EAu),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0303u, 0x1EBDu),
-     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0304u, 0x0113u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0306u, 0x0115u),
-     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0307u, 0x0117u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0308u, 0x00EBu),
-     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0309u, 0x1EBBu),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x030Cu, 0x011Bu),
-     HB_CODEPOINT_ENCODE3 (0x0065u, 0x030Fu, 0x0205u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0311u, 0x0207u),
-     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0323u, 0x1EB9u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0327u, 0x0229u),
-     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0328u, 0x0119u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x032Du, 0x1E19u),
-     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0330u, 0x1E1Bu),   HB_CODEPOINT_ENCODE3 (0x0066u, 0x0307u, 0x1E1Fu),
-     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0301u, 0x01F5u),   HB_CODEPOINT_ENCODE3 (0x0067u, 0x0302u, 0x011Du),
-     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0304u, 0x1E21u),   HB_CODEPOINT_ENCODE3 (0x0067u, 0x0306u, 0x011Fu),
-     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0307u, 0x0121u),   HB_CODEPOINT_ENCODE3 (0x0067u, 0x030Cu, 0x01E7u),
-     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0327u, 0x0123u),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x0302u, 0x0125u),
-     HB_CODEPOINT_ENCODE3 (0x0068u, 0x0307u, 0x1E23u),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x0308u, 0x1E27u),
-     HB_CODEPOINT_ENCODE3 (0x0068u, 0x030Cu, 0x021Fu),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x0323u, 0x1E25u),
-     HB_CODEPOINT_ENCODE3 (0x0068u, 0x0327u, 0x1E29u),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x032Eu, 0x1E2Bu),
-     HB_CODEPOINT_ENCODE3 (0x0068u, 0x0331u, 0x1E96u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0300u, 0x00ECu),
-     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0301u, 0x00EDu),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0302u, 0x00EEu),
-     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0303u, 0x0129u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0304u, 0x012Bu),
-     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0306u, 0x012Du),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0308u, 0x00EFu),
-     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0309u, 0x1EC9u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x030Cu, 0x01D0u),
-     HB_CODEPOINT_ENCODE3 (0x0069u, 0x030Fu, 0x0209u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0311u, 0x020Bu),
-     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0323u, 0x1ECBu),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0328u, 0x012Fu),
-     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0330u, 0x1E2Du),   HB_CODEPOINT_ENCODE3 (0x006Au, 0x0302u, 0x0135u),
-     HB_CODEPOINT_ENCODE3 (0x006Au, 0x030Cu, 0x01F0u),   HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0301u, 0x1E31u),
-     HB_CODEPOINT_ENCODE3 (0x006Bu, 0x030Cu, 0x01E9u),   HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0323u, 0x1E33u),
-     HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0327u, 0x0137u),   HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0331u, 0x1E35u),
-     HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0301u, 0x013Au),   HB_CODEPOINT_ENCODE3 (0x006Cu, 0x030Cu, 0x013Eu),
-     HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0323u, 0x1E37u),   HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0327u, 0x013Cu),
-     HB_CODEPOINT_ENCODE3 (0x006Cu, 0x032Du, 0x1E3Du),   HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0331u, 0x1E3Bu),
-     HB_CODEPOINT_ENCODE3 (0x006Du, 0x0301u, 0x1E3Fu),   HB_CODEPOINT_ENCODE3 (0x006Du, 0x0307u, 0x1E41u),
-     HB_CODEPOINT_ENCODE3 (0x006Du, 0x0323u, 0x1E43u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0300u, 0x01F9u),
-     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0301u, 0x0144u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0303u, 0x00F1u),
-     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0307u, 0x1E45u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x030Cu, 0x0148u),
-     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0323u, 0x1E47u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0327u, 0x0146u),
-     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x032Du, 0x1E4Bu),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0331u, 0x1E49u),
-     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0300u, 0x00F2u),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0301u, 0x00F3u),
-     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0302u, 0x00F4u),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0303u, 0x00F5u),
-     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0304u, 0x014Du),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0306u, 0x014Fu),
-     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0307u, 0x022Fu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0308u, 0x00F6u),
-     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0309u, 0x1ECFu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Bu, 0x0151u),
-     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Cu, 0x01D2u),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Fu, 0x020Du),
-     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0311u, 0x020Fu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x031Bu, 0x01A1u),
-     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0323u, 0x1ECDu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0328u, 0x01EBu),
-     HB_CODEPOINT_ENCODE3 (0x0070u, 0x0301u, 0x1E55u),   HB_CODEPOINT_ENCODE3 (0x0070u, 0x0307u, 0x1E57u),
-     HB_CODEPOINT_ENCODE3 (0x0072u, 0x0301u, 0x0155u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x0307u, 0x1E59u),
-     HB_CODEPOINT_ENCODE3 (0x0072u, 0x030Cu, 0x0159u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x030Fu, 0x0211u),
-     HB_CODEPOINT_ENCODE3 (0x0072u, 0x0311u, 0x0213u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x0323u, 0x1E5Bu),
-     HB_CODEPOINT_ENCODE3 (0x0072u, 0x0327u, 0x0157u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x0331u, 0x1E5Fu),
-     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0301u, 0x015Bu),   HB_CODEPOINT_ENCODE3 (0x0073u, 0x0302u, 0x015Du),
-     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0307u, 0x1E61u),   HB_CODEPOINT_ENCODE3 (0x0073u, 0x030Cu, 0x0161u),
-     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0323u, 0x1E63u),   HB_CODEPOINT_ENCODE3 (0x0073u, 0x0326u, 0x0219u),
-     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0327u, 0x015Fu),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x0307u, 0x1E6Bu),
-     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0308u, 0x1E97u),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x030Cu, 0x0165u),
-     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0323u, 0x1E6Du),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x0326u, 0x021Bu),
-     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0327u, 0x0163u),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x032Du, 0x1E71u),
-     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0331u, 0x1E6Fu),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0300u, 0x00F9u),
-     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0301u, 0x00FAu),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0302u, 0x00FBu),
-     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0303u, 0x0169u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0304u, 0x016Bu),
-     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0306u, 0x016Du),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0308u, 0x00FCu),
-     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0309u, 0x1EE7u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Au, 0x016Fu),
-     HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Bu, 0x0171u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Cu, 0x01D4u),
-     HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Fu, 0x0215u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0311u, 0x0217u),
-     HB_CODEPOINT_ENCODE3 (0x0075u, 0x031Bu, 0x01B0u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0323u, 0x1EE5u),
-     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0324u, 0x1E73u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0328u, 0x0173u),
-     HB_CODEPOINT_ENCODE3 (0x0075u, 0x032Du, 0x1E77u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0330u, 0x1E75u),
-     HB_CODEPOINT_ENCODE3 (0x0076u, 0x0303u, 0x1E7Du),   HB_CODEPOINT_ENCODE3 (0x0076u, 0x0323u, 0x1E7Fu),
-     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0300u, 0x1E81u),   HB_CODEPOINT_ENCODE3 (0x0077u, 0x0301u, 0x1E83u),
-     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0302u, 0x0175u),   HB_CODEPOINT_ENCODE3 (0x0077u, 0x0307u, 0x1E87u),
-     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0308u, 0x1E85u),   HB_CODEPOINT_ENCODE3 (0x0077u, 0x030Au, 0x1E98u),
-     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0323u, 0x1E89u),   HB_CODEPOINT_ENCODE3 (0x0078u, 0x0307u, 0x1E8Bu),
-     HB_CODEPOINT_ENCODE3 (0x0078u, 0x0308u, 0x1E8Du),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0300u, 0x1EF3u),
-     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0301u, 0x00FDu),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0302u, 0x0177u),
-     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0303u, 0x1EF9u),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0304u, 0x0233u),
-     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0307u, 0x1E8Fu),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0308u, 0x00FFu),
-     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0309u, 0x1EF7u),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x030Au, 0x1E99u),
-     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0323u, 0x1EF5u),   HB_CODEPOINT_ENCODE3 (0x007Au, 0x0301u, 0x017Au),
-     HB_CODEPOINT_ENCODE3 (0x007Au, 0x0302u, 0x1E91u),   HB_CODEPOINT_ENCODE3 (0x007Au, 0x0307u, 0x017Cu),
-     HB_CODEPOINT_ENCODE3 (0x007Au, 0x030Cu, 0x017Eu),   HB_CODEPOINT_ENCODE3 (0x007Au, 0x0323u, 0x1E93u),
-     HB_CODEPOINT_ENCODE3 (0x007Au, 0x0331u, 0x1E95u),   HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0300u, 0x1FEDu),
-     HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0301u, 0x0385u),   HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0342u, 0x1FC1u),
-     HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0300u, 0x1EA6u),   HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0301u, 0x1EA4u),
-     HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0303u, 0x1EAAu),   HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0309u, 0x1EA8u),
-     HB_CODEPOINT_ENCODE3 (0x00C4u, 0x0304u, 0x01DEu),   HB_CODEPOINT_ENCODE3 (0x00C5u, 0x0301u, 0x01FAu),
-     HB_CODEPOINT_ENCODE3 (0x00C6u, 0x0301u, 0x01FCu),   HB_CODEPOINT_ENCODE3 (0x00C6u, 0x0304u, 0x01E2u),
-     HB_CODEPOINT_ENCODE3 (0x00C7u, 0x0301u, 0x1E08u),   HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0300u, 0x1EC0u),
-     HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0301u, 0x1EBEu),   HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0303u, 0x1EC4u),
-     HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0309u, 0x1EC2u),   HB_CODEPOINT_ENCODE3 (0x00CFu, 0x0301u, 0x1E2Eu),
-     HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0300u, 0x1ED2u),   HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0301u, 0x1ED0u),
-     HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0303u, 0x1ED6u),   HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0309u, 0x1ED4u),
-     HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0301u, 0x1E4Cu),   HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0304u, 0x022Cu),
-     HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0308u, 0x1E4Eu),   HB_CODEPOINT_ENCODE3 (0x00D6u, 0x0304u, 0x022Au),
-     HB_CODEPOINT_ENCODE3 (0x00D8u, 0x0301u, 0x01FEu),   HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0300u, 0x01DBu),
-     HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0301u, 0x01D7u),   HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0304u, 0x01D5u),
-     HB_CODEPOINT_ENCODE3 (0x00DCu, 0x030Cu, 0x01D9u),   HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0300u, 0x1EA7u),
-     HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0301u, 0x1EA5u),   HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0303u, 0x1EABu),
-     HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0309u, 0x1EA9u),   HB_CODEPOINT_ENCODE3 (0x00E4u, 0x0304u, 0x01DFu),
-     HB_CODEPOINT_ENCODE3 (0x00E5u, 0x0301u, 0x01FBu),   HB_CODEPOINT_ENCODE3 (0x00E6u, 0x0301u, 0x01FDu),
-     HB_CODEPOINT_ENCODE3 (0x00E6u, 0x0304u, 0x01E3u),   HB_CODEPOINT_ENCODE3 (0x00E7u, 0x0301u, 0x1E09u),
-     HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0300u, 0x1EC1u),   HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0301u, 0x1EBFu),
-     HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0303u, 0x1EC5u),   HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0309u, 0x1EC3u),
-     HB_CODEPOINT_ENCODE3 (0x00EFu, 0x0301u, 0x1E2Fu),   HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0300u, 0x1ED3u),
-     HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0301u, 0x1ED1u),   HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0303u, 0x1ED7u),
-     HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0309u, 0x1ED5u),   HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0301u, 0x1E4Du),
-     HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0304u, 0x022Du),   HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0308u, 0x1E4Fu),
-     HB_CODEPOINT_ENCODE3 (0x00F6u, 0x0304u, 0x022Bu),   HB_CODEPOINT_ENCODE3 (0x00F8u, 0x0301u, 0x01FFu),
-     HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0300u, 0x01DCu),   HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0301u, 0x01D8u),
-     HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0304u, 0x01D6u),   HB_CODEPOINT_ENCODE3 (0x00FCu, 0x030Cu, 0x01DAu),
-     HB_CODEPOINT_ENCODE3 (0x0102u, 0x0300u, 0x1EB0u),   HB_CODEPOINT_ENCODE3 (0x0102u, 0x0301u, 0x1EAEu),
-     HB_CODEPOINT_ENCODE3 (0x0102u, 0x0303u, 0x1EB4u),   HB_CODEPOINT_ENCODE3 (0x0102u, 0x0309u, 0x1EB2u),
-     HB_CODEPOINT_ENCODE3 (0x0103u, 0x0300u, 0x1EB1u),   HB_CODEPOINT_ENCODE3 (0x0103u, 0x0301u, 0x1EAFu),
-     HB_CODEPOINT_ENCODE3 (0x0103u, 0x0303u, 0x1EB5u),   HB_CODEPOINT_ENCODE3 (0x0103u, 0x0309u, 0x1EB3u),
-     HB_CODEPOINT_ENCODE3 (0x0112u, 0x0300u, 0x1E14u),   HB_CODEPOINT_ENCODE3 (0x0112u, 0x0301u, 0x1E16u),
-     HB_CODEPOINT_ENCODE3 (0x0113u, 0x0300u, 0x1E15u),   HB_CODEPOINT_ENCODE3 (0x0113u, 0x0301u, 0x1E17u),
-     HB_CODEPOINT_ENCODE3 (0x014Cu, 0x0300u, 0x1E50u),   HB_CODEPOINT_ENCODE3 (0x014Cu, 0x0301u, 0x1E52u),
-     HB_CODEPOINT_ENCODE3 (0x014Du, 0x0300u, 0x1E51u),   HB_CODEPOINT_ENCODE3 (0x014Du, 0x0301u, 0x1E53u),
-     HB_CODEPOINT_ENCODE3 (0x015Au, 0x0307u, 0x1E64u),   HB_CODEPOINT_ENCODE3 (0x015Bu, 0x0307u, 0x1E65u),
-     HB_CODEPOINT_ENCODE3 (0x0160u, 0x0307u, 0x1E66u),   HB_CODEPOINT_ENCODE3 (0x0161u, 0x0307u, 0x1E67u),
-     HB_CODEPOINT_ENCODE3 (0x0168u, 0x0301u, 0x1E78u),   HB_CODEPOINT_ENCODE3 (0x0169u, 0x0301u, 0x1E79u),
-     HB_CODEPOINT_ENCODE3 (0x016Au, 0x0308u, 0x1E7Au),   HB_CODEPOINT_ENCODE3 (0x016Bu, 0x0308u, 0x1E7Bu),
-     HB_CODEPOINT_ENCODE3 (0x017Fu, 0x0307u, 0x1E9Bu),   HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0300u, 0x1EDCu),
-     HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0301u, 0x1EDAu),   HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0303u, 0x1EE0u),
-     HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0309u, 0x1EDEu),   HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0323u, 0x1EE2u),
-     HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0300u, 0x1EDDu),   HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0301u, 0x1EDBu),
-     HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0303u, 0x1EE1u),   HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0309u, 0x1EDFu),
-     HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0323u, 0x1EE3u),   HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0300u, 0x1EEAu),
-     HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0301u, 0x1EE8u),   HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0303u, 0x1EEEu),
-     HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0309u, 0x1EECu),   HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0323u, 0x1EF0u),
-     HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0300u, 0x1EEBu),   HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0301u, 0x1EE9u),
-     HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0303u, 0x1EEFu),   HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0309u, 0x1EEDu),
-     HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0323u, 0x1EF1u),   HB_CODEPOINT_ENCODE3 (0x01B7u, 0x030Cu, 0x01EEu),
-     HB_CODEPOINT_ENCODE3 (0x01EAu, 0x0304u, 0x01ECu),   HB_CODEPOINT_ENCODE3 (0x01EBu, 0x0304u, 0x01EDu),
-     HB_CODEPOINT_ENCODE3 (0x0226u, 0x0304u, 0x01E0u),   HB_CODEPOINT_ENCODE3 (0x0227u, 0x0304u, 0x01E1u),
-     HB_CODEPOINT_ENCODE3 (0x0228u, 0x0306u, 0x1E1Cu),   HB_CODEPOINT_ENCODE3 (0x0229u, 0x0306u, 0x1E1Du),
-     HB_CODEPOINT_ENCODE3 (0x022Eu, 0x0304u, 0x0230u),   HB_CODEPOINT_ENCODE3 (0x022Fu, 0x0304u, 0x0231u),
-     HB_CODEPOINT_ENCODE3 (0x0292u, 0x030Cu, 0x01EFu),   HB_CODEPOINT_ENCODE3 (0x0308u, 0x0301u, 0x0000u),
-     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0300u, 0x1FBAu),   HB_CODEPOINT_ENCODE3 (0x0391u, 0x0301u, 0x0386u),
-     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0304u, 0x1FB9u),   HB_CODEPOINT_ENCODE3 (0x0391u, 0x0306u, 0x1FB8u),
-     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0313u, 0x1F08u),   HB_CODEPOINT_ENCODE3 (0x0391u, 0x0314u, 0x1F09u),
-     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0345u, 0x1FBCu),   HB_CODEPOINT_ENCODE3 (0x0395u, 0x0300u, 0x1FC8u),
-     HB_CODEPOINT_ENCODE3 (0x0395u, 0x0301u, 0x0388u),   HB_CODEPOINT_ENCODE3 (0x0395u, 0x0313u, 0x1F18u),
-     HB_CODEPOINT_ENCODE3 (0x0395u, 0x0314u, 0x1F19u),   HB_CODEPOINT_ENCODE3 (0x0397u, 0x0300u, 0x1FCAu),
-     HB_CODEPOINT_ENCODE3 (0x0397u, 0x0301u, 0x0389u),   HB_CODEPOINT_ENCODE3 (0x0397u, 0x0313u, 0x1F28u),
-     HB_CODEPOINT_ENCODE3 (0x0397u, 0x0314u, 0x1F29u),   HB_CODEPOINT_ENCODE3 (0x0397u, 0x0345u, 0x1FCCu),
-     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0300u, 0x1FDAu),   HB_CODEPOINT_ENCODE3 (0x0399u, 0x0301u, 0x038Au),
-     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0304u, 0x1FD9u),   HB_CODEPOINT_ENCODE3 (0x0399u, 0x0306u, 0x1FD8u),
-     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0308u, 0x03AAu),   HB_CODEPOINT_ENCODE3 (0x0399u, 0x0313u, 0x1F38u),
-     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0314u, 0x1F39u),   HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0300u, 0x1FF8u),
-     HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0301u, 0x038Cu),   HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0313u, 0x1F48u),
-     HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0314u, 0x1F49u),   HB_CODEPOINT_ENCODE3 (0x03A1u, 0x0314u, 0x1FECu),
-     HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0300u, 0x1FEAu),   HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0301u, 0x038Eu),
-     HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0304u, 0x1FE9u),   HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0306u, 0x1FE8u),
-     HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0308u, 0x03ABu),   HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0314u, 0x1F59u),
-     HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0300u, 0x1FFAu),   HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0301u, 0x038Fu),
-     HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0313u, 0x1F68u),   HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0314u, 0x1F69u),
-     HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0345u, 0x1FFCu),   HB_CODEPOINT_ENCODE3 (0x03ACu, 0x0345u, 0x1FB4u),
-     HB_CODEPOINT_ENCODE3 (0x03AEu, 0x0345u, 0x1FC4u),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0300u, 0x1F70u),
-     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0301u, 0x03ACu),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0304u, 0x1FB1u),
-     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0306u, 0x1FB0u),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0313u, 0x1F00u),
-     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0314u, 0x1F01u),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0342u, 0x1FB6u),
-     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0345u, 0x1FB3u),   HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0300u, 0x1F72u),
-     HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0301u, 0x03ADu),   HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0313u, 0x1F10u),
-     HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0314u, 0x1F11u),   HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0300u, 0x1F74u),
-     HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0301u, 0x03AEu),   HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0313u, 0x1F20u),
-     HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0314u, 0x1F21u),   HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0342u, 0x1FC6u),
-     HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0345u, 0x1FC3u),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0300u, 0x1F76u),
-     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0301u, 0x03AFu),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0304u, 0x1FD1u),
-     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0306u, 0x1FD0u),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0308u, 0x03CAu),
-     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0313u, 0x1F30u),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0314u, 0x1F31u),
-     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0342u, 0x1FD6u),   HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0300u, 0x1F78u),
-     HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0301u, 0x03CCu),   HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0313u, 0x1F40u),
-     HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0314u, 0x1F41u),   HB_CODEPOINT_ENCODE3 (0x03C1u, 0x0313u, 0x1FE4u),
-     HB_CODEPOINT_ENCODE3 (0x03C1u, 0x0314u, 0x1FE5u),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0300u, 0x1F7Au),
-     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0301u, 0x03CDu),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0304u, 0x1FE1u),
-     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0306u, 0x1FE0u),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0308u, 0x03CBu),
-     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0313u, 0x1F50u),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0314u, 0x1F51u),
-     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0342u, 0x1FE6u),   HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0300u, 0x1F7Cu),
-     HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0301u, 0x03CEu),   HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0313u, 0x1F60u),
-     HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0314u, 0x1F61u),   HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0342u, 0x1FF6u),
-     HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0345u, 0x1FF3u),   HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0300u, 0x1FD2u),
-     HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0301u, 0x0390u),   HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0342u, 0x1FD7u),
-     HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0300u, 0x1FE2u),   HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0301u, 0x03B0u),
-     HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0342u, 0x1FE7u),   HB_CODEPOINT_ENCODE3 (0x03CEu, 0x0345u, 0x1FF4u),
-     HB_CODEPOINT_ENCODE3 (0x03D2u, 0x0301u, 0x03D3u),   HB_CODEPOINT_ENCODE3 (0x03D2u, 0x0308u, 0x03D4u),
-     HB_CODEPOINT_ENCODE3 (0x0406u, 0x0308u, 0x0407u),   HB_CODEPOINT_ENCODE3 (0x0410u, 0x0306u, 0x04D0u),
-     HB_CODEPOINT_ENCODE3 (0x0410u, 0x0308u, 0x04D2u),   HB_CODEPOINT_ENCODE3 (0x0413u, 0x0301u, 0x0403u),
-     HB_CODEPOINT_ENCODE3 (0x0415u, 0x0300u, 0x0400u),   HB_CODEPOINT_ENCODE3 (0x0415u, 0x0306u, 0x04D6u),
-     HB_CODEPOINT_ENCODE3 (0x0415u, 0x0308u, 0x0401u),   HB_CODEPOINT_ENCODE3 (0x0416u, 0x0306u, 0x04C1u),
-     HB_CODEPOINT_ENCODE3 (0x0416u, 0x0308u, 0x04DCu),   HB_CODEPOINT_ENCODE3 (0x0417u, 0x0308u, 0x04DEu),
-     HB_CODEPOINT_ENCODE3 (0x0418u, 0x0300u, 0x040Du),   HB_CODEPOINT_ENCODE3 (0x0418u, 0x0304u, 0x04E2u),
-     HB_CODEPOINT_ENCODE3 (0x0418u, 0x0306u, 0x0419u),   HB_CODEPOINT_ENCODE3 (0x0418u, 0x0308u, 0x04E4u),
-     HB_CODEPOINT_ENCODE3 (0x041Au, 0x0301u, 0x040Cu),   HB_CODEPOINT_ENCODE3 (0x041Eu, 0x0308u, 0x04E6u),
-     HB_CODEPOINT_ENCODE3 (0x0423u, 0x0304u, 0x04EEu),   HB_CODEPOINT_ENCODE3 (0x0423u, 0x0306u, 0x040Eu),
-     HB_CODEPOINT_ENCODE3 (0x0423u, 0x0308u, 0x04F0u),   HB_CODEPOINT_ENCODE3 (0x0423u, 0x030Bu, 0x04F2u),
-     HB_CODEPOINT_ENCODE3 (0x0427u, 0x0308u, 0x04F4u),   HB_CODEPOINT_ENCODE3 (0x042Bu, 0x0308u, 0x04F8u),
-     HB_CODEPOINT_ENCODE3 (0x042Du, 0x0308u, 0x04ECu),   HB_CODEPOINT_ENCODE3 (0x0430u, 0x0306u, 0x04D1u),
-     HB_CODEPOINT_ENCODE3 (0x0430u, 0x0308u, 0x04D3u),   HB_CODEPOINT_ENCODE3 (0x0433u, 0x0301u, 0x0453u),
-     HB_CODEPOINT_ENCODE3 (0x0435u, 0x0300u, 0x0450u),   HB_CODEPOINT_ENCODE3 (0x0435u, 0x0306u, 0x04D7u),
-     HB_CODEPOINT_ENCODE3 (0x0435u, 0x0308u, 0x0451u),   HB_CODEPOINT_ENCODE3 (0x0436u, 0x0306u, 0x04C2u),
-     HB_CODEPOINT_ENCODE3 (0x0436u, 0x0308u, 0x04DDu),   HB_CODEPOINT_ENCODE3 (0x0437u, 0x0308u, 0x04DFu),
-     HB_CODEPOINT_ENCODE3 (0x0438u, 0x0300u, 0x045Du),   HB_CODEPOINT_ENCODE3 (0x0438u, 0x0304u, 0x04E3u),
-     HB_CODEPOINT_ENCODE3 (0x0438u, 0x0306u, 0x0439u),   HB_CODEPOINT_ENCODE3 (0x0438u, 0x0308u, 0x04E5u),
-     HB_CODEPOINT_ENCODE3 (0x043Au, 0x0301u, 0x045Cu),   HB_CODEPOINT_ENCODE3 (0x043Eu, 0x0308u, 0x04E7u),
-     HB_CODEPOINT_ENCODE3 (0x0443u, 0x0304u, 0x04EFu),   HB_CODEPOINT_ENCODE3 (0x0443u, 0x0306u, 0x045Eu),
-     HB_CODEPOINT_ENCODE3 (0x0443u, 0x0308u, 0x04F1u),   HB_CODEPOINT_ENCODE3 (0x0443u, 0x030Bu, 0x04F3u),
-     HB_CODEPOINT_ENCODE3 (0x0447u, 0x0308u, 0x04F5u),   HB_CODEPOINT_ENCODE3 (0x044Bu, 0x0308u, 0x04F9u),
-     HB_CODEPOINT_ENCODE3 (0x044Du, 0x0308u, 0x04EDu),   HB_CODEPOINT_ENCODE3 (0x0456u, 0x0308u, 0x0457u),
-     HB_CODEPOINT_ENCODE3 (0x0474u, 0x030Fu, 0x0476u),   HB_CODEPOINT_ENCODE3 (0x0475u, 0x030Fu, 0x0477u),
-     HB_CODEPOINT_ENCODE3 (0x04D8u, 0x0308u, 0x04DAu),   HB_CODEPOINT_ENCODE3 (0x04D9u, 0x0308u, 0x04DBu),
-     HB_CODEPOINT_ENCODE3 (0x04E8u, 0x0308u, 0x04EAu),   HB_CODEPOINT_ENCODE3 (0x04E9u, 0x0308u, 0x04EBu),
      HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B8u, 0x0000u),
      HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BCu, 0x0000u),
      HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BFu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D2u, 0x05BCu, 0x0000u),
      HB_CODEPOINT_ENCODE3 (0x05D3u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D4u, 0x05BCu, 0x0000u),
      HB_CODEPOINT_ENCODE3 (0x05D5u, 0x05B9u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D5u, 0x05BCu, 0x0000u),
      HB_CODEPOINT_ENCODE3 (0x05D6u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D8u, 0x05BCu, 0x0000u),
      HB_CODEPOINT_ENCODE3 (0x05D9u, 0x05B4u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D9u, 0x05BCu, 0x0000u),
      HB_CODEPOINT_ENCODE3 (0x05DAu, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05DBu, 0x05BCu, 0x0000u),
@@ -723,17 +1058,17 @@ static const uint64_t
    HB_CODEPOINT_ENCODE3 (0x1D1BAu, 0x1D165u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D1BBu, 0x1D16Eu, 0x0000u),
    HB_CODEPOINT_ENCODE3 (0x1D1BBu, 0x1D16Fu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D1BCu, 0x1D16Eu, 0x0000u),
    HB_CODEPOINT_ENCODE3 (0x1D1BCu, 0x1D16Fu, 0x0000u),
 };
 
 #ifndef HB_OPTIMIZE_SIZE
 
 static const uint8_t
-_hb_ucd_u8[31814] =
+_hb_ucd_u8[32102] =
 {
     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, 26, 26, 26,
    26, 26, 26, 26, 26, 26, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26,
    26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
    26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 28,
    29, 26, 30, 31, 32, 33, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
    26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 34, 35, 35, 35, 35,
@@ -2334,21 +2669,27 @@ static const uint8_t
     2,  2,  2,  2, 82, 82, 82, 82, 82, 82, 82, 82,122,122,122,122,
   122,122,122,122,122,122,122,122,122,122,122,122,122,122,  2,  2,
     2,  2,  2,  2,  2,122,122,122,122,  2,  2,  2,  2,  2,  2,  2,
     2,  2,  2,  2,  2,122,122,122,122,122,122,122, 89, 89, 89, 89,
    89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
    89, 89, 89, 89, 89,  2,  2,  2,  2,  2,  2,  2,130,130,130,130,
   130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,  2,
     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,130,130,130,  2,
-    2,  2,  2,  2,  2,  2,130,130,130,130,130,130,  0,  0,  0,  0,
-    0,  0,  0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
-    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  1,  1,  1,  1,
-    1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
-    3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  2,  2, 94, 94, 94, 94,
+    2,  2,  2,  2,  2,  2,130,130,130,130,130,130,144,144,144,144,
+  144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
+  144,144,144,144,  2,  2,  2,  2,  2,  2,  2,  2,144,144,144,144,
+  144,144,144,144,144,144,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,147,147,147,147,
+  147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,
+  147,147,147,147,  2,  2,  2,  2,  2,  2,  2,  2,148,148,148,148,
+  148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
+  148,148,148,148,148,148,  2,  2,  2,  2,  2,  2,149,149,149,149,
+  149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
+  149,149,149,  2,  2,  2,  2,  2,  2,  2,  2,  2, 94, 94, 94, 94,
    94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
    94, 94, 94, 94, 94, 94, 94, 94, 94, 94,  2,  2,  2,  2, 94, 94,
    94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,  2,  2,  2,  2,
     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 94, 85, 85, 85, 85,
    85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,  2,  2,
     2,  2,  2,  2,  2,  2,  2,  2,  2, 85,  2,  2,101,101,101,101,
   101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
   101,101,101,101,101,  2,  2,  2,  2,  2,  2,  2,101,101,101,101,
@@ -2391,45 +2732,51 @@ static const uint8_t
   114,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,114,114,114,114,
   114,114,114,114,114,114,  2,  2,  2,  2,  2,  2, 32, 32, 32, 32,
    32, 32, 32, 32, 32, 32, 32, 32, 32,  2,  2,  2,102,102,102,102,
   102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,
   102,102,102,102,102,  2,  2,  2,  2,  2,  2,  2,102,102,102,102,
   102,102,102,102,102,102,  2,  2,  2,  2,  2,  2,126,126,126,126,
   126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,
   126,126,126,126,126,126,126,  2,  2,126,126,126,126,126,126,126,
-  126,126,126,126,126,126,126,126,  2,  2,  2,  2,  4,  4,  4,  4,
-    4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,125,125,125,125,
+  126,126,126,126,126,126,126,126,  2,  2,  2,  2,142,142,142,142,
+  142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,
+  142,142,142,142,142,142,142,142,  2,  2,  2,  2,125,125,125,125,
   125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,  2,
-    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,125,  5,  5,  5,  5,
-    5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-    5,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  6,  6,  6,  6,
-    6,  6,  6,  6,  2,  2,  2,  2,  2,  2,  2,  2,  7,  7,  7,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,125,150,150,150,150,
+  150,150,150,150,  2,  2,150,150,150,150,150,150,150,150,150,150,
+  150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+  150,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,141,141,141,141,
+  141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
+  141,141,141,141,  2,  2,  2,  2,  2,  2,  2,  2,140,140,140,140,
+  140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,  2,
     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,121,121,121,121,
   121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
   121,121,121,121,121,  2,  2,  2,  2,  2,  2,  2,133,133,133,133,
   133,133,133,133,133,  2,133,133,133,133,133,133,133,133,133,133,
   133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
   133,133,133,  2,133,133,133,133,133,133,133,133,133,133,133,133,
   133,133,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,133,133,133,133,
   133,133,133,133,133,133,133,133,133,  2,  2,  2,134,134,134,134,
   134,134,134,134,134,134,134,134,134,134,134,134,  2,  2,134,134,
   134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,
   134,134,134,134,  2,134,134,134,134,134,134,134,134,134,134,134,
-  134,134,134,  2,  2,  2,  2,  2,  2,  2,  2,  2,  8,  8,  8,  8,
-    8,  8,  8,  2,  8,  8,  2,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-    8,  8,  8,  2,  2,  2,  8,  2,  8,  8,  2,  8,  8,  8,  8,  8,
-    8,  8,  8,  8,  2,  2,  2,  2,  2,  2,  2,  2,  8,  8,  8,  8,
-    8,  8,  8,  8,  8,  8,  2,  2,  2,  2,  2,  2,  9,  9,  9,  9,
-    9,  9,  2,  9,  9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  2,  9,
-    9,  9,  9,  9,  9,  2,  2,  2,  2,  2,  2,  2,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  2,  2,  2,  2,  2,  2, 10, 10, 10, 10,
-   10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-   10, 10, 10, 10, 10,  2,  2,  2,  2,  2,  2,  2, 22, 22, 22, 22,
+  134,134,134,  2,  2,  2,  2,  2,  2,  2,  2,  2,138,138,138,138,
+  138,138,138,  2,138,138,  2,138,138,138,138,138,138,138,138,138,
+  138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,
+  138,138,138,  2,  2,  2,138,  2,138,138,  2,138,138,138,138,138,
+  138,138,138,138,  2,  2,  2,  2,  2,  2,  2,  2,138,138,138,138,
+  138,138,138,138,138,138,  2,  2,  2,  2,  2,  2,143,143,143,143,
+  143,143,  2,143,143,  2,143,143,143,143,143,143,143,143,143,143,
+  143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
+  143,143,143,143,143,143,143,143,143,143,143,  2,143,143,  2,143,
+  143,143,143,143,143,  2,  2,  2,  2,  2,  2,  2,143,143,143,143,
+  143,143,143,143,143,143,  2,  2,  2,  2,  2,  2,145,145,145,145,
+  145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
+  145,145,145,145,145,  2,  2,  2,  2,  2,  2,  2, 22, 22, 22, 22,
    22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,  2,  2,
     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 22, 63, 63, 63, 63,
    63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,