changeset 53444:4c30c8658495

8210782: Upgrade HarfBuzz to the latest 2.3.1 Reviewed-by: serb, ihse, erikj
author prr
date Sun, 10 Mar 2019 03:34:59 -0700
parents 1cbbfbe009d0
children 2cc4a95e4af7
files make/lib/Awt2dLibraries.gmk src/java.desktop/share/legal/harfbuzz.md src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-fdsc-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-ankr-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-bsln-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-common.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-feat-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-just-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-kerx-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-lcar-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-morx-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-trak-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-ltag-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-map.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-map.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-array.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-atomic-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-atomic.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-json.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-text.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-serialize.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff-interp-common.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff-interp-cs-common.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff-interp-dict-common.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff1-interp-cs.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff2-interp-cs.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-coretext.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-debug.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-deprecated.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-dsalgs.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-fallback-shape.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ft.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-iter.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-kern.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-machinery.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-mutex-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-mutex.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-null.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-object-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-object.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-file-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-file.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff-common.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff1-table.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff1-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff2-table.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff2-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cmap-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-cbdt-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-colr-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-cpal-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-sbix-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-svg-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-deprecated.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-face.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-face.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-font.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-gasp-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-glyf-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hdmx-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-head-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hhea-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hmtx-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-kern-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-base-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-common-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-common.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gdef-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gpos-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsub-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsubgpos-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsubgpos.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-jstf-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-map-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-map.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-map.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-math-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-math.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-maxp-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name-language.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name-language.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-os2-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-os2-unicode-ranges.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-post-macroman.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-post-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-fallback.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-win1256.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-default.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-hangul.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-hebrew.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-machine.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-table.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer-machine.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar-machine.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-thai.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-tibetan.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-machine.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-table.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-vowel-constraints.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-vowel-constraints.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-normalize-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-normalize.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-normalize.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-stat-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-tag-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-tag.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-tag.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-avar-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-fvar-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-hvar-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-mvar-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-vorg-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set-digest-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set-digest.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape-plan-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape-plan.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape-plan.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-impl-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-impl.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-list.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-static.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-string-array.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff-common.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff-common.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff1.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff1.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff2.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff2.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-glyf.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-glyf.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-input.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-input.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-plan.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-plan.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ucdn.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ucdn/ucdn.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode-emoji-table.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-utf-private.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-utf.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-vector.hh src/java.desktop/share/native/libfontmanager/harfbuzz/hb-version.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb-warning.cc src/java.desktop/share/native/libfontmanager/harfbuzz/hb.h src/java.desktop/share/native/libfontmanager/harfbuzz/hb.hh src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc
diffstat 222 files changed, 46683 insertions(+), 22097 deletions(-) [+]
line wrap: on
line diff
--- a/make/lib/Awt2dLibraries.gmk	Mon Feb 25 17:16:03 2019 -0800
+++ b/make/lib/Awt2dLibraries.gmk	Sun Mar 10 03:34:59 2019 -0700
@@ -536,7 +536,8 @@
 
 ifneq ($(OPENJDK_TARGET_OS), windows)
   HARFBUZZ_CFLAGS += -DGETPAGESIZE -DHAVE_MPROTECT -DHAVE_PTHREAD \
-                      -DHAVE_SYSCONF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H
+                      -DHAVE_SYSCONF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H \
+                      -DHB_NO_PRAGMA_GCC_DIAGNOSTIC
 endif
 ifneq (, $(findstring $(OPENJDK_TARGET_OS), linux macosx))
   HARFBUZZ_CFLAGS += -DHAVE_INTEL_ATOMIC_PRIMITIVES
@@ -613,7 +614,7 @@
         type-limits missing-field-initializers implicit-fallthrough \
         strict-aliasing undef unused-function, \
     DISABLED_WARNINGS_CXX_gcc := reorder delete-non-virtual-dtor strict-overflow \
-        maybe-uninitialized, \
+        maybe-uninitialized class-memaccess, \
     DISABLED_WARNINGS_clang := unused-value incompatible-pointer-types \
         tautological-constant-out-of-range-compare int-to-pointer-cast \
         sign-compare undef missing-field-initializers, \
@@ -623,8 +624,8 @@
         E_ENUM_VAL_OVERFLOWS_INT_MAX, \
     DISABLED_WARNINGS_CXX_solstudio := \
         truncwarn wvarhidenmem wvarhidemem wbadlkginit identexpected \
-        hidevf w_novirtualdescr arrowrtn2, \
-    DISABLED_WARNINGS_microsoft := 4267 4244 4018 4090 4996 4146 4334 4819 4101, \
+        hidevf w_novirtualdescr arrowrtn2 refmemnoconstr_aggr unknownpragma, \
+    DISABLED_WARNINGS_microsoft := 4267 4244 4018 4090 4996 4146 4334 4819 4101 4068 4805 4138, \
     LDFLAGS := $(subst -Xlinker -z -Xlinker defs,, \
         $(subst -Wl$(COMMA)-z$(COMMA)defs,,$(LDFLAGS_JDKLIB))) $(LDFLAGS_CXX_JDK) \
         $(call SET_SHARED_LIBRARY_ORIGIN), \
--- a/src/java.desktop/share/legal/harfbuzz.md	Mon Feb 25 17:16:03 2019 -0800
+++ b/src/java.desktop/share/legal/harfbuzz.md	Sun Mar 10 03:34:59 2019 -0700
@@ -1,4 +1,4 @@
-## Harfbuzz v1.8.2
+## Harfbuzz v2.3.1
 
 ### Harfbuzz License
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-fdsc-table.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,126 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_AAT_FDSC_TABLE_HH
+#define HB_AAT_FDSC_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+#include "hb-open-type.hh"
+
+/*
+ * fdsc -- Font descriptors
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fdsc.html
+ */
+#define HB_AAT_TAG_fdsc HB_TAG('f','d','s','c')
+
+
+namespace AAT {
+
+
+struct FontDescriptor
+{
+  bool has_data () const { return tag; }
+
+  int cmp (hb_tag_t a) const { return tag.cmp (a); }
+
+  float get_value () const { return u.value.to_float (); }
+
+  enum non_alphabetic_value_t {
+    Alphabetic          = 0,
+    Dingbats            = 1,
+    PiCharacters        = 2,
+    Fleurons            = 3,
+    DecorativeBorders   = 4,
+    InternationalSymbols= 5,
+    MathSymbols         = 6
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  Tag           tag;            /* The 4-byte table tag name. */
+  union {
+  Fixed         value;          /* The value for the descriptor tag. */
+  HBUINT32      nalfType;       /* If the tag is `nalf`, see non_alphabetic_value_t */
+  } u;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct fdsc
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_fdsc;
+
+  enum {
+    Weight       = HB_TAG ('w','g','h','t'),
+                                /* Percent weight relative to regular weight.
+                                 * (defaul value: 1.0) */
+    Width        = HB_TAG ('w','d','t','h'),
+                                /* Percent width relative to regular width.
+                                 * (default value: 1.0) */
+    Slant        = HB_TAG ('s','l','n','t'),
+                                /* Angle of slant in degrees, where positive
+                                 * is clockwise from straight up.
+                                 * (default value: 0.0) */
+    OpticalSize  = HB_TAG ('o','p','s','z'),
+                                /* Point size the font was designed for.
+                                 * (default value: 12.0) */
+    NonAlphabetic= HB_TAG ('n','a','l','f')
+                                /* These values are treated as integers,
+                                 * not fixed32s. 0 means alphabetic, and greater
+                                 * integers mean the font is non-alphabetic (e.g. symbols).
+                                 * (default value: 0) */
+  };
+
+  const FontDescriptor &get_descriptor (hb_tag_t style) const
+  { return descriptors.lsearch (style); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  descriptors.sanitize (c));
+  }
+
+  protected:
+  Fixed         version;        /* Version number of the font descriptors
+                                 * table (0x00010000 for the current version). */
+  LArrayOf<FontDescriptor>
+                descriptors;    /* List of tagged-coordinate pairs style descriptors
+                                 * that will be included to characterize this font.
+                                 * Each descriptor consists of a <tag, value> pair.
+                                 * These pairs are located in the gxFontDescriptor
+                                 * array that follows. */
+  public:
+  DEFINE_SIZE_ARRAY (8, descriptors);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_FDSC_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-ankr-table.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_AAT_LAYOUT_ANKR_TABLE_HH
+#define HB_AAT_LAYOUT_ANKR_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+
+/*
+ * ankr -- Anchor Point
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ankr.html
+ */
+#define HB_AAT_TAG_ankr HB_TAG('a','n','k','r')
+
+
+namespace AAT {
+
+using namespace OT;
+
+
+struct Anchor
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  FWORD         xCoordinate;
+  FWORD         yCoordinate;
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+typedef LArrayOf<Anchor> GlyphAnchors;
+
+struct ankr
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_ankr;
+
+  const Anchor &get_anchor (hb_codepoint_t glyph_id,
+                            unsigned int i,
+                            unsigned int num_glyphs) const
+  {
+    const NNOffsetTo<GlyphAnchors> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs);
+    if (!offset)
+      return Null(Anchor);
+    const GlyphAnchors &anchors = &(this+anchorData) + *offset;
+    return anchors[i];
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          version == 0 &&
+                          lookupTable.sanitize (c, this, &(this+anchorData))));
+  }
+
+  protected:
+  HBUINT16      version;        /* Version number (set to zero) */
+  HBUINT16      flags;          /* Flags (currently unused; set to zero) */
+  LOffsetTo<Lookup<NNOffsetTo<GlyphAnchors> > >
+                lookupTable;    /* Offset to the table's lookup table */
+  LNNOffsetTo<HBUINT8>
+                anchorData;     /* Offset to the glyph data table */
+
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_ANKR_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-bsln-table.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,158 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_AAT_LAYOUT_BSLN_TABLE_HH
+#define HB_AAT_LAYOUT_BSLN_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+
+/*
+ * bsln -- Baseline
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6bsln.html
+ */
+#define HB_AAT_TAG_bsln HB_TAG('b','s','l','n')
+
+
+namespace AAT {
+
+
+struct BaselineTableFormat0Part
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  // Roman, Ideographic centered, Ideographic low, Hanging and Math
+  // are the default defined ones, but any other maybe accessed also.
+  HBINT16       deltas[32];     /* These are the FUnit distance deltas from
+                                 * the font's natural baseline to the other
+                                 * baselines used in the font. */
+  public:
+  DEFINE_SIZE_STATIC (64);
+};
+
+struct BaselineTableFormat1Part
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          lookupTable.sanitize (c)));
+  }
+
+  protected:
+  HBINT16       deltas[32];     /* ditto */
+  Lookup<HBUINT16>
+                lookupTable;    /* Lookup table that maps glyphs to their
+                                 * baseline values. */
+  public:
+  DEFINE_SIZE_MIN (66);
+};
+
+struct BaselineTableFormat2Part
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  GlyphID       stdGlyph;       /* The specific glyph index number in this
+                                 * font that is used to set the baseline values.
+                                 * This is the standard glyph.
+                                 * This glyph must contain a set of control points
+                                 * (whose numbers are contained in the ctlPoints field)
+                                 * that are used to determine baseline distances. */
+  HBUINT16      ctlPoints[32];  /* Set of control point numbers,
+                                 * associated with the standard glyph.
+                                 * A value of 0xFFFF means there is no corresponding
+                                 * control point in the standard glyph. */
+  public:
+  DEFINE_SIZE_STATIC (66);
+};
+
+struct BaselineTableFormat3Part
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && lookupTable.sanitize (c));
+  }
+
+  protected:
+  GlyphID       stdGlyph;       /* ditto */
+  HBUINT16      ctlPoints[32];  /* ditto */
+  Lookup<HBUINT16>
+                lookupTable;    /* Lookup table that maps glyphs to their
+                                 * baseline values. */
+  public:
+  DEFINE_SIZE_MIN (68);
+};
+
+struct bsln
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_bsln;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!(c->check_struct (this) && defaultBaseline < 32)))
+      return_trace (false);
+
+    switch (format)
+    {
+    case 0: return_trace (parts.format0.sanitize (c));
+    case 1: return_trace (parts.format1.sanitize (c));
+    case 2: return_trace (parts.format2.sanitize (c));
+    case 3: return_trace (parts.format3.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
+  protected:
+  FixedVersion<>version;        /* Version number of the Baseline table. */
+  HBUINT16      format;         /* Format of the baseline table. Only one baseline
+                                 * format may be selected for the font. */
+  HBUINT16      defaultBaseline;/* Default baseline value for all glyphs.
+                                 * This value can be from 0 through 31. */
+  union {
+  // Distance-Based Formats
+  BaselineTableFormat0Part      format0;
+  BaselineTableFormat1Part      format1;
+  // Control Point-based Formats
+  BaselineTableFormat2Part      format2;
+  BaselineTableFormat3Part      format3;
+  } parts;
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_BSLN_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-common.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,845 @@
+/*
+ * Copyright © 2017  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_LAYOUT_COMMON_HH
+#define HB_AAT_LAYOUT_COMMON_HH
+
+#include "hb-aat-layout.hh"
+#include "hb-open-type.hh"
+
+
+namespace AAT {
+
+using namespace OT;
+
+
+/*
+ * Lookup Table
+ */
+
+template <typename T> struct Lookup;
+
+template <typename T>
+struct LookupFormat0
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+  {
+    if (unlikely (glyph_id >= num_glyphs)) return nullptr;
+    return &arrayZ[glyph_id];
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (arrayZ.sanitize (c, c->get_num_glyphs ()));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (arrayZ.sanitize (c, c->get_num_glyphs (), base));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 0 */
+  UnsizedArrayOf<T>
+                arrayZ;         /* Array of lookup values, indexed by glyph index. */
+  public:
+  DEFINE_SIZE_UNBOUNDED (2);
+};
+
+
+template <typename T>
+struct LookupSegmentSingle
+{
+  static constexpr unsigned TerminationWordCount = 2u;
+
+  int cmp (hb_codepoint_t g) const
+  { return g < first ? -1 : g <= last ? 0 : +1 ; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && value.sanitize (c));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && value.sanitize (c, base));
+  }
+
+  GlyphID       last;           /* Last GlyphID in this segment */
+  GlyphID       first;          /* First GlyphID in this segment */
+  T             value;          /* The lookup value (only one) */
+  public:
+  DEFINE_SIZE_STATIC (4 + T::static_size);
+};
+
+template <typename T>
+struct LookupFormat2
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id) const
+  {
+    const LookupSegmentSingle<T> *v = segments.bsearch (glyph_id);
+    return v ? &v->value : nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (segments.sanitize (c));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (segments.sanitize (c, base));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 2 */
+  VarSizedBinSearchArrayOf<LookupSegmentSingle<T> >
+                segments;       /* The actual segments. These must already be sorted,
+                                 * according to the first word in each one (the last
+                                 * glyph in each segment). */
+  public:
+  DEFINE_SIZE_ARRAY (8, segments);
+};
+
+template <typename T>
+struct LookupSegmentArray
+{
+  static constexpr unsigned TerminationWordCount = 2u;
+
+  const T* get_value (hb_codepoint_t glyph_id, const void *base) const
+  {
+    return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
+  }
+
+  int cmp (hb_codepoint_t g) const
+  { return g < first ? -1 : g <= last ? 0 : +1; }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  first <= last &&
+                  valuesZ.sanitize (c, base, last - first + 1));
+  }
+  template <typename T2>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T2 user_data) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  first <= last &&
+                  valuesZ.sanitize (c, base, last - first + 1, user_data));
+  }
+
+  GlyphID       last;           /* Last GlyphID in this segment */
+  GlyphID       first;          /* First GlyphID in this segment */
+  NNOffsetTo<UnsizedArrayOf<T> >
+                valuesZ;        /* A 16-bit offset from the start of
+                                 * the table to the data. */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+template <typename T>
+struct LookupFormat4
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id) const
+  {
+    const LookupSegmentArray<T> *v = segments.bsearch (glyph_id);
+    return v ? v->get_value (glyph_id, this) : nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (segments.sanitize (c, this));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (segments.sanitize (c, this, base));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 4 */
+  VarSizedBinSearchArrayOf<LookupSegmentArray<T> >
+                segments;       /* The actual segments. These must already be sorted,
+                                 * according to the first word in each one (the last
+                                 * glyph in each segment). */
+  public:
+  DEFINE_SIZE_ARRAY (8, segments);
+};
+
+template <typename T>
+struct LookupSingle
+{
+  static constexpr unsigned TerminationWordCount = 1u;
+
+  int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && value.sanitize (c));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && value.sanitize (c, base));
+  }
+
+  GlyphID       glyph;          /* Last GlyphID */
+  T             value;          /* The lookup value (only one) */
+  public:
+  DEFINE_SIZE_STATIC (2 + T::static_size);
+};
+
+template <typename T>
+struct LookupFormat6
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id) const
+  {
+    const LookupSingle<T> *v = entries.bsearch (glyph_id);
+    return v ? &v->value : nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (entries.sanitize (c));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (entries.sanitize (c, base));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 6 */
+  VarSizedBinSearchArrayOf<LookupSingle<T> >
+                entries;        /* The actual entries, sorted by glyph index. */
+  public:
+  DEFINE_SIZE_ARRAY (8, entries);
+};
+
+template <typename T>
+struct LookupFormat8
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id) const
+  {
+    return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ?
+           &valueArrayZ[glyph_id - firstGlyph] : nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount, base));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 8 */
+  GlyphID       firstGlyph;     /* First glyph index included in the trimmed array. */
+  HBUINT16      glyphCount;     /* Total number of glyphs (equivalent to the last
+                                 * glyph minus the value of firstGlyph plus 1). */
+  UnsizedArrayOf<T>
+                valueArrayZ;    /* The lookup values (indexed by the glyph index
+                                 * minus the value of firstGlyph). */
+  public:
+  DEFINE_SIZE_ARRAY (6, valueArrayZ);
+};
+
+template <typename T>
+struct LookupFormat10
+{
+  friend struct Lookup<T>;
+
+  private:
+  const typename T::type get_value_or_null (hb_codepoint_t glyph_id) const
+  {
+    if (!(firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount))
+      return Null(T);
+
+    const HBUINT8 *p = &valueArrayZ[(glyph_id - firstGlyph) * valueSize];
+
+    unsigned int v = 0;
+    unsigned int count = valueSize;
+    for (unsigned int i = 0; i < count; i++)
+      v = (v << 8) | *p++;
+
+    return v;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  valueSize <= 4 &&
+                  valueArrayZ.sanitize (c, glyphCount * valueSize));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 8 */
+  HBUINT16      valueSize;      /* Byte size of each value. */
+  GlyphID       firstGlyph;     /* First glyph index included in the trimmed array. */
+  HBUINT16      glyphCount;     /* Total number of glyphs (equivalent to the last
+                                 * glyph minus the value of firstGlyph plus 1). */
+  UnsizedArrayOf<HBUINT8>
+                valueArrayZ;    /* The lookup values (indexed by the glyph index
+                                 * minus the value of firstGlyph). */
+  public:
+  DEFINE_SIZE_ARRAY (8, valueArrayZ);
+};
+
+template <typename T>
+struct Lookup
+{
+  const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+  {
+    switch (u.format) {
+    case 0: return u.format0.get_value (glyph_id, num_glyphs);
+    case 2: return u.format2.get_value (glyph_id);
+    case 4: return u.format4.get_value (glyph_id);
+    case 6: return u.format6.get_value (glyph_id);
+    case 8: return u.format8.get_value (glyph_id);
+    default:return nullptr;
+    }
+  }
+
+  const typename T::type get_value_or_null (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+  {
+    switch (u.format) {
+      /* Format 10 cannot return a pointer. */
+      case 10: return u.format10.get_value_or_null (glyph_id);
+      default:
+      const T *v = get_value (glyph_id, num_glyphs);
+      return v ? *v : Null(T);
+    }
+  }
+
+  typename T::type get_class (hb_codepoint_t glyph_id,
+                              unsigned int num_glyphs,
+                              unsigned int outOfRange) const
+  {
+    const T *v = get_value (glyph_id, num_glyphs);
+    return v ? *v : outOfRange;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format) {
+    case 0: return_trace (u.format0.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+    case 4: return_trace (u.format4.sanitize (c));
+    case 6: return_trace (u.format6.sanitize (c));
+    case 8: return_trace (u.format8.sanitize (c));
+    case 10: return_trace (u.format10.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format) {
+    case 0: return_trace (u.format0.sanitize (c, base));
+    case 2: return_trace (u.format2.sanitize (c, base));
+    case 4: return_trace (u.format4.sanitize (c, base));
+    case 6: return_trace (u.format6.sanitize (c, base));
+    case 8: return_trace (u.format8.sanitize (c, base));
+    case 10: return_trace (false); /* We don't support format10 here currently. */
+    default:return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16              format;         /* Format identifier */
+  LookupFormat0<T>      format0;
+  LookupFormat2<T>      format2;
+  LookupFormat4<T>      format4;
+  LookupFormat6<T>      format6;
+  LookupFormat8<T>      format8;
+  LookupFormat10<T>     format10;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+/* Lookup 0 has unbounded size (dependant on num_glyphs).  So we need to defined
+ * special NULL objects for Lookup<> objects, but since it's template our macros
+ * don't work.  So we have to hand-code them here.  UGLY. */
+} /* Close namespace. */
+/* Ugly hand-coded null objects for template Lookup<> :(. */
+extern HB_INTERNAL const unsigned char _hb_Null_AAT_Lookup[2];
+template <>
+/*static*/ inline const AAT::Lookup<OT::HBUINT16>& Null<AAT::Lookup<OT::HBUINT16> > ()
+{ return *reinterpret_cast<const AAT::Lookup<OT::HBUINT16> *> (_hb_Null_AAT_Lookup); }
+template <>
+/*static*/ inline const AAT::Lookup<OT::HBUINT32>& Null<AAT::Lookup<OT::HBUINT32> > ()
+{ return *reinterpret_cast<const AAT::Lookup<OT::HBUINT32> *> (_hb_Null_AAT_Lookup); }
+template <>
+/*static*/ inline const AAT::Lookup<OT::Offset<OT::HBUINT16, false> >& Null<AAT::Lookup<OT::Offset<OT::HBUINT16, false> > > ()
+{ return *reinterpret_cast<const AAT::Lookup<OT::Offset<OT::HBUINT16, false> > *> (_hb_Null_AAT_Lookup); }
+namespace AAT {
+
+enum { DELETED_GLYPH = 0xFFFF };
+
+/*
+ * (Extended) State Table
+ */
+
+template <typename T>
+struct Entry
+{
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+  {
+    TRACE_SANITIZE (this);
+    /* Note, we don't recurse-sanitize data because we don't access it.
+     * That said, in our DEFINE_SIZE_STATIC we access T::static_size,
+     * which ensures that data has a simple sanitize(). To be determined
+     * if I need to remove that as well.
+     *
+     * HOWEVER! Because we are a template, our DEFINE_SIZE_STATIC
+     * assertion wouldn't be checked, hence the line below. */
+    static_assert (T::static_size, "");
+
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT16      newState;       /* Byte offset from beginning of state table
+                                 * to the new state. Really?!?! Or just state
+                                 * number?  The latter in morx for sure. */
+  HBUINT16      flags;          /* Table specific. */
+  T             data;           /* Optional offsets to per-glyph tables. */
+  public:
+  DEFINE_SIZE_STATIC (4 + T::static_size);
+};
+
+template <>
+struct Entry<void>
+{
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count /*XXX Unused?*/) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT16      newState;       /* Byte offset from beginning of state table to the new state. */
+  HBUINT16      flags;          /* Table specific. */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+template <typename Types, typename Extra>
+struct StateTable
+{
+  typedef typename Types::HBUINT HBUINT;
+  typedef typename Types::HBUSHORT HBUSHORT;
+  typedef typename Types::ClassTypeNarrow ClassType;
+
+  enum State
+  {
+    STATE_START_OF_TEXT = 0,
+    STATE_START_OF_LINE = 1,
+  };
+  enum Class
+  {
+    CLASS_END_OF_TEXT = 0,
+    CLASS_OUT_OF_BOUNDS = 1,
+    CLASS_DELETED_GLYPH = 2,
+    CLASS_END_OF_LINE = 3,
+  };
+
+  int new_state (unsigned int newState) const
+  { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
+
+  unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+  {
+    if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
+    return (this+classTable).get_class (glyph_id, num_glyphs, 1);
+  }
+
+  const Entry<Extra> *get_entries () const
+  { return (this+entryTable).arrayZ; }
+
+  const Entry<Extra> &get_entry (int state, unsigned int klass) const
+  {
+    if (unlikely (klass >= nClasses))
+      klass = StateTable<Types, Entry<Extra> >::CLASS_OUT_OF_BOUNDS;
+
+    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
+    const Entry<Extra> *entries = (this+entryTable).arrayZ;
+
+    unsigned int entry = states[state * nClasses + klass];
+    DEBUG_MSG (APPLY, nullptr, "e%u", entry);
+
+    return entries[entry];
+  }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                 unsigned int *num_entries_out = nullptr) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!(c->check_struct (this) &&
+                    nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
+                    classTable.sanitize (c, this)))) return_trace (false);
+
+    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
+    const Entry<Extra> *entries = (this+entryTable).arrayZ;
+
+    unsigned int num_classes = nClasses;
+    if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
+      return_trace (false);
+    unsigned int row_stride = num_classes * states[0].static_size;
+
+    /* Apple 'kern' table has this peculiarity:
+     *
+     * "Because the stateTableOffset in the state table header is (strictly
+     * speaking) redundant, some 'kern' tables use it to record an initial
+     * state where that should not be StartOfText. To determine if this is
+     * done, calculate what the stateTableOffset should be. If it's different
+     * from the actual stateTableOffset, use it as the initial state."
+     *
+     * We implement this by calling the initial state zero, but allow *negative*
+     * states if the start state indeed was not the first state.  Since the code
+     * is shared, this will also apply to 'mort' table.  The 'kerx' / 'morx'
+     * tables are not affected since those address states by index, not offset.
+     */
+
+    int min_state = 0;
+    int max_state = 0;
+    unsigned int num_entries = 0;
+
+    int state_pos = 0;
+    int state_neg = 0;
+    unsigned int entry = 0;
+    while (min_state < state_neg || state_pos <= max_state)
+    {
+      if (min_state < state_neg)
+      {
+        /* Negative states. */
+        if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes)))
+          return_trace (false);
+        if (unlikely (!c->check_range (&states[min_state * num_classes],
+                                       -min_state,
+                                       row_stride)))
+          return_trace (false);
+        if ((c->max_ops -= state_neg - min_state) <= 0)
+          return_trace (false);
+        { /* Sweep new states. */
+          const HBUSHORT *stop = &states[min_state * num_classes];
+          if (unlikely (stop > states))
+            return_trace (false);
+          for (const HBUSHORT *p = states; stop < p; p--)
+            num_entries = MAX<unsigned int> (num_entries, *(p - 1) + 1);
+          state_neg = min_state;
+        }
+      }
+
+      if (state_pos <= max_state)
+      {
+        /* Positive states. */
+        if (unlikely (!c->check_range (states,
+                                       max_state + 1,
+                                       row_stride)))
+          return_trace (false);
+        if ((c->max_ops -= max_state - state_pos + 1) <= 0)
+          return_trace (false);
+        { /* Sweep new states. */
+          if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
+            return_trace (false);
+          const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
+          if (unlikely (stop < states))
+            return_trace (false);
+          for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
+            num_entries = MAX<unsigned int> (num_entries, *p + 1);
+          state_pos = max_state + 1;
+        }
+      }
+
+      if (unlikely (!c->check_array (entries, num_entries)))
+        return_trace (false);
+      if ((c->max_ops -= num_entries - entry) <= 0)
+        return_trace (false);
+      { /* Sweep new entries. */
+        const Entry<Extra> *stop = &entries[num_entries];
+        for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
+        {
+          int newState = new_state (p->newState);
+          min_state = MIN (min_state, newState);
+          max_state = MAX (max_state, newState);
+        }
+        entry = num_entries;
+      }
+    }
+
+    if (num_entries_out)
+      *num_entries_out = num_entries;
+
+    return_trace (true);
+  }
+
+  protected:
+  HBUINT        nClasses;       /* Number of classes, which is the number of indices
+                                 * in a single line in the state array. */
+  NNOffsetTo<ClassType, HBUINT>
+                classTable;     /* Offset to the class table. */
+  NNOffsetTo<UnsizedArrayOf<HBUSHORT>, HBUINT>
+                stateArrayTable;/* Offset to the state array. */
+  NNOffsetTo<UnsizedArrayOf<Entry<Extra> >, HBUINT>
+                entryTable;     /* Offset to the entry array. */
+
+  public:
+  DEFINE_SIZE_STATIC (4 * sizeof (HBUINT));
+};
+
+template <typename HBUCHAR>
+struct ClassTable
+{
+  unsigned int get_class (hb_codepoint_t glyph_id, unsigned int outOfRange) const
+  {
+    unsigned int i = glyph_id - firstGlyph;
+    return i >= classArray.len ? outOfRange : classArray.arrayZ[i];
+  }
+  unsigned int get_class (hb_codepoint_t glyph_id,
+                          unsigned int num_glyphs HB_UNUSED,
+                          unsigned int outOfRange) const
+  {
+    return get_class (glyph_id, outOfRange);
+  }
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && classArray.sanitize (c));
+  }
+  protected:
+  GlyphID               firstGlyph;     /* First glyph index included in the trimmed array. */
+  ArrayOf<HBUCHAR>      classArray;     /* The class codes (indexed by glyph index minus
+                                         * firstGlyph). */
+  public:
+  DEFINE_SIZE_ARRAY (4, classArray);
+};
+
+struct ObsoleteTypes
+{
+  static constexpr bool extended = false;
+  typedef HBUINT16 HBUINT;
+  typedef HBUINT8 HBUSHORT;
+  typedef ClassTable<HBUINT8> ClassTypeNarrow;
+  typedef ClassTable<HBUINT16> ClassTypeWide;
+
+  template <typename T>
+  static unsigned int offsetToIndex (unsigned int offset,
+                                     const void *base,
+                                     const T *array)
+  {
+    return (offset - ((const char *) array - (const char *) base)) / sizeof (T);
+  }
+  template <typename T>
+  static unsigned int byteOffsetToIndex (unsigned int offset,
+                                         const void *base,
+                                         const T *array)
+  {
+    return offsetToIndex (offset, base, array);
+  }
+  template <typename T>
+  static unsigned int wordOffsetToIndex (unsigned int offset,
+                                         const void *base,
+                                         const T *array)
+  {
+    return offsetToIndex (2 * offset, base, array);
+  }
+};
+struct ExtendedTypes
+{
+  static constexpr bool extended = true;
+  typedef HBUINT32 HBUINT;
+  typedef HBUINT16 HBUSHORT;
+  typedef Lookup<HBUINT16> ClassTypeNarrow;
+  typedef Lookup<HBUINT16> ClassTypeWide;
+
+  template <typename T>
+  static unsigned int offsetToIndex (unsigned int offset,
+                                     const void *base HB_UNUSED,
+                                     const T *array HB_UNUSED)
+  {
+    return offset;
+  }
+  template <typename T>
+  static unsigned int byteOffsetToIndex (unsigned int offset,
+                                         const void *base HB_UNUSED,
+                                         const T *array HB_UNUSED)
+  {
+    return offset / 2;
+  }
+  template <typename T>
+  static unsigned int wordOffsetToIndex (unsigned int offset,
+                                         const void *base HB_UNUSED,
+                                         const T *array HB_UNUSED)
+  {
+    return offset;
+  }
+};
+
+template <typename Types, typename EntryData>
+struct StateTableDriver
+{
+  StateTableDriver (const StateTable<Types, EntryData> &machine_,
+                    hb_buffer_t *buffer_,
+                    hb_face_t *face_) :
+              machine (machine_),
+              buffer (buffer_),
+              num_glyphs (face_->get_num_glyphs ()) {}
+
+  template <typename context_t>
+  void drive (context_t *c)
+  {
+    if (!c->in_place)
+      buffer->clear_output ();
+
+    int state = StateTable<Types, EntryData>::STATE_START_OF_TEXT;
+    for (buffer->idx = 0; buffer->successful;)
+    {
+      unsigned int klass = buffer->idx < buffer->len ?
+                           machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
+                           (unsigned) StateTable<Types, EntryData>::CLASS_END_OF_TEXT;
+      DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
+      const Entry<EntryData> &entry = machine.get_entry (state, klass);
+
+      /* Unsafe-to-break before this if not in state 0, as things might
+       * go differently if we start from state 0 here.
+       *
+       * Ugh.  The indexing here is ugly... */
+      if (state && buffer->backtrack_len () && buffer->idx < buffer->len)
+      {
+        /* If there's no action and we're just epsilon-transitioning to state 0,
+         * safe to break. */
+        if (c->is_actionable (this, entry) ||
+            !(entry.newState == StateTable<Types, EntryData>::STATE_START_OF_TEXT &&
+              entry.flags == context_t::DontAdvance))
+          buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
+      }
+
+      /* Unsafe-to-break if end-of-text would kick in here. */
+      if (buffer->idx + 2 <= buffer->len)
+      {
+        const Entry<EntryData> &end_entry = machine.get_entry (state, StateTable<Types, EntryData>::CLASS_END_OF_TEXT);
+        if (c->is_actionable (this, end_entry))
+          buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
+      }
+
+      c->transition (this, entry);
+
+      state = machine.new_state (entry.newState);
+      DEBUG_MSG (APPLY, nullptr, "s%d", state);
+
+      if (buffer->idx == buffer->len)
+        break;
+
+      if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
+        buffer->next_glyph ();
+    }
+
+    if (!c->in_place)
+    {
+      for (; buffer->successful && buffer->idx < buffer->len;)
+        buffer->next_glyph ();
+      buffer->swap_buffers ();
+    }
+  }
+
+  public:
+  const StateTable<Types, EntryData> &machine;
+  hb_buffer_t *buffer;
+  unsigned int num_glyphs;
+};
+
+
+struct ankr;
+
+struct hb_aat_apply_context_t :
+       hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
+{
+  const char *get_name () { return "APPLY"; }
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.apply (this); }
+  static return_t default_return_value () { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+
+  const hb_ot_shape_plan_t *plan;
+  hb_font_t *font;
+  hb_face_t *face;
+  hb_buffer_t *buffer;
+  hb_sanitize_context_t sanitizer;
+  const ankr *ankr_table;
+
+  /* Unused. For debug tracing only. */
+  unsigned int lookup_index;
+  unsigned int debug_depth;
+
+  HB_INTERNAL hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
+                                      hb_font_t *font_,
+                                      hb_buffer_t *buffer_,
+                                      hb_blob_t *blob = const_cast<hb_blob_t *> (&Null(hb_blob_t)));
+
+  HB_INTERNAL ~hb_aat_apply_context_t ();
+
+  HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
+
+  void set_lookup_index (unsigned int i) { lookup_index = i; }
+};
+
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_COMMON_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-feat-table.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,217 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_AAT_LAYOUT_FEAT_TABLE_HH
+#define HB_AAT_LAYOUT_FEAT_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+
+/*
+ * feat -- Feature Name
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6feat.html
+ */
+#define HB_AAT_TAG_feat HB_TAG('f','e','a','t')
+
+
+namespace AAT {
+
+
+struct SettingName
+{
+  friend struct FeatureName;
+
+  int cmp (hb_aat_layout_feature_selector_t key) const
+  { return (int) key - (int) setting; }
+
+  hb_aat_layout_feature_selector_t get_selector () const
+  { return (hb_aat_layout_feature_selector_t) (unsigned) setting; }
+
+  void get_info (hb_aat_layout_feature_selector_info_t *s,
+                        hb_aat_layout_feature_selector_t default_selector) const
+  {
+    s->name_id = nameIndex;
+
+    s->enable = (hb_aat_layout_feature_selector_t) (unsigned int) setting;
+    s->disable = default_selector == HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID ?
+                 (hb_aat_layout_feature_selector_t) (s->enable + 1) :
+                 default_selector;
+
+    s->reserved = 0;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16      setting;        /* The setting. */
+  NameID        nameIndex;      /* The name table index for the setting's name. */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+DECLARE_NULL_NAMESPACE_BYTES (AAT, SettingName);
+
+struct feat;
+
+struct FeatureName
+{
+  int cmp (hb_aat_layout_feature_type_t key) const
+  { return (int) key - (int) feature; }
+
+  enum {
+    Exclusive   = 0x8000,       /* If set, the feature settings are mutually exclusive. */
+    NotDefault  = 0x4000,       /* If clear, then the setting with an index of 0 in
+                                 * the setting name array for this feature should
+                                 * be taken as the default for the feature
+                                 * (if one is required). If set, then bits 0-15 of this
+                                 * featureFlags field contain the index of the setting
+                                 * which is to be taken as the default. */
+    IndexMask   = 0x00FF        /* If bits 30 and 31 are set, then these sixteen bits
+                                 * indicate the index of the setting in the setting name
+                                 * array for this feature which should be taken
+                                 * as the default. */
+  };
+
+  unsigned int get_selector_infos (unsigned int                           start_offset,
+                                   unsigned int                          *selectors_count, /* IN/OUT.  May be NULL. */
+                                   hb_aat_layout_feature_selector_info_t *selectors,       /* OUT.     May be NULL. */
+                                   unsigned int                          *pdefault_index,  /* OUT.     May be NULL. */
+                                   const void *base) const
+  {
+    hb_array_t< const SettingName> settings_table = (base+settingTableZ).as_array (nSettings);
+
+    static_assert (Index::NOT_FOUND_INDEX == HB_AAT_LAYOUT_NO_SELECTOR_INDEX, "");
+
+    hb_aat_layout_feature_selector_t default_selector = HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID;
+    unsigned int default_index = Index::NOT_FOUND_INDEX;
+    if (featureFlags & Exclusive)
+    {
+      default_index = (featureFlags & NotDefault) ? featureFlags & IndexMask : 0;
+      default_selector = settings_table[default_index].get_selector ();
+    }
+    if (pdefault_index)
+      *pdefault_index = default_index;
+
+    if (selectors_count)
+    {
+      hb_array_t<const SettingName> arr = settings_table.sub_array (start_offset, selectors_count);
+      for (unsigned int i = 0; i < arr.length; i++)
+        settings_table[start_offset + i].get_info (&selectors[i], default_selector);
+    }
+    return settings_table.length;
+  }
+
+  hb_aat_layout_feature_type_t get_feature_type () const
+  { return (hb_aat_layout_feature_type_t) (unsigned int) feature; }
+
+  hb_ot_name_id_t get_feature_name_id () const { return nameIndex; }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          (base+settingTableZ).sanitize (c, nSettings)));
+  }
+
+  protected:
+  HBUINT16      feature;        /* Feature type. */
+  HBUINT16      nSettings;      /* The number of records in the setting name array. */
+  LOffsetTo<UnsizedArrayOf<SettingName>, false>
+                settingTableZ;  /* Offset in bytes from the beginning of this table to
+                                 * this feature's setting name array. The actual type of
+                                 * record this offset refers to will depend on the
+                                 * exclusivity value, as described below. */
+  HBUINT16      featureFlags;   /* Single-bit flags associated with the feature type. */
+  HBINT16       nameIndex;      /* The name table index for the feature's name.
+                                 * This index has values greater than 255 and
+                                 * less than 32768. */
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+struct feat
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_feat;
+
+  bool has_data () const { return version.to_int (); }
+
+  unsigned int get_feature_types (unsigned int                  start_offset,
+                                  unsigned int                 *count,
+                                  hb_aat_layout_feature_type_t *features) const
+  {
+    unsigned int feature_count = featureNameCount;
+    if (count && *count)
+    {
+      unsigned int len = MIN (feature_count - start_offset, *count);
+      for (unsigned int i = 0; i < len; i++)
+        features[i] = namesZ[i + start_offset].get_feature_type ();
+      *count = len;
+    }
+    return featureNameCount;
+  }
+
+  const FeatureName& get_feature (hb_aat_layout_feature_type_t feature_type) const
+  {
+    return namesZ.bsearch (featureNameCount, feature_type);
+  }
+
+  hb_ot_name_id_t get_feature_name_id (hb_aat_layout_feature_type_t feature) const
+  { return get_feature (feature).get_feature_name_id (); }
+
+  unsigned int get_selector_infos (hb_aat_layout_feature_type_t           feature_type,
+                                   unsigned int                           start_offset,
+                                   unsigned int                          *selectors_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. */) const
+  {
+    return get_feature (feature_type).get_selector_infos (start_offset, selectors_count, selectors,
+                                                          default_index, this);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          version.major == 1 &&
+                          namesZ.sanitize (c, featureNameCount, this)));
+  }
+
+  protected:
+  FixedVersion<>version;        /* Version number of the feature name table
+                                 * (0x00010000 for the current version). */
+  HBUINT16      featureNameCount;
+                                /* The number of entries in the feature name array. */
+  HBUINT16      reserved1;      /* Reserved (set to zero). */
+  HBUINT32      reserved2;      /* Reserved (set to zero). */
+  SortedUnsizedArrayOf<FeatureName>
+                namesZ;         /* The feature name array. */
+  public:
+  DEFINE_SIZE_STATIC (24);
+};
+
+} /* namespace AAT */
+
+#endif /* HB_AAT_LAYOUT_FEAT_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-just-table.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,417 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_AAT_LAYOUT_JUST_TABLE_HH
+#define HB_AAT_LAYOUT_JUST_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+#include "hb-ot-layout.hh"
+#include "hb-open-type.hh"
+
+#include "hb-aat-layout-morx-table.hh"
+
+/*
+ * just -- Justification
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6just.html
+ */
+#define HB_AAT_TAG_just HB_TAG('j','u','s','t')
+
+
+namespace AAT {
+
+using namespace OT;
+
+
+struct ActionSubrecordHeader
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  HBUINT16      actionClass;    /* The JustClass value associated with this
+                                 * ActionSubrecord. */
+  HBUINT16      actionType;     /* The type of postcompensation action. */
+  HBUINT16      actionLength;   /* Length of this ActionSubrecord record, which
+                                 * must be a multiple of 4. */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct DecompositionAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  ActionSubrecordHeader
+                header;
+  Fixed         lowerLimit;     /* If the distance factor is less than this value,
+                                 * then the ligature is decomposed. */
+  Fixed         upperLimit;     /* If the distance factor is greater than this value,
+                                 * then the ligature is decomposed. */
+  HBUINT16      order;          /* Numerical order in which this ligature will
+                                 * be decomposed; you may want infrequent ligatures
+                                 * to decompose before more frequent ones. The ligatures
+                                 * on the line of text will decompose in increasing
+                                 * value of this field. */
+  ArrayOf<HBUINT16>
+                decomposedglyphs;
+                                /* Number of 16-bit glyph indexes that follow;
+                                 * the ligature will be decomposed into these glyphs.
+                                 *
+                                 * Array of decomposed glyphs. */
+  public:
+  DEFINE_SIZE_ARRAY (18, decomposedglyphs);
+};
+
+struct UnconditionalAddGlyphAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  ActionSubrecordHeader
+                header;
+  GlyphID       addGlyph;       /* Glyph that should be added if the distance factor
+                                 * is growing. */
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct ConditionalAddGlyphAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  ActionSubrecordHeader
+                header;
+  Fixed         substThreshold; /* Distance growth factor (in ems) at which
+                                 * this glyph is replaced and the growth factor
+                                 * recalculated. */
+  GlyphID       addGlyph;       /* Glyph to be added as kashida. If this value is
+                                 * 0xFFFF, no extra glyph will be added. Note that
+                                 * generally when a glyph is added, justification
+                                 * will need to be redone. */
+  GlyphID       substGlyph;     /* Glyph to be substituted for this glyph if the
+                                 * growth factor equals or exceeds the value of
+                                 * substThreshold. */
+  public:
+  DEFINE_SIZE_STATIC (14);
+};
+
+struct DuctileGlyphAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  ActionSubrecordHeader
+                header;
+  HBUINT32      variationAxis;  /* The 4-byte tag identifying the ductile axis.
+                                 * This would normally be 0x64756374 ('duct'),
+                                 * but you may use any axis the font contains. */
+  Fixed         minimumLimit;   /* The lowest value for the ductility axis tha
+                                 * still yields an acceptable appearance. Normally
+                                 * this will be 1.0. */
+  Fixed         noStretchValue; /* This is the default value that corresponds to
+                                 * no change in appearance. Normally, this will
+                                 * be 1.0. */
+  Fixed         maximumLimit;   /* The highest value for the ductility axis that
+                                 * still yields an acceptable appearance. */
+  public:
+  DEFINE_SIZE_STATIC (22);
+};
+
+struct RepeatedAddGlyphAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  ActionSubrecordHeader
+                header;
+  HBUINT16      flags;          /* Currently unused; set to 0. */
+  GlyphID       glyph;          /* Glyph that should be added if the distance factor
+                                 * is growing. */
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+struct ActionSubrecord
+{
+  unsigned int get_length () const { return u.header.actionLength; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+
+    switch (u.header.actionType)
+    {
+    case 0:  return_trace (u.decompositionAction.sanitize (c));
+    case 1:  return_trace (u.unconditionalAddGlyphAction.sanitize (c));
+    case 2:  return_trace (u.conditionalAddGlyphAction.sanitize (c));
+    // case 3: return_trace (u.stretchGlyphAction.sanitize (c));
+    case 4:  return_trace (u.decompositionAction.sanitize (c));
+    case 5:  return_trace (u.decompositionAction.sanitize (c));
+    default: return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  ActionSubrecordHeader         header;
+  DecompositionAction           decompositionAction;
+  UnconditionalAddGlyphAction   unconditionalAddGlyphAction;
+  ConditionalAddGlyphAction     conditionalAddGlyphAction;
+  /* StretchGlyphAction stretchGlyphAction; -- Not supported by CoreText */
+  DuctileGlyphAction            ductileGlyphAction;
+  RepeatedAddGlyphAction        repeatedAddGlyphAction;
+  } u;                          /* Data. The format of this data depends on
+                                 * the value of the actionType field. */
+  public:
+  DEFINE_SIZE_UNION (6, header);
+};
+
+struct PostcompensationActionChain
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+
+    unsigned int offset = min_size;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const ActionSubrecord& subrecord = StructAtOffset<ActionSubrecord> (this, offset);
+      if (unlikely (!subrecord.sanitize (c))) return_trace (false);
+      offset += subrecord.get_length ();
+    }
+
+    return_trace (true);
+  }
+
+  protected:
+  HBUINT32      count;
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct JustWidthDeltaEntry
+{
+  enum Flags
+  {
+    Reserved1           =0xE000,/* Reserved. You should set these bits to zero. */
+    UnlimiteGap         =0x1000,/* The glyph can take unlimited gap. When this
+                                 * glyph participates in the justification process,
+                                 * it and any other glyphs on the line having this
+                                 * bit set absorb all the remaining gap. */
+    Reserved2           =0x0FF0,/* Reserved. You should set these bits to zero. */
+    Priority            =0x000F /* The justification priority of the glyph. */
+  };
+
+  enum Priority
+  {
+    Kashida             = 0,    /* Kashida priority. This is the highest priority
+                                 * during justification. */
+    Whitespace          = 1,    /* Whitespace priority. Any whitespace glyphs (as
+                                 * identified in the glyph properties table) will
+                                 * get this priority. */
+    InterCharacter      = 2,    /* Inter-character priority. Give this to any
+                                 * remaining glyphs. */
+    NullPriority        = 3     /* Null priority. You should set this priority for
+                                 * glyphs that only participate in justification
+                                 * after the above priorities. Normally all glyphs
+                                 * have one of the previous three values. If you
+                                 * don't want a glyph to participate in justification,
+                                 * and you don't want to set its factors to zero,
+                                 * you may instead assign it to the null priority. */
+  };
+
+  protected:
+  Fixed         beforeGrowLimit;/* The ratio by which the advance width of the
+                                 * glyph is permitted to grow on the left or top side. */
+  Fixed         beforeShrinkLimit;
+                                /* The ratio by which the advance width of the
+                                 * glyph is permitted to shrink on the left or top side. */
+  Fixed         afterGrowLimit; /* The ratio by which the advance width of the glyph
+                                 * is permitted to shrink on the left or top side. */
+  Fixed         afterShrinkLimit;
+                                /* The ratio by which the advance width of the glyph
+                                 * is at most permitted to shrink on the right or
+                                 * bottom side. */
+  HBUINT16      growFlags;      /* Flags controlling the grow case. */
+  HBUINT16      shrinkFlags;    /* Flags controlling the shrink case. */
+
+  public:
+  DEFINE_SIZE_STATIC (20);
+};
+
+struct WidthDeltaPair
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT32      justClass;      /* The justification category associated
+                                 * with the wdRecord field. Only 7 bits of
+                                 * this field are used. (The other bits are
+                                 * used as padding to guarantee longword
+                                 * alignment of the following record). */
+  JustWidthDeltaEntry
+                wdRecord;       /* The actual width delta record. */
+
+  public:
+  DEFINE_SIZE_STATIC (24);
+};
+
+typedef OT::LArrayOf<WidthDeltaPair> WidthDeltaCluster;
+
+struct JustificationCategory
+{
+  typedef void EntryData;
+
+  enum Flags
+  {
+    SetMark             =0x8000,/* If set, make the current glyph the marked
+                                 * glyph. */
+    DontAdvance         =0x4000,/* If set, don't advance to the next glyph before
+                                 * going to the new state. */
+    MarkCategory        =0x3F80,/* The justification category for the marked
+                                 * glyph if nonzero. */
+    CurrentCategory     =0x007F /* The justification category for the current
+                                 * glyph if nonzero. */
+  };
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          morphHeader.sanitize (c) &&
+                          stHeader.sanitize (c)));
+  }
+
+  protected:
+  ChainSubtable<ObsoleteTypes>
+                morphHeader;    /* Metamorphosis-style subtable header. */
+  StateTable<ObsoleteTypes, EntryData>
+                stHeader;       /* The justification insertion state table header */
+  public:
+  DEFINE_SIZE_STATIC (30);
+};
+
+struct JustificationHeader
+{
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          justClassTable.sanitize (c, base, base) &&
+                          wdcTable.sanitize (c, base) &&
+                          pcTable.sanitize (c, base) &&
+                          lookupTable.sanitize (c, base)));
+  }
+
+  protected:
+  OffsetTo<JustificationCategory>
+                justClassTable; /* Offset to the justification category state table. */
+  OffsetTo<WidthDeltaCluster>
+                wdcTable;       /* Offset from start of justification table to start
+                                 * of the subtable containing the width delta factors
+                                 * for the glyphs in your font.
+                                 *
+                                 * The width delta clusters table. */
+  OffsetTo<PostcompensationActionChain>
+                pcTable;        /* Offset from start of justification table to start
+                                 * of postcompensation subtable (set to zero if none).
+                                 *
+                                 * The postcompensation subtable, if present in the font. */
+  Lookup<OffsetTo<WidthDeltaCluster> >
+                lookupTable;    /* Lookup table associating glyphs with width delta
+                                 * clusters. See the description of Width Delta Clusters
+                                 * table for details on how to interpret the lookup values. */
+
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+struct just
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_just;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    return_trace (likely (c->check_struct (this) &&
+                          version.major == 1 &&
+                          horizData.sanitize (c, this, this) &&
+                          vertData.sanitize (c, this, this)));
+  }
+
+  protected:
+  FixedVersion<>version;        /* Version of the justification table
+                                 * (0x00010000u for version 1.0). */
+  HBUINT16      format;         /* Format of the justification table (set to 0). */
+  OffsetTo<JustificationHeader>
+                horizData;      /* Byte offset from the start of the justification table
+                                 * to the header for tables that contain justification
+                                 * information for horizontal text.
+                                 * If you are not including this information,
+                                 * store 0. */
+  OffsetTo<JustificationHeader>
+                vertData;       /* ditto, vertical */
+
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_JUST_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-kerx-table.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,1001 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_LAYOUT_KERX_TABLE_HH
+#define HB_AAT_LAYOUT_KERX_TABLE_HH
+
+#include "hb-kern.hh"
+#include "hb-aat-layout-ankr-table.hh"
+
+/*
+ * kerx -- Extended Kerning
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kerx.html
+ */
+#define HB_AAT_TAG_kerx HB_TAG('k','e','r','x')
+
+
+namespace AAT {
+
+using namespace OT;
+
+
+static inline int
+kerxTupleKern (int value,
+               unsigned int tupleCount,
+               const void *base,
+               hb_aat_apply_context_t *c)
+{
+  if (likely (!tupleCount || !c)) return value;
+
+  unsigned int offset = value;
+  const FWORD *pv = &StructAtOffset<FWORD> (base, offset);
+  if (unlikely (!c->sanitizer.check_array (pv, tupleCount))) return 0;
+  return *pv;
+}
+
+
+struct hb_glyph_pair_t
+{
+  hb_codepoint_t left;
+  hb_codepoint_t right;
+};
+
+struct KernPair
+{
+  int get_kerning () const { return value; }
+
+  int cmp (const hb_glyph_pair_t &o) const
+  {
+    int ret = left.cmp (o.left);
+    if (ret) return ret;
+    return right.cmp (o.right);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  GlyphID       left;
+  GlyphID       right;
+  FWORD         value;
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+template <typename KernSubTableHeader>
+struct KerxSubTableFormat0
+{
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right,
+                   hb_aat_apply_context_t *c = nullptr) const
+  {
+    hb_glyph_pair_t pair = {left, right};
+    int v = pairs.bsearch (pair).get_kerning ();
+    return kerxTupleKern (v, header.tuple_count (), this, c);
+  }
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    if (!c->plan->requested_kerning)
+      return false;
+
+    if (header.coverage & header.Backwards)
+      return false;
+
+    accelerator_t accel (*this, c);
+    hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
+    machine.kern (c->font, c->buffer, c->plan->kern_mask);
+
+    return_trace (true);
+  }
+
+  struct accelerator_t
+  {
+    const KerxSubTableFormat0 &table;
+    hb_aat_apply_context_t *c;
+
+    accelerator_t (const KerxSubTableFormat0 &table_,
+                   hb_aat_apply_context_t *c_) :
+                     table (table_), c (c_) {}
+
+    int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+    { return table.get_kerning (left, right, c); }
+  };
+
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (pairs.sanitize (c)));
+  }
+
+  protected:
+  KernSubTableHeader    header;
+  BinSearchArrayOf<KernPair, typename KernSubTableHeader::Types::HBUINT>
+                        pairs;  /* Sorted kern records. */
+  public:
+  DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 16, pairs);
+};
+
+
+template <bool extended>
+struct Format1Entry;
+
+template <>
+struct Format1Entry<true>
+{
+  enum Flags
+  {
+    Push                = 0x8000,       /* If set, push this glyph on the kerning stack. */
+    DontAdvance         = 0x4000,       /* If set, don't advance to the next glyph
+                                         * before going to the new state. */
+    Reset               = 0x2000,       /* If set, reset the kerning data (clear the stack) */
+    Reserved            = 0x1FFF,       /* Not used; set to 0. */
+  };
+
+  struct EntryData
+  {
+    HBUINT16    kernActionIndex;/* Index into the kerning value array. If
+                                 * this index is 0xFFFF, then no kerning
+                                 * is to be performed. */
+    public:
+    DEFINE_SIZE_STATIC (2);
+  };
+
+  static bool performAction (const Entry<EntryData> &entry)
+  { return entry.data.kernActionIndex != 0xFFFF; }
+
+  static unsigned int kernActionIndex (const Entry<EntryData> &entry)
+  { return entry.data.kernActionIndex; }
+};
+template <>
+struct Format1Entry<false>
+{
+  enum Flags
+  {
+    Push                = 0x8000,       /* If set, push this glyph on the kerning stack. */
+    DontAdvance         = 0x4000,       /* If set, don't advance to the next glyph
+                                         * before going to the new state. */
+    Offset              = 0x3FFF,       /* Byte offset from beginning of subtable to the
+                                         * value table for the glyphs on the kerning stack. */
+
+    Reset               = 0x0000,       /* Not supported? */
+  };
+
+  typedef void EntryData;
+
+  static bool performAction (const Entry<EntryData> &entry)
+  { return entry.flags & Offset; }
+
+  static unsigned int kernActionIndex (const Entry<EntryData> &entry)
+  { return entry.flags & Offset; }
+};
+
+template <typename KernSubTableHeader>
+struct KerxSubTableFormat1
+{
+  typedef typename KernSubTableHeader::Types Types;
+  typedef typename Types::HBUINT HBUINT;
+
+  typedef Format1Entry<Types::extended> Format1EntryT;
+  typedef typename Format1EntryT::EntryData EntryData;
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = true;
+    enum
+    {
+      DontAdvance       = Format1EntryT::DontAdvance,
+    };
+
+    driver_context_t (const KerxSubTableFormat1 *table_,
+                      hb_aat_apply_context_t *c_) :
+        c (c_),
+        table (table_),
+        /* Apparently the offset kernAction is from the beginning of the state-machine,
+         * similar to offsets in morx table, NOT from beginning of this table, like
+         * other subtables in kerx.  Discovered via testing. */
+        kernAction (&table->machine + table->kernAction),
+        depth (0),
+        crossStream (table->header.coverage & table->header.CrossStream) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                        const Entry<EntryData> &entry)
+    {
+      return Format1EntryT::performAction (entry);
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                     const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+      unsigned int flags = entry.flags;
+
+      if (flags & Format1EntryT::Reset)
+        depth = 0;
+
+      if (flags & Format1EntryT::Push)
+      {
+        if (likely (depth < ARRAY_LENGTH (stack)))
+          stack[depth++] = buffer->idx;
+        else
+          depth = 0; /* Probably not what CoreText does, but better? */
+      }
+
+      if (Format1EntryT::performAction (entry) && depth)
+      {
+        unsigned int tuple_count = MAX (1u, table->header.tuple_count ());
+
+        unsigned int kern_idx = Format1EntryT::kernActionIndex (entry);
+        kern_idx = Types::byteOffsetToIndex (kern_idx, &table->machine, kernAction.arrayZ);
+        const FWORD *actions = &kernAction[kern_idx];
+        if (!c->sanitizer.check_array (actions, depth, tuple_count))
+        {
+          depth = 0;
+          return;
+        }
+
+        hb_mask_t kern_mask = c->plan->kern_mask;
+
+        /* From Apple 'kern' spec:
+         * "Each pops one glyph from the kerning stack and applies the kerning value to it.
+         * The end of the list is marked by an odd value... */
+        bool last = false;
+        while (!last && depth)
+        {
+          unsigned int idx = stack[--depth];
+          int v = *actions;
+          actions += tuple_count;
+          if (idx >= buffer->len) continue;
+
+          /* "The end of the list is marked by an odd value..." */
+          last = v & 1;
+          v &= ~1;
+
+          hb_glyph_position_t &o = buffer->pos[idx];
+
+          /* Testing shows that CoreText only applies kern (cross-stream or not)
+           * if none has been applied by previous subtables.  That is, it does
+           * NOT seem to accumulate as otherwise implied by specs. */
+
+          /* The following flag is undocumented in the spec, but described
+           * in the 'kern' table example. */
+          if (v == -0x8000)
+          {
+            o.attach_type() = ATTACH_TYPE_NONE;
+            o.attach_chain() = 0;
+            o.x_offset = o.y_offset = 0;
+          }
+          else if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
+          {
+            if (crossStream)
+            {
+              if (buffer->pos[idx].attach_type() && !buffer->pos[idx].y_offset)
+              {
+                o.y_offset = c->font->em_scale_y (v);
+                buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+              }
+            }
+            else if (buffer->info[idx].mask & kern_mask)
+            {
+              if (!buffer->pos[idx].x_offset)
+              {
+                buffer->pos[idx].x_advance += c->font->em_scale_x (v);
+                buffer->pos[idx].x_offset += c->font->em_scale_x (v);
+              }
+            }
+          }
+          else
+          {
+            if (crossStream)
+            {
+              /* CoreText doesn't do crossStream kerning in vertical.  We do. */
+              if (buffer->pos[idx].attach_type() && !buffer->pos[idx].x_offset)
+              {
+                o.x_offset = c->font->em_scale_x (v);
+                buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+              }
+            }
+            else if (buffer->info[idx].mask & kern_mask)
+            {
+              if (!buffer->pos[idx].y_offset)
+              {
+                buffer->pos[idx].y_advance += c->font->em_scale_y (v);
+                buffer->pos[idx].y_offset += c->font->em_scale_y (v);
+              }
+            }
+          }
+        }
+      }
+    }
+
+    private:
+    hb_aat_apply_context_t *c;
+    const KerxSubTableFormat1 *table;
+    const UnsizedArrayOf<FWORD> &kernAction;
+    unsigned int stack[8];
+    unsigned int depth;
+    bool crossStream;
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    if (!c->plan->requested_kerning &&
+        !(header.coverage & header.CrossStream))
+      return false;
+
+    driver_context_t dc (this, c);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
+    driver.drive (&dc);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    /* The rest of array sanitizations are done at run-time. */
+    return_trace (likely (c->check_struct (this) &&
+                          machine.sanitize (c)));
+  }
+
+  protected:
+  KernSubTableHeader                            header;
+  StateTable<Types, EntryData>                  machine;
+  NNOffsetTo<UnsizedArrayOf<FWORD>, HBUINT>     kernAction;
+  public:
+  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 5 * sizeof (HBUINT));
+};
+
+template <typename KernSubTableHeader>
+struct KerxSubTableFormat2
+{
+  typedef typename KernSubTableHeader::Types Types;
+  typedef typename Types::HBUINT HBUINT;
+
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right,
+                   hb_aat_apply_context_t *c) const
+  {
+    unsigned int num_glyphs = c->sanitizer.get_num_glyphs ();
+    unsigned int l = (this+leftClassTable).get_class (left, num_glyphs, 0);
+    unsigned int r = (this+rightClassTable).get_class (right, num_glyphs, 0);
+
+    const UnsizedArrayOf<FWORD> &arrayZ = this+array;
+    unsigned int kern_idx = l + r;
+    kern_idx = Types::offsetToIndex (kern_idx, this, &arrayZ);
+    const FWORD *v = &arrayZ[kern_idx];
+    if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
+
+    return kerxTupleKern (*v, header.tuple_count (), this, c);
+  }
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    if (!c->plan->requested_kerning)
+      return false;
+
+    if (header.coverage & header.Backwards)
+      return false;
+
+    accelerator_t accel (*this, c);
+    hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
+    machine.kern (c->font, c->buffer, c->plan->kern_mask);
+
+    return_trace (true);
+  }
+
+  struct accelerator_t
+  {
+    const KerxSubTableFormat2 &table;
+    hb_aat_apply_context_t *c;
+
+    accelerator_t (const KerxSubTableFormat2 &table_,
+                   hb_aat_apply_context_t *c_) :
+                     table (table_), c (c_) {}
+
+    int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+    { return table.get_kerning (left, right, c); }
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          leftClassTable.sanitize (c, this) &&
+                          rightClassTable.sanitize (c, this) &&
+                          c->check_range (this, array)));
+  }
+
+  protected:
+  KernSubTableHeader    header;
+  HBUINT                rowWidth;       /* The width, in bytes, of a row in the table. */
+  NNOffsetTo<typename Types::ClassTypeWide, HBUINT>
+                        leftClassTable; /* Offset from beginning of this subtable to
+                                         * left-hand class table. */
+  NNOffsetTo<typename Types::ClassTypeWide, HBUINT>
+                        rightClassTable;/* Offset from beginning of this subtable to
+                                         * right-hand class table. */
+  NNOffsetTo<UnsizedArrayOf<FWORD>, HBUINT>
+                         array;         /* Offset from beginning of this subtable to
+                                         * the start of the kerning array. */
+  public:
+  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 4 * sizeof (HBUINT));
+};
+
+template <typename KernSubTableHeader>
+struct KerxSubTableFormat4
+{
+  typedef ExtendedTypes Types;
+
+  struct EntryData
+  {
+    HBUINT16    ankrActionIndex;/* Either 0xFFFF (for no action) or the index of
+                                 * the action to perform. */
+    public:
+    DEFINE_SIZE_STATIC (2);
+  };
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = true;
+    enum Flags
+    {
+      Mark              = 0x8000,       /* If set, remember this glyph as the marked glyph. */
+      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph before
+                                         * going to the new state. */
+      Reserved          = 0x3FFF,       /* Not used; set to 0. */
+    };
+
+    enum SubTableFlags
+    {
+      ActionType        = 0xC0000000,   /* A two-bit field containing the action type. */
+      Unused            = 0x3F000000,   /* Unused - must be zero. */
+      Offset            = 0x00FFFFFF,   /* Masks the offset in bytes from the beginning
+                                         * of the subtable to the beginning of the control
+                                         * point table. */
+    };
+
+    driver_context_t (const KerxSubTableFormat4 *table,
+                             hb_aat_apply_context_t *c_) :
+        c (c_),
+        action_type ((table->flags & ActionType) >> 30),
+        ankrData ((HBUINT16 *) ((const char *) &table->machine + (table->flags & Offset))),
+        mark_set (false),
+        mark (0) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                        const Entry<EntryData> &entry)
+    {
+      return entry.data.ankrActionIndex != 0xFFFF;
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                     const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+
+      if (mark_set && entry.data.ankrActionIndex != 0xFFFF && buffer->idx < buffer->len)
+      {
+        hb_glyph_position_t &o = buffer->cur_pos();
+        switch (action_type)
+        {
+          case 0: /* Control Point Actions.*/
+          {
+            /* indexed into glyph outline. */
+            const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex];
+            if (!c->sanitizer.check_array (data, 2)) return;
+            HB_UNUSED unsigned int markControlPoint = *data++;
+            HB_UNUSED unsigned int currControlPoint = *data++;
+            hb_position_t markX = 0;
+            hb_position_t markY = 0;
+            hb_position_t currX = 0;
+            hb_position_t currY = 0;
+            if (!c->font->get_glyph_contour_point_for_origin (c->buffer->info[mark].codepoint,
+                                                              markControlPoint,
+                                                              HB_DIRECTION_LTR /*XXX*/,
+                                                              &markX, &markY) ||
+                !c->font->get_glyph_contour_point_for_origin (c->buffer->cur ().codepoint,
+                                                              currControlPoint,
+                                                              HB_DIRECTION_LTR /*XXX*/,
+                                                              &currX, &currY))
+              return;
+
+            o.x_offset = markX - currX;
+            o.y_offset = markY - currY;
+          }
+          break;
+
+          case 1: /* Anchor Point Actions. */
+          {
+           /* Indexed into 'ankr' table. */
+            const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex];
+            if (!c->sanitizer.check_array (data, 2)) return;
+            unsigned int markAnchorPoint = *data++;
+            unsigned int currAnchorPoint = *data++;
+            const Anchor &markAnchor = c->ankr_table->get_anchor (c->buffer->info[mark].codepoint,
+                                                                  markAnchorPoint,
+                                                                  c->sanitizer.get_num_glyphs ());
+            const Anchor &currAnchor = c->ankr_table->get_anchor (c->buffer->cur ().codepoint,
+                                                                  currAnchorPoint,
+                                                                  c->sanitizer.get_num_glyphs ());
+
+            o.x_offset = c->font->em_scale_x (markAnchor.xCoordinate) - c->font->em_scale_x (currAnchor.xCoordinate);
+            o.y_offset = c->font->em_scale_y (markAnchor.yCoordinate) - c->font->em_scale_y (currAnchor.yCoordinate);
+          }
+          break;
+
+          case 2: /* Control Point Coordinate Actions. */
+          {
+            const FWORD *data = (const FWORD *) &ankrData[entry.data.ankrActionIndex];
+            if (!c->sanitizer.check_array (data, 4)) return;
+            int markX = *data++;
+            int markY = *data++;
+            int currX = *data++;
+            int currY = *data++;
+
+            o.x_offset = c->font->em_scale_x (markX) - c->font->em_scale_x (currX);
+            o.y_offset = c->font->em_scale_y (markY) - c->font->em_scale_y (currY);
+          }
+          break;
+        }
+        o.attach_type() = ATTACH_TYPE_MARK;
+        o.attach_chain() = (int) mark - (int) buffer->idx;
+        buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+      }
+
+      if (entry.flags & Mark)
+      {
+        mark_set = true;
+        mark = buffer->idx;
+      }
+    }
+
+    private:
+    hb_aat_apply_context_t *c;
+    unsigned int action_type;
+    const HBUINT16 *ankrData;
+    bool mark_set;
+    unsigned int mark;
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    driver_context_t dc (this, c);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
+    driver.drive (&dc);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    /* The rest of array sanitizations are done at run-time. */
+    return_trace (likely (c->check_struct (this) &&
+                          machine.sanitize (c)));
+  }
+
+  protected:
+  KernSubTableHeader            header;
+  StateTable<Types, EntryData>  machine;
+  HBUINT32                      flags;
+  public:
+  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 20);
+};
+
+template <typename KernSubTableHeader>
+struct KerxSubTableFormat6
+{
+  enum Flags
+  {
+    ValuesAreLong       = 0x00000001,
+  };
+
+  bool is_long () const { return flags & ValuesAreLong; }
+
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right,
+                          hb_aat_apply_context_t *c) const
+  {
+    unsigned int num_glyphs = c->sanitizer.get_num_glyphs ();
+    if (is_long ())
+    {
+      const typename U::Long &t = u.l;
+      unsigned int l = (this+t.rowIndexTable).get_value_or_null (left, num_glyphs);
+      unsigned int r = (this+t.columnIndexTable).get_value_or_null (right, num_glyphs);
+      unsigned int offset = l + r;
+      if (unlikely (offset < l)) return 0; /* Addition overflow. */
+      if (unlikely (hb_unsigned_mul_overflows (offset, sizeof (FWORD32)))) return 0;
+      const FWORD32 *v = &StructAtOffset<FWORD32> (&(this+t.array), offset * sizeof (FWORD32));
+      if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
+      return kerxTupleKern (*v, header.tuple_count (), &(this+vector), c);
+    }
+    else
+    {
+      const typename U::Short &t = u.s;
+      unsigned int l = (this+t.rowIndexTable).get_value_or_null (left, num_glyphs);
+      unsigned int r = (this+t.columnIndexTable).get_value_or_null (right, num_glyphs);
+      unsigned int offset = l + r;
+      const FWORD *v = &StructAtOffset<FWORD> (&(this+t.array), offset * sizeof (FWORD));
+      if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
+      return kerxTupleKern (*v, header.tuple_count (), &(this+vector), c);
+    }
+  }
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    if (!c->plan->requested_kerning)
+      return false;
+
+    if (header.coverage & header.Backwards)
+      return false;
+
+    accelerator_t accel (*this, c);
+    hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
+    machine.kern (c->font, c->buffer, c->plan->kern_mask);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          (is_long () ?
+                           (
+                             u.l.rowIndexTable.sanitize (c, this) &&
+                             u.l.columnIndexTable.sanitize (c, this) &&
+                             c->check_range (this, u.l.array)
+                           ) : (
+                             u.s.rowIndexTable.sanitize (c, this) &&
+                             u.s.columnIndexTable.sanitize (c, this) &&
+                             c->check_range (this, u.s.array)
+                           )) &&
+                          (header.tuple_count () == 0 ||
+                           c->check_range (this, vector))));
+  }
+
+  struct accelerator_t
+  {
+    const KerxSubTableFormat6 &table;
+    hb_aat_apply_context_t *c;
+
+    accelerator_t (const KerxSubTableFormat6 &table_,
+                   hb_aat_apply_context_t *c_) :
+                     table (table_), c (c_) {}
+
+    int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+    { return table.get_kerning (left, right, c); }
+  };
+
+  protected:
+  KernSubTableHeader            header;
+  HBUINT32                      flags;
+  HBUINT16                      rowCount;
+  HBUINT16                      columnCount;
+  union U
+  {
+    struct Long
+    {
+      LNNOffsetTo<Lookup<HBUINT32> >            rowIndexTable;
+      LNNOffsetTo<Lookup<HBUINT32> >            columnIndexTable;
+      LNNOffsetTo<UnsizedArrayOf<FWORD32> >     array;
+    } l;
+    struct Short
+    {
+      LNNOffsetTo<Lookup<HBUINT16> >            rowIndexTable;
+      LNNOffsetTo<Lookup<HBUINT16> >            columnIndexTable;
+      LNNOffsetTo<UnsizedArrayOf<FWORD> >       array;
+    } s;
+  } u;
+  LNNOffsetTo<UnsizedArrayOf<FWORD> >   vector;
+  public:
+  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 24);
+};
+
+
+struct KerxSubTableHeader
+{
+  typedef ExtendedTypes Types;
+
+  unsigned int tuple_count () const { return tupleCount; }
+  bool is_horizontal () const       { return !(coverage & Vertical); }
+
+  enum Coverage
+  {
+    Vertical    = 0x80000000u,  /* Set if table has vertical kerning values. */
+    CrossStream = 0x40000000u,  /* Set if table has cross-stream kerning values. */
+    Variation   = 0x20000000u,  /* Set if table has variation kerning values. */
+    Backwards   = 0x10000000u,  /* If clear, process the glyphs forwards, that
+                                 * is, from first to last in the glyph stream.
+                                 * If we, process them from last to first.
+                                 * This flag only applies to state-table based
+                                 * 'kerx' subtables (types 1 and 4). */
+    Reserved    = 0x0FFFFF00u,  /* Reserved, set to zero. */
+    SubtableType= 0x000000FFu,  /* Subtable type. */
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  public:
+  HBUINT32      length;
+  HBUINT32      coverage;
+  HBUINT32      tupleCount;
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+struct KerxSubTable
+{
+  friend struct kerx;
+
+  unsigned int get_size () const { return u.header.length; }
+  unsigned int get_type () const { return u.header.coverage & u.header.SubtableType; }
+
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    unsigned int subtable_type = get_type ();
+    TRACE_DISPATCH (this, subtable_type);
+    switch (subtable_type) {
+    case 0:     return_trace (c->dispatch (u.format0));
+    case 1:     return_trace (c->dispatch (u.format1));
+    case 2:     return_trace (c->dispatch (u.format2));
+    case 4:     return_trace (c->dispatch (u.format4));
+    case 6:     return_trace (c->dispatch (u.format6));
+    default:    return_trace (c->default_return_value ());
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.header.sanitize (c) ||
+        u.header.length <= u.header.static_size ||
+        !c->check_range (this, u.header.length))
+      return_trace (false);
+
+    return_trace (dispatch (c));
+  }
+
+  public:
+  union {
+  KerxSubTableHeader                            header;
+  KerxSubTableFormat0<KerxSubTableHeader>       format0;
+  KerxSubTableFormat1<KerxSubTableHeader>       format1;
+  KerxSubTableFormat2<KerxSubTableHeader>       format2;
+  KerxSubTableFormat4<KerxSubTableHeader>       format4;
+  KerxSubTableFormat6<KerxSubTableHeader>       format6;
+  } u;
+  public:
+  DEFINE_SIZE_MIN (12);
+};
+
+
+/*
+ * The 'kerx' Table
+ */
+
+template <typename T>
+struct KerxTable
+{
+  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
+  const T* thiz () const { return static_cast<const T *> (this); }
+
+  bool has_state_machine () const
+  {
+    typedef typename T::SubTable SubTable;
+
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (st->get_type () == 1)
+        return true;
+      st = &StructAfter<SubTable> (*st);
+    }
+    return false;
+  }
+
+  bool has_cross_stream () const
+  {
+    typedef typename T::SubTable SubTable;
+
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (st->u.header.coverage & st->u.header.CrossStream)
+        return true;
+      st = &StructAfter<SubTable> (*st);
+    }
+    return false;
+  }
+
+  int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+  {
+    typedef typename T::SubTable SubTable;
+
+    int v = 0;
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if ((st->u.header.coverage & (st->u.header.Variation | st->u.header.CrossStream)) ||
+          !st->u.header.is_horizontal ())
+        continue;
+      v += st->get_kerning (left, right);
+      st = &StructAfter<SubTable> (*st);
+    }
+    return v;
+  }
+
+  bool apply (AAT::hb_aat_apply_context_t *c) const
+  {
+    typedef typename T::SubTable SubTable;
+
+    bool ret = false;
+    bool seenCrossStream = false;
+    c->set_lookup_index (0);
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      bool reverse;
+
+      if (!T::Types::extended && (st->u.header.coverage & st->u.header.Variation))
+        goto skip;
+
+      if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction) != st->u.header.is_horizontal ())
+        goto skip;
+
+      reverse = bool (st->u.header.coverage & st->u.header.Backwards) !=
+                HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
+
+      if (!c->buffer->message (c->font, "start %c%c%c%c subtable %d", HB_UNTAG (thiz()->tableTag), c->lookup_index))
+        goto skip;
+
+      if (!seenCrossStream &&
+          (st->u.header.coverage & st->u.header.CrossStream))
+      {
+        /* Attach all glyphs into a chain. */
+        seenCrossStream = true;
+        hb_glyph_position_t *pos = c->buffer->pos;
+        unsigned int count = c->buffer->len;
+        for (unsigned int i = 0; i < count; i++)
+        {
+          pos[i].attach_type() = ATTACH_TYPE_CURSIVE;
+          pos[i].attach_chain() = HB_DIRECTION_IS_FORWARD (c->buffer->props.direction) ? -1 : +1;
+          /* We intentionally don't set HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT,
+           * since there needs to be a non-zero attachment for post-positioning to
+           * be needed. */
+        }
+      }
+
+      if (reverse)
+        c->buffer->reverse ();
+
+      {
+        /* See comment in sanitize() for conditional here. */
+        hb_sanitize_with_object_t with (&c->sanitizer, i < count - 1 ? st : (const SubTable *) nullptr);
+        ret |= st->dispatch (c);
+      }
+
+      if (reverse)
+        c->buffer->reverse ();
+
+      (void) c->buffer->message (c->font, "end %c%c%c%c subtable %d", HB_UNTAG (thiz()->tableTag), c->lookup_index);
+
+    skip:
+      st = &StructAfter<SubTable> (*st);
+      c->set_lookup_index (c->lookup_index + 1);
+    }
+
+    return ret;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!thiz()->version.sanitize (c) ||
+                  (unsigned) thiz()->version < (unsigned) T::minVersion ||
+                  !thiz()->tableCount.sanitize (c)))
+      return_trace (false);
+
+    typedef typename T::SubTable SubTable;
+
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (unlikely (!st->u.header.sanitize (c)))
+        return_trace (false);
+      /* OpenType kern table has 2-byte subtable lengths.  That's limiting.
+       * MS implementation also only supports one subtable, of format 0,
+       * anyway.  Certain versions of some fonts, like Calibry, contain
+       * kern subtable that exceeds 64kb.  Looks like, the subtable length
+       * is simply ignored.  Which makes sense.  It's only needed if you
+       * have multiple subtables.  To handle such fonts, we just ignore
+       * the length for the last subtable. */
+      hb_sanitize_with_object_t with (c, i < count - 1 ? st : (const SubTable *) nullptr);
+
+      if (unlikely (!st->sanitize (c)))
+        return_trace (false);
+
+      st = &StructAfter<SubTable> (*st);
+    }
+
+    return_trace (true);
+  }
+};
+
+struct kerx : KerxTable<kerx>
+{
+  friend struct KerxTable<kerx>;
+
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_kerx;
+  static constexpr unsigned minVersion = 2u;
+
+  typedef KerxSubTableHeader SubTableHeader;
+  typedef SubTableHeader::Types Types;
+  typedef KerxSubTable SubTable;
+
+  bool has_data () const { return version; }
+
+  protected:
+  HBUINT16      version;        /* The version number of the extended kerning table
+                                 * (currently 2, 3, or 4). */
+  HBUINT16      unused;         /* Set to 0. */
+  HBUINT32      tableCount;     /* The number of subtables included in the extended kerning
+                                 * table. */
+  SubTable      firstSubTable;  /* Subtables. */
+/*subtableGlyphCoverageArray*/  /* Only if version >= 3. We don't use. */
+
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_KERX_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-lcar-table.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,93 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+#ifndef HB_AAT_LAYOUT_LCAR_TABLE_HH
+#define HB_AAT_LAYOUT_LCAR_TABLE_HH
+
+#include "hb-open-type.hh"
+#include "hb-aat-layout-common.hh"
+
+/*
+ * lcar -- Ligature caret
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6lcar.html
+ */
+#define HB_AAT_TAG_lcar HB_TAG('l','c','a','r')
+
+
+namespace AAT {
+
+typedef ArrayOf<HBINT16> LigCaretClassEntry;
+
+struct lcar
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_lcar;
+
+  unsigned int get_lig_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 */) const
+  {
+    const OffsetTo<LigCaretClassEntry>* entry_offset = lookup.get_value (glyph,
+                                                                         font->face->get_num_glyphs ());
+    const LigCaretClassEntry& array = entry_offset ? this+*entry_offset : Null (LigCaretClassEntry);
+    if (caret_count)
+    {
+      hb_array_t<const HBINT16> arr = array.sub_array (start_offset, caret_count);
+      unsigned int count = arr.length;
+      for (unsigned int i = 0; i < count; ++i)
+        switch (format)
+        {
+        case 0: caret_array[i] = font->em_scale_dir (arr[i], direction); break;
+        case 1:
+          hb_position_t x, y;
+          font->get_glyph_contour_point_for_origin (glyph, arr[i], direction, &x, &y);
+          caret_array[i] = HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
+          break;
+        }
+    }
+    return array.len;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          version.major == 1 &&
+                          lookup.sanitize (c, this)));
+  }
+
+  protected:
+  FixedVersion<>version;        /* Version number of the ligature caret table */
+  HBUINT16      format;         /* Format of the ligature caret table. */
+  Lookup<OffsetTo<LigCaretClassEntry> >
+                lookup;         /* data Lookup table associating glyphs */
+
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+} /* namespace AAT */
+
+#endif /* HB_AAT_LAYOUT_LCAR_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-morx-table.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,1159 @@
+/*
+ * Copyright © 2017  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_LAYOUT_MORX_TABLE_HH
+#define HB_AAT_LAYOUT_MORX_TABLE_HH
+
+#include "hb-open-type.hh"
+#include "hb-aat-layout-common.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-aat-map.hh"
+
+/*
+ * morx -- Extended Glyph Metamorphosis
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6mort.html
+ */
+#define HB_AAT_TAG_morx HB_TAG('m','o','r','x')
+#define HB_AAT_TAG_mort HB_TAG('m','o','r','t')
+
+
+namespace AAT {
+
+using namespace OT;
+
+template <typename Types>
+struct RearrangementSubtable
+{
+  typedef typename Types::HBUINT HBUINT;
+
+  typedef void EntryData;
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = true;
+    enum Flags
+    {
+      MarkFirst         = 0x8000,       /* If set, make the current glyph the first
+                                         * glyph to be rearranged. */
+      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph
+                                         * before going to the new state. This means
+                                         * that the glyph index doesn't change, even
+                                         * if the glyph at that index has changed. */
+      MarkLast          = 0x2000,       /* If set, make the current glyph the last
+                                         * glyph to be rearranged. */
+      Reserved          = 0x1FF0,       /* These bits are reserved and should be set to 0. */
+      Verb              = 0x000F,       /* The type of rearrangement specified. */
+    };
+
+    driver_context_t (const RearrangementSubtable *table HB_UNUSED) :
+        ret (false),
+        start (0), end (0) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                        const Entry<EntryData> &entry)
+    {
+      return (entry.flags & Verb) && start < end;
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                     const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+      unsigned int flags = entry.flags;
+
+      if (flags & MarkFirst)
+        start = buffer->idx;
+
+      if (flags & MarkLast)
+        end = MIN (buffer->idx + 1, buffer->len);
+
+      if ((flags & Verb) && start < end)
+      {
+        /* The following map has two nibbles, for start-side
+         * and end-side. Values of 0,1,2 mean move that many
+         * to the other side. Value of 3 means move 2 and
+         * flip them. */
+        const unsigned char map[16] =
+        {
+          0x00, /* 0    no change */
+          0x10, /* 1    Ax => xA */
+          0x01, /* 2    xD => Dx */
+          0x11, /* 3    AxD => DxA */
+          0x20, /* 4    ABx => xAB */
+          0x30, /* 5    ABx => xBA */
+          0x02, /* 6    xCD => CDx */
+          0x03, /* 7    xCD => DCx */
+          0x12, /* 8    AxCD => CDxA */
+          0x13, /* 9    AxCD => DCxA */
+          0x21, /* 10   ABxD => DxAB */
+          0x31, /* 11   ABxD => DxBA */
+          0x22, /* 12   ABxCD => CDxAB */
+          0x32, /* 13   ABxCD => CDxBA */
+          0x23, /* 14   ABxCD => DCxAB */
+          0x33, /* 15   ABxCD => DCxBA */
+        };
+
+        unsigned int m = map[flags & Verb];
+        unsigned int l = MIN<unsigned int> (2, m >> 4);
+        unsigned int r = MIN<unsigned int> (2, m & 0x0F);
+        bool reverse_l = 3 == (m >> 4);
+        bool reverse_r = 3 == (m & 0x0F);
+
+        if (end - start >= l + r)
+        {
+          buffer->merge_clusters (start, MIN (buffer->idx + 1, buffer->len));
+          buffer->merge_clusters (start, end);
+
+          hb_glyph_info_t *info = buffer->info;
+          hb_glyph_info_t buf[4];
+
+          memcpy (buf, info + start, l * sizeof (buf[0]));
+          memcpy (buf + 2, info + end - r, r * sizeof (buf[0]));
+
+          if (l != r)
+            memmove (info + start + r, info + start + l, (end - start - l - r) * sizeof (buf[0]));
+
+          memcpy (info + start, buf + 2, r * sizeof (buf[0]));
+          memcpy (info + end - l, buf, l * sizeof (buf[0]));
+          if (reverse_l)
+          {
+            buf[0] = info[end - 1];
+            info[end - 1] = info[end - 2];
+            info[end - 2] = buf[0];
+          }
+          if (reverse_r)
+          {
+            buf[0] = info[start];
+            info[start] = info[start + 1];
+            info[start + 1] = buf[0];
+          }
+        }
+      }
+    }
+
+    public:
+    bool ret;
+    private:
+    unsigned int start;
+    unsigned int end;
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    driver_context_t dc (this);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+    driver.drive (&dc);
+
+    return_trace (dc.ret);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (machine.sanitize (c));
+  }
+
+  protected:
+  StateTable<Types, EntryData>  machine;
+  public:
+  DEFINE_SIZE_STATIC (16);
+};
+
+template <typename Types>
+struct ContextualSubtable
+{
+  typedef typename Types::HBUINT HBUINT;
+
+  struct EntryData
+  {
+    HBUINT16    markIndex;      /* Index of the substitution table for the
+                                 * marked glyph (use 0xFFFF for none). */
+    HBUINT16    currentIndex;   /* Index of the substitution table for the
+                                 * current glyph (use 0xFFFF for none). */
+    public:
+    DEFINE_SIZE_STATIC (4);
+  };
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = true;
+    enum Flags
+    {
+      SetMark           = 0x8000,       /* If set, make the current glyph the marked glyph. */
+      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph before
+                                         * going to the new state. */
+      Reserved          = 0x3FFF,       /* These bits are reserved and should be set to 0. */
+    };
+
+    driver_context_t (const ContextualSubtable *table_,
+                             hb_aat_apply_context_t *c_) :
+        ret (false),
+        c (c_),
+        mark_set (false),
+        mark (0),
+        table (table_),
+        subs (table+table->substitutionTables) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver,
+                        const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+
+      if (buffer->idx == buffer->len && !mark_set)
+        return false;
+
+      return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                     const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+
+      /* Looks like CoreText applies neither mark nor current substitution for
+       * end-of-text if mark was not explicitly set. */
+      if (buffer->idx == buffer->len && !mark_set)
+        return;
+
+      const GlyphID *replacement;
+
+      replacement = nullptr;
+      if (Types::extended)
+      {
+        if (entry.data.markIndex != 0xFFFF)
+        {
+          const Lookup<GlyphID> &lookup = subs[entry.data.markIndex];
+          replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs);
+        }
+      }
+      else
+      {
+        unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint;
+        const UnsizedArrayOf<GlyphID> &subs_old = (const UnsizedArrayOf<GlyphID> &) subs;
+        replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
+        if (!replacement->sanitize (&c->sanitizer) || !*replacement)
+          replacement = nullptr;
+      }
+      if (replacement)
+      {
+        buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len));
+        buffer->info[mark].codepoint = *replacement;
+        ret = true;
+      }
+
+      replacement = nullptr;
+      unsigned int idx = MIN (buffer->idx, buffer->len - 1);
+      if (Types::extended)
+      {
+        if (entry.data.currentIndex != 0xFFFF)
+        {
+          const Lookup<GlyphID> &lookup = subs[entry.data.currentIndex];
+          replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs);
+        }
+      }
+      else
+      {
+        unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint;
+        const UnsizedArrayOf<GlyphID> &subs_old = (const UnsizedArrayOf<GlyphID> &) subs;
+        replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
+        if (!replacement->sanitize (&c->sanitizer) || !*replacement)
+          replacement = nullptr;
+      }
+      if (replacement)
+      {
+        buffer->info[idx].codepoint = *replacement;
+        ret = true;
+      }
+
+      if (entry.flags & SetMark)
+      {
+        mark_set = true;
+        mark = buffer->idx;
+      }
+    }
+
+    public:
+    bool ret;
+    private:
+    hb_aat_apply_context_t *c;
+    bool mark_set;
+    unsigned int mark;
+    const ContextualSubtable *table;
+    const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false> &subs;
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    driver_context_t dc (this, c);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+    driver.drive (&dc);
+
+    return_trace (dc.ret);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    unsigned int num_entries = 0;
+    if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false);
+
+    if (!Types::extended)
+      return_trace (substitutionTables.sanitize (c, this, 0));
+
+    unsigned int num_lookups = 0;
+
+    const Entry<EntryData> *entries = machine.get_entries ();
+    for (unsigned int i = 0; i < num_entries; i++)
+    {
+      const EntryData &data = entries[i].data;
+
+      if (data.markIndex != 0xFFFF)
+        num_lookups = MAX<unsigned int> (num_lookups, 1 + data.markIndex);
+      if (data.currentIndex != 0xFFFF)
+        num_lookups = MAX<unsigned int> (num_lookups, 1 + data.currentIndex);
+    }
+
+    return_trace (substitutionTables.sanitize (c, this, num_lookups));
+  }
+
+  protected:
+  StateTable<Types, EntryData>
+                machine;
+  NNOffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false>, HBUINT>
+                substitutionTables;
+  public:
+  DEFINE_SIZE_STATIC (20);
+};
+
+
+template <bool extended>
+struct LigatureEntry;
+
+template <>
+struct LigatureEntry<true>
+{
+  enum Flags
+  {
+    SetComponent        = 0x8000,       /* Push this glyph onto the component stack for
+                                         * eventual processing. */
+    DontAdvance         = 0x4000,       /* Leave the glyph pointer at this glyph for the
+                                           next iteration. */
+    PerformAction       = 0x2000,       /* Use the ligActionIndex to process a ligature
+                                         * group. */
+    Reserved            = 0x1FFF,       /* These bits are reserved and should be set to 0. */
+  };
+
+  struct EntryData
+  {
+    HBUINT16    ligActionIndex; /* Index to the first ligActionTable entry
+                                 * for processing this group, if indicated
+                                 * by the flags. */
+    public:
+    DEFINE_SIZE_STATIC (2);
+  };
+
+  static bool performAction (const Entry<EntryData> &entry)
+  { return entry.flags & PerformAction; }
+
+  static unsigned int ligActionIndex (const Entry<EntryData> &entry)
+  { return entry.data.ligActionIndex; }
+};
+template <>
+struct LigatureEntry<false>
+{
+  enum Flags
+  {
+    SetComponent        = 0x8000,       /* Push this glyph onto the component stack for
+                                         * eventual processing. */
+    DontAdvance         = 0x4000,       /* Leave the glyph pointer at this glyph for the
+                                           next iteration. */
+    Offset              = 0x3FFF,       /* Byte offset from beginning of subtable to the
+                                         * ligature action list. This value must be a
+                                         * multiple of 4. */
+  };
+
+  typedef void EntryData;
+
+  static bool performAction (const Entry<EntryData> &entry)
+  { return entry.flags & Offset; }
+
+  static unsigned int ligActionIndex (const Entry<EntryData> &entry)
+  { return entry.flags & Offset; }
+};
+
+
+template <typename Types>
+struct LigatureSubtable
+{
+  typedef typename Types::HBUINT HBUINT;
+
+  typedef LigatureEntry<Types::extended> LigatureEntryT;
+  typedef typename LigatureEntryT::EntryData EntryData;
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = false;
+    enum
+    {
+      DontAdvance       = LigatureEntryT::DontAdvance,
+    };
+    enum LigActionFlags
+    {
+      LigActionLast     = 0x80000000,   /* This is the last action in the list. This also
+                                         * implies storage. */
+      LigActionStore    = 0x40000000,   /* Store the ligature at the current cumulated index
+                                         * in the ligature table in place of the marked
+                                         * (i.e. currently-popped) glyph. */
+      LigActionOffset   = 0x3FFFFFFF,   /* A 30-bit value which is sign-extended to 32-bits
+                                         * and added to the glyph ID, resulting in an index
+                                         * into the component table. */
+    };
+
+    driver_context_t (const LigatureSubtable *table_,
+                      hb_aat_apply_context_t *c_) :
+        ret (false),
+        c (c_),
+        table (table_),
+        ligAction (table+table->ligAction),
+        component (table+table->component),
+        ligature (table+table->ligature),
+        match_length (0) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                        const Entry<EntryData> &entry)
+    {
+      return LigatureEntryT::performAction (entry);
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                     const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+
+      DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx);
+      if (entry.flags & LigatureEntryT::SetComponent)
+      {
+        /* Never mark same index twice, in case DontAdvance was used... */
+        if (match_length && match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] == buffer->out_len)
+          match_length--;
+
+        match_positions[match_length++ % ARRAY_LENGTH (match_positions)] = buffer->out_len;
+        DEBUG_MSG (APPLY, nullptr, "Set component at %u", buffer->out_len);
+      }
+
+      if (LigatureEntryT::performAction (entry))
+      {
+        DEBUG_MSG (APPLY, nullptr, "Perform action with %u", match_length);
+        unsigned int end = buffer->out_len;
+
+        if (unlikely (!match_length))
+          return;
+
+        if (buffer->idx >= buffer->len)
+          return; /* TODO Work on previous instead? */
+
+        unsigned int cursor = match_length;
+
+        unsigned int action_idx = LigatureEntryT::ligActionIndex (entry);
+        action_idx = Types::offsetToIndex (action_idx, table, ligAction.arrayZ);
+        const HBUINT32 *actionData = &ligAction[action_idx];
+
+        unsigned int ligature_idx = 0;
+        unsigned int action;
+        do
+        {
+          if (unlikely (!cursor))
+          {
+            /* Stack underflow.  Clear the stack. */
+            DEBUG_MSG (APPLY, nullptr, "Stack underflow");
+            match_length = 0;
+            break;
+          }
+
+          DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1);
+          buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]);
+
+          if (unlikely (!actionData->sanitize (&c->sanitizer))) break;
+          action = *actionData;
+
+          uint32_t uoffset = action & LigActionOffset;
+          if (uoffset & 0x20000000)
+            uoffset |= 0xC0000000; /* Sign-extend. */
+          int32_t offset = (int32_t) uoffset;
+          unsigned int component_idx = buffer->cur().codepoint + offset;
+          component_idx = Types::wordOffsetToIndex (component_idx, table, component.arrayZ);
+          const HBUINT16 &componentData = component[component_idx];
+          if (unlikely (!componentData.sanitize (&c->sanitizer))) break;
+          ligature_idx += componentData;
+
+          DEBUG_MSG (APPLY, nullptr, "Action store %u last %u",
+                     bool (action & LigActionStore),
+                     bool (action & LigActionLast));
+          if (action & (LigActionStore | LigActionLast))
+          {
+            ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ);
+            const GlyphID &ligatureData = ligature[ligature_idx];
+            if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break;
+            hb_codepoint_t lig = ligatureData;
+
+            DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
+            buffer->replace_glyph (lig);
+
+            unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u;
+            /* Now go and delete all subsequent components. */
+            while (match_length - 1u > cursor)
+            {
+              DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
+              buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]);
+              buffer->replace_glyph (DELETED_GLYPH);
+            }
+
+            buffer->move_to (lig_end);
+            buffer->merge_out_clusters (match_positions[cursor % ARRAY_LENGTH (match_positions)], buffer->out_len);
+          }
+
+          actionData++;
+        }
+        while (!(action & LigActionLast));
+        buffer->move_to (end);
+      }
+    }
+
+    public:
+    bool ret;
+    private:
+    hb_aat_apply_context_t *c;
+    const LigatureSubtable *table;
+    const UnsizedArrayOf<HBUINT32> &ligAction;
+    const UnsizedArrayOf<HBUINT16> &component;
+    const UnsizedArrayOf<GlyphID> &ligature;
+    unsigned int match_length;
+    unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    driver_context_t dc (this, c);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+    driver.drive (&dc);
+
+    return_trace (dc.ret);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    /* The rest of array sanitizations are done at run-time. */
+    return_trace (c->check_struct (this) && machine.sanitize (c) &&
+                  ligAction && component && ligature);
+  }
+
+  protected:
+  StateTable<Types, EntryData>
+                machine;
+  NNOffsetTo<UnsizedArrayOf<HBUINT32>, HBUINT>
+                ligAction;      /* Offset to the ligature action table. */
+  NNOffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT>
+                component;      /* Offset to the component table. */
+  NNOffsetTo<UnsizedArrayOf<GlyphID>, HBUINT>
+                ligature;       /* Offset to the actual ligature lists. */
+  public:
+  DEFINE_SIZE_STATIC (28);
+};
+
+template <typename Types>
+struct NoncontextualSubtable
+{
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    bool ret = false;
+    unsigned int num_glyphs = c->face->get_num_glyphs ();
+
+    hb_glyph_info_t *info = c->buffer->info;
+    unsigned int count = c->buffer->len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const GlyphID *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
+      if (replacement)
+      {
+        info[i].codepoint = *replacement;
+        ret = true;
+      }
+    }
+
+    return_trace (ret);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (substitute.sanitize (c));
+  }
+
+  protected:
+  Lookup<GlyphID>       substitute;
+  public:
+  DEFINE_SIZE_MIN (2);
+};
+
+template <typename Types>
+struct InsertionSubtable
+{
+  typedef typename Types::HBUINT HBUINT;
+
+  struct EntryData
+  {
+    HBUINT16    currentInsertIndex;     /* Zero-based index into the insertion glyph table.
+                                         * The number of glyphs to be inserted is contained
+                                         * in the currentInsertCount field in the flags.
+                                         * A value of 0xFFFF indicates no insertion is to
+                                         * be done. */
+    HBUINT16    markedInsertIndex;      /* Zero-based index into the insertion glyph table.
+                                         * The number of glyphs to be inserted is contained
+                                         * in the markedInsertCount field in the flags.
+                                         * A value of 0xFFFF indicates no insertion is to
+                                         * be done. */
+    public:
+    DEFINE_SIZE_STATIC (4);
+  };
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = false;
+    enum Flags
+    {
+      SetMark           = 0x8000,       /* If set, mark the current glyph. */
+      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph before
+                                         * going to the new state.  This does not mean
+                                         * that the glyph pointed to is the same one as
+                                         * before. If you've made insertions immediately
+                                         * downstream of the current glyph, the next glyph
+                                         * processed would in fact be the first one
+                                         * inserted. */
+      CurrentIsKashidaLike= 0x2000,     /* If set, and the currentInsertList is nonzero,
+                                         * then the specified glyph list will be inserted
+                                         * as a kashida-like insertion, either before or
+                                         * after the current glyph (depending on the state
+                                         * of the currentInsertBefore flag). If clear, and
+                                         * the currentInsertList is nonzero, then the
+                                         * specified glyph list will be inserted as a
+                                         * split-vowel-like insertion, either before or
+                                         * after the current glyph (depending on the state
+                                         * of the currentInsertBefore flag). */
+      MarkedIsKashidaLike= 0x1000,      /* If set, and the markedInsertList is nonzero,
+                                         * then the specified glyph list will be inserted
+                                         * as a kashida-like insertion, either before or
+                                         * after the marked glyph (depending on the state
+                                         * of the markedInsertBefore flag). If clear, and
+                                         * the markedInsertList is nonzero, then the
+                                         * specified glyph list will be inserted as a
+                                         * split-vowel-like insertion, either before or
+                                         * after the marked glyph (depending on the state
+                                         * of the markedInsertBefore flag). */
+      CurrentInsertBefore= 0x0800,      /* If set, specifies that insertions are to be made
+                                         * to the left of the current glyph. If clear,
+                                         * they're made to the right of the current glyph. */
+      MarkedInsertBefore= 0x0400,       /* If set, specifies that insertions are to be
+                                         * made to the left of the marked glyph. If clear,
+                                         * they're made to the right of the marked glyph. */
+      CurrentInsertCount= 0x3E0,        /* This 5-bit field is treated as a count of the
+                                         * number of glyphs to insert at the current
+                                         * position. Since zero means no insertions, the
+                                         * largest number of insertions at any given
+                                         * current location is 31 glyphs. */
+      MarkedInsertCount= 0x001F,        /* This 5-bit field is treated as a count of the
+                                         * number of glyphs to insert at the marked
+                                         * position. Since zero means no insertions, the
+                                         * largest number of insertions at any given
+                                         * marked location is 31 glyphs. */
+    };
+
+    driver_context_t (const InsertionSubtable *table,
+                      hb_aat_apply_context_t *c_) :
+        ret (false),
+        c (c_),
+        mark (0),
+        insertionAction (table+table->insertionAction) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                        const Entry<EntryData> &entry)
+    {
+      return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
+             (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                     const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+      unsigned int flags = entry.flags;
+
+      unsigned mark_loc = buffer->out_len;
+
+      if (entry.data.markedInsertIndex != 0xFFFF)
+      {
+        unsigned int count = (flags & MarkedInsertCount);
+        unsigned int start = entry.data.markedInsertIndex;
+        const GlyphID *glyphs = &insertionAction[start];
+        if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
+
+        bool before = flags & MarkedInsertBefore;
+
+        unsigned int end = buffer->out_len;
+        buffer->move_to (mark);
+
+        if (buffer->idx < buffer->len && !before)
+          buffer->copy_glyph ();
+        /* TODO We ignore KashidaLike setting. */
+        for (unsigned int i = 0; i < count; i++)
+          buffer->output_glyph (glyphs[i]);
+        if (buffer->idx < buffer->len && !before)
+          buffer->skip_glyph ();
+
+        buffer->move_to (end + count);
+
+        buffer->unsafe_to_break_from_outbuffer (mark, MIN (buffer->idx + 1, buffer->len));
+      }
+
+      if (flags & SetMark)
+        mark = mark_loc;
+
+      if (entry.data.currentInsertIndex != 0xFFFF)
+      {
+        unsigned int count = (flags & CurrentInsertCount) >> 5;
+        unsigned int start = entry.data.currentInsertIndex;
+        const GlyphID *glyphs = &insertionAction[start];
+        if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
+
+        bool before = flags & CurrentInsertBefore;
+
+        unsigned int end = buffer->out_len;
+
+        if (buffer->idx < buffer->len && !before)
+          buffer->copy_glyph ();
+        /* TODO We ignore KashidaLike setting. */
+        for (unsigned int i = 0; i < count; i++)
+          buffer->output_glyph (glyphs[i]);
+        if (buffer->idx < buffer->len && !before)
+          buffer->skip_glyph ();
+
+        /* Humm. Not sure where to move to.  There's this wording under
+         * DontAdvance flag:
+         *
+         * "If set, don't update the glyph index before going to the new state.
+         * This does not mean that the glyph pointed to is the same one as
+         * before. If you've made insertions immediately downstream of the
+         * current glyph, the next glyph processed would in fact be the first
+         * one inserted."
+         *
+         * This suggests that if DontAdvance is NOT set, we should move to
+         * end+count.  If it *was*, then move to end, such that newly inserted
+         * glyphs are now visible.
+         *
+         * https://github.com/harfbuzz/harfbuzz/issues/1224#issuecomment-427691417
+         */
+        buffer->move_to ((flags & DontAdvance) ? end : end + count);
+      }
+    }
+
+    public:
+    bool ret;
+    private:
+    hb_aat_apply_context_t *c;
+    unsigned int mark;
+    const UnsizedArrayOf<GlyphID> &insertionAction;
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    driver_context_t dc (this, c);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+    driver.drive (&dc);
+
+    return_trace (dc.ret);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    /* The rest of array sanitizations are done at run-time. */
+    return_trace (c->check_struct (this) && machine.sanitize (c) &&
+                  insertionAction);
+  }
+
+  protected:
+  StateTable<Types, EntryData>
+                machine;
+  NNOffsetTo<UnsizedArrayOf<GlyphID>, HBUINT>
+                insertionAction;        /* Byte offset from stateHeader to the start of
+                                         * the insertion glyph table. */
+  public:
+  DEFINE_SIZE_STATIC (20);
+};
+
+
+struct Feature
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT16      featureType;    /* The type of feature. */
+  HBUINT16      featureSetting; /* The feature's setting (aka selector). */
+  HBUINT32      enableFlags;    /* Flags for the settings that this feature
+                                 * and setting enables. */
+  HBUINT32      disableFlags;   /* Complement of flags for the settings that this
+                                 * feature and setting disable. */
+
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+template <typename Types>
+struct ChainSubtable
+{
+  typedef typename Types::HBUINT HBUINT;
+
+  template <typename T>
+  friend struct Chain;
+
+  unsigned int get_size () const     { return length; }
+  unsigned int get_type () const     { return coverage & 0xFF; }
+  unsigned int get_coverage () const { return coverage >> (sizeof (HBUINT) * 8 - 8); }
+
+  enum Coverage
+  {
+    Vertical            = 0x80, /* If set, this subtable will only be applied
+                                 * to vertical text. If clear, this subtable
+                                 * will only be applied to horizontal text. */
+    Backwards           = 0x40, /* If set, this subtable will process glyphs
+                                 * in descending order. If clear, it will
+                                 * process the glyphs in ascending order. */
+    AllDirections       = 0x20, /* If set, this subtable will be applied to
+                                 * both horizontal and vertical text (i.e.
+                                 * the state of bit 0x80000000 is ignored). */
+    Logical             = 0x10, /* If set, this subtable will process glyphs
+                                 * in logical order (or reverse logical order,
+                                 * depending on the value of bit 0x80000000). */
+  };
+  enum Type
+  {
+    Rearrangement       = 0,
+    Contextual          = 1,
+    Ligature            = 2,
+    Noncontextual       = 4,
+    Insertion           = 5
+  };
+
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    unsigned int subtable_type = get_type ();
+    TRACE_DISPATCH (this, subtable_type);
+    switch (subtable_type) {
+    case Rearrangement:         return_trace (c->dispatch (u.rearrangement));
+    case Contextual:            return_trace (c->dispatch (u.contextual));
+    case Ligature:              return_trace (c->dispatch (u.ligature));
+    case Noncontextual:         return_trace (c->dispatch (u.noncontextual));
+    case Insertion:             return_trace (c->dispatch (u.insertion));
+    default:                    return_trace (c->default_return_value ());
+    }
+  }
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    hb_sanitize_with_object_t with (&c->sanitizer, this);
+    return_trace (dispatch (c));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!length.sanitize (c) ||
+        length <= min_size ||
+        !c->check_range (this, length))
+      return_trace (false);
+
+    hb_sanitize_with_object_t with (c, this);
+    return_trace (dispatch (c));
+  }
+
+  protected:
+  HBUINT        length;         /* Total subtable length, including this header. */
+  HBUINT        coverage;       /* Coverage flags and subtable type. */
+  HBUINT32      subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */
+  union {
+  RearrangementSubtable<Types>  rearrangement;
+  ContextualSubtable<Types>     contextual;
+  LigatureSubtable<Types>       ligature;
+  NoncontextualSubtable<Types>  noncontextual;
+  InsertionSubtable<Types>      insertion;
+  } u;
+  public:
+  DEFINE_SIZE_MIN (2 * sizeof (HBUINT) + 4);
+};
+
+template <typename Types>
+struct Chain
+{
+  typedef typename Types::HBUINT HBUINT;
+
+  hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const
+  {
+    hb_mask_t flags = defaultFlags;
+    {
+      unsigned int count = featureCount;
+      for (unsigned i = 0; i < count; i++)
+      {
+        const Feature &feature = featureZ[i];
+        hb_aat_layout_feature_type_t type = (hb_aat_layout_feature_type_t) (unsigned int) feature.featureType;
+        hb_aat_layout_feature_selector_t setting = (hb_aat_layout_feature_selector_t) (unsigned int) feature.featureSetting;
+      retry:
+        const hb_aat_map_builder_t::feature_info_t *info = map->features.bsearch (type);
+        if (info && info->setting == setting)
+        {
+          flags &= feature.disableFlags;
+          flags |= feature.enableFlags;
+        }
+        else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE && setting == HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS)
+        {
+          /* Deprecated. https://github.com/harfbuzz/harfbuzz/issues/1342 */
+          type = HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE;
+          setting = HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS;
+          goto retry;
+        }
+      }
+    }
+    return flags;
+  }
+
+  void apply (hb_aat_apply_context_t *c,
+                     hb_mask_t flags) const
+  {
+    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types> > (featureZ.as_array (featureCount));
+    unsigned int count = subtableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      bool reverse;
+
+      if (!(subtable->subFeatureFlags & flags))
+        goto skip;
+
+      if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) &&
+          HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
+          bool (subtable->get_coverage() & ChainSubtable<Types>::Vertical))
+        goto skip;
+
+      /* Buffer contents is always in logical direction.  Determine if
+       * we need to reverse before applying this subtable.  We reverse
+       * back after if we did reverse indeed.
+       *
+       * Quoting the spac:
+       * """
+       * Bits 28 and 30 of the coverage field control the order in which
+       * glyphs are processed when the subtable is run by the layout engine.
+       * Bit 28 is used to indicate if the glyph processing direction is
+       * the same as logical order or layout order. Bit 30 is used to
+       * indicate whether glyphs are processed forwards or backwards within
+       * that order.
+
+                Bit 30  Bit 28  Interpretation for Horizontal Text
+                0       0       The subtable is processed in layout order
+                                (the same order as the glyphs, which is
+                                always left-to-right).
+                1       0       The subtable is processed in reverse layout order
+                                (the order opposite that of the glyphs, which is
+                                always right-to-left).
+                0       1       The subtable is processed in logical order
+                                (the same order as the characters, which may be
+                                left-to-right or right-to-left).
+                1       1       The subtable is processed in reverse logical order
+                                (the order opposite that of the characters, which
+                                may be right-to-left or left-to-right).
+       */
+      reverse = subtable->get_coverage () & ChainSubtable<Types>::Logical ?
+                bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) :
+                bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) !=
+                HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
+
+      if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index))
+        goto skip;
+
+      if (reverse)
+        c->buffer->reverse ();
+
+      subtable->apply (c);
+
+      if (reverse)
+        c->buffer->reverse ();
+
+      (void) c->buffer->message (c->font, "end chain subtable %d", c->lookup_index);
+
+      if (unlikely (!c->buffer->successful)) return;
+
+    skip:
+      subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
+      c->set_lookup_index (c->lookup_index + 1);
+    }
+  }
+
+  unsigned int get_size () const { return length; }
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int version HB_UNUSED) const
+  {
+    TRACE_SANITIZE (this);
+    if (!length.sanitize (c) ||
+        length < min_size ||
+        !c->check_range (this, length))
+      return_trace (false);
+
+    if (!c->check_array (featureZ.arrayZ, featureCount))
+      return_trace (false);
+
+    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types> > (featureZ.as_array (featureCount));
+    unsigned int count = subtableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (!subtable->sanitize (c))
+        return_trace (false);
+      subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
+    }
+
+    return_trace (true);
+  }
+
+  protected:
+  HBUINT32      defaultFlags;   /* The default specification for subtables. */
+  HBUINT32      length;         /* Total byte count, including this header. */
+  HBUINT        featureCount;   /* Number of feature subtable entries. */
+  HBUINT        subtableCount;  /* The number of subtables in the chain. */
+
+  UnsizedArrayOf<Feature>       featureZ;       /* Features. */
+/*ChainSubtable firstSubtable;*//* Subtables. */
+/*subtableGlyphCoverageArray*/  /* Only if version >= 3. We don't use. */
+
+  public:
+  DEFINE_SIZE_MIN (8 + 2 * sizeof (HBUINT));
+};
+
+
+/*
+ * The 'mort'/'morx' Table
+ */
+
+template <typename Types>
+struct mortmorx
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_morx;
+
+  bool has_data () const { return version != 0; }
+
+  void compile_flags (const hb_aat_map_builder_t *mapper,
+                      hb_aat_map_t *map) const
+  {
+    const Chain<Types> *chain = &firstChain;
+    unsigned int count = chainCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      map->chain_flags.push (chain->compile_flags (mapper));
+      chain = &StructAfter<Chain<Types> > (*chain);
+    }
+  }
+
+  void apply (hb_aat_apply_context_t *c) const
+  {
+    if (unlikely (!c->buffer->successful)) return;
+    c->set_lookup_index (0);
+    const Chain<Types> *chain = &firstChain;
+    unsigned int count = chainCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      chain->apply (c, c->plan->aat_map.chain_flags[i]);
+      if (unlikely (!c->buffer->successful)) return;
+      chain = &StructAfter<Chain<Types> > (*chain);
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!version.sanitize (c) || !version || !chainCount.sanitize (c))
+      return_trace (false);
+
+    const Chain<Types> *chain = &firstChain;
+    unsigned int count = chainCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (!chain->sanitize (c, version))
+        return_trace (false);
+      chain = &StructAfter<Chain<Types> > (*chain);
+    }
+
+    return_trace (true);
+  }
+
+  protected:
+  HBUINT16      version;        /* Version number of the glyph metamorphosis table.
+                                 * 1, 2, or 3. */
+  HBUINT16      unused;         /* Set to 0. */
+  HBUINT32      chainCount;     /* Number of metamorphosis chains contained in this
+                                 * table. */
+  Chain<Types>  firstChain;     /* Chains. */
+
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+struct morx : mortmorx<ExtendedTypes>
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_morx;
+};
+struct mort : mortmorx<ObsoleteTypes>
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_mort;
+};
+
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_MORX_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-trak-table.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,237 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_LAYOUT_TRAK_TABLE_HH
+#define HB_AAT_LAYOUT_TRAK_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+#include "hb-ot-layout.hh"
+#include "hb-open-type.hh"
+
+/*
+ * trak -- Tracking
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6trak.html
+ */
+#define HB_AAT_TAG_trak HB_TAG('t','r','a','k')
+
+
+namespace AAT {
+
+
+struct TrackTableEntry
+{
+  friend struct TrackData;
+
+  float get_track_value () const { return track.to_float (); }
+
+  int get_value (const void *base, unsigned int index,
+                 unsigned int table_size) const
+  { return (base+valuesZ).as_array (table_size)[index]; }
+
+  public:
+  bool sanitize (hb_sanitize_context_t *c, const void *base,
+                 unsigned int table_size) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          (valuesZ.sanitize (c, base, table_size))));
+  }
+
+  protected:
+  Fixed         track;          /* Track value for this record. */
+  NameID        trackNameID;    /* The 'name' table index for this track.
+                                 * (a short word or phrase like "loose"
+                                 * or "very tight") */
+  NNOffsetTo<UnsizedArrayOf<FWORD> >
+                valuesZ;        /* Offset from start of tracking table to
+                                 * per-size tracking values for this track. */
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct TrackData
+{
+  float interpolate_at (unsigned int idx,
+                        float target_size,
+                        const TrackTableEntry &trackTableEntry,
+                        const void *base) const
+  {
+    unsigned int sizes = nSizes;
+    hb_array_t<const Fixed> size_table ((base+sizeTable).arrayZ, sizes);
+
+    float s0 = size_table[idx].to_float ();
+    float s1 = size_table[idx + 1].to_float ();
+    float t = unlikely (s0 == s1) ? 0.f : (target_size - s0) / (s1 - s0);
+    return t * trackTableEntry.get_value (base, idx + 1, sizes) +
+           (1.f - t) * trackTableEntry.get_value (base, idx, sizes);
+  }
+
+  int get_tracking (const void *base, float ptem) const
+  {
+    /* CoreText points are CSS pixels (96 per inch),
+     * NOT typographic points (72 per inch).
+     *
+     * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
+     */
+    float csspx = ptem * 96.f / 72.f;
+
+    /*
+     * Choose track.
+     */
+    const TrackTableEntry *trackTableEntry = nullptr;
+    unsigned int count = nTracks;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      /* Note: Seems like the track entries are sorted by values.  But the
+       * spec doesn't explicitly say that.  It just mentions it in the example. */
+
+      /* For now we only seek for track entries with zero tracking value */
+
+      if (trackTable[i].get_track_value () == 0.f)
+      {
+        trackTableEntry = &trackTable[i];
+        break;
+      }
+    }
+    if (!trackTableEntry) return 0.;
+
+    /*
+     * Choose size.
+     */
+    unsigned int sizes = nSizes;
+    if (!sizes) return 0.;
+    if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
+
+    hb_array_t<const Fixed> size_table ((base+sizeTable).arrayZ, sizes);
+    unsigned int size_index;
+    for (size_index = 0; size_index < sizes - 1; size_index++)
+      if (size_table[size_index].to_float () >= csspx)
+        break;
+
+    return round (interpolate_at (size_index ? size_index - 1 : 0, csspx,
+                                  *trackTableEntry, base));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          sizeTable.sanitize (c, base, nSizes) &&
+                          trackTable.sanitize (c, nTracks, base, nSizes)));
+  }
+
+  protected:
+  HBUINT16      nTracks;        /* Number of separate tracks included in this table. */
+  HBUINT16      nSizes;         /* Number of point sizes included in this table. */
+  LOffsetTo<UnsizedArrayOf<Fixed>, false>
+                sizeTable;      /* Offset from start of the tracking table to
+                                 * Array[nSizes] of size values.. */
+  UnsizedArrayOf<TrackTableEntry>
+                trackTable;     /* Array[nTracks] of TrackTableEntry records. */
+
+  public:
+  DEFINE_SIZE_ARRAY (8, trackTable);
+};
+
+struct trak
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_trak;
+
+  bool has_data () const { return version.to_int (); }
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    hb_mask_t trak_mask = c->plan->trak_mask;
+
+    const float ptem = c->font->ptem;
+    if (unlikely (ptem <= 0.f))
+      return_trace (false);
+
+    hb_buffer_t *buffer = c->buffer;
+    if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
+    {
+      const TrackData &trackData = this+horizData;
+      int tracking = trackData.get_tracking (this, ptem);
+      hb_position_t offset_to_add = c->font->em_scalef_x (tracking / 2);
+      hb_position_t advance_to_add = c->font->em_scalef_x (tracking);
+      foreach_grapheme (buffer, start, end)
+      {
+        if (!(buffer->info[start].mask & trak_mask)) continue;
+        buffer->pos[start].x_advance += advance_to_add;
+        buffer->pos[start].x_offset += offset_to_add;
+      }
+    }
+    else
+    {
+      const TrackData &trackData = this+vertData;
+      int tracking = trackData.get_tracking (this, ptem);
+      hb_position_t offset_to_add = c->font->em_scalef_y (tracking / 2);
+      hb_position_t advance_to_add = c->font->em_scalef_y (tracking);
+      foreach_grapheme (buffer, start, end)
+      {
+        if (!(buffer->info[start].mask & trak_mask)) continue;
+        buffer->pos[start].y_advance += advance_to_add;
+        buffer->pos[start].y_offset += offset_to_add;
+      }
+    }
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    return_trace (likely (c->check_struct (this) &&
+                          version.major == 1 &&
+                          horizData.sanitize (c, this, this) &&
+                          vertData.sanitize (c, this, this)));
+  }
+
+  protected:
+  FixedVersion<>version;        /* Version of the tracking table
+                                         * (0x00010000u for version 1.0). */
+  HBUINT16      format;         /* Format of the tracking table (set to 0). */
+  OffsetTo<TrackData>
+                horizData;      /* Offset from start of tracking table to TrackData
+                                 * for horizontal text (or 0 if none). */
+  OffsetTo<TrackData>
+                vertData;       /* Offset from start of tracking table to TrackData
+                                 * for vertical text (or 0 if none). */
+  HBUINT16      reserved;       /* Reserved. Set to 0. */
+
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_TRAK_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout.cc	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,384 @@
+/*
+ * Copyright © 2017  Google, Inc.
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-open-type.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"
+
+
+/**
+ * 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.
+ **/
+
+
+/* Table data courtesy of Apple.  Converted from mnemonics to integers
+ * when moving to this file. */
+static const hb_aat_feature_mapping_t feature_mappings[] =
+{
+  {HB_TAG ('a','f','r','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS,               HB_AAT_LAYOUT_FEATURE_SELECTOR_VERTICAL_FRACTIONS,             HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS},
+  {HB_TAG ('c','2','p','c'), HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE,              HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_PETITE_CAPS,         HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE},
+  {HB_TAG ('c','2','s','c'), HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE,              HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_SMALL_CAPS,          HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE},
+  {HB_TAG ('c','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_ON,       HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_OFF},
+  {HB_TAG ('c','a','s','e'), HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT,   HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_ON,       HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_OFF},
+  {HB_TAG ('c','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_OFF},
+  {HB_TAG ('c','p','s','p'), HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT,   HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_OFF},
+  {HB_TAG ('c','s','w','h'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_OFF},
+  {HB_TAG ('d','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_ON,              HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_OFF},
+  {HB_TAG ('e','x','p','t'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPERT_CHARACTERS,              (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('f','r','a','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS,               HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS,             HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS},
+  {HB_TAG ('f','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT,                (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('h','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT,            (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('h','i','s','t'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
+  {HB_TAG ('h','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA,          HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF},
+  {HB_TAG ('h','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
+  {HB_TAG ('h','n','g','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION,         HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL,                HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION},
+  {HB_TAG ('h','o','j','o'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_HOJO_CHARACTERS,                (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('h','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_TEXT,                (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('i','t','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN,        HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON,            HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF},
+  {HB_TAG ('j','p','0','4'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS2004_CHARACTERS,             (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('j','p','7','8'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1978_CHARACTERS,             (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('j','p','8','3'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1983_CHARACTERS,             (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('j','p','9','0'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1990_CHARACTERS,             (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('l','i','g','a'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_ON,            HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_OFF},
+  {HB_TAG ('l','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE,             HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_NUMBERS,             (hb_aat_layout_feature_selector_t) 2},
+  {HB_TAG ('m','g','r','k'), HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS,     HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_ON,          HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_OFF},
+  {HB_TAG ('n','l','c','k'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_NLCCHARACTERS,                  (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('o','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE,             HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_NUMBERS,             (hb_aat_layout_feature_selector_t) 2},
+  {HB_TAG ('o','r','d','n'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,       HB_AAT_LAYOUT_FEATURE_SELECTOR_ORDINALS,                       HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
+  {HB_TAG ('p','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT,          (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('p','c','a','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE,              HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_PETITE_CAPS,         HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE},
+  {HB_TAG ('p','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT,              (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('p','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING,          HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS,           (hb_aat_layout_feature_selector_t) 4},
+  {HB_TAG ('p','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT,              (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('q','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT,             (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('r','u','b','y'), HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA,               HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON,                   HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF},
+  {HB_TAG ('s','i','n','f'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,       HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS,           HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
+  {HB_TAG ('s','m','c','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE,              HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS,          HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE},
+  {HB_TAG ('s','m','p','l'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_SIMPLIFIED_CHARACTERS,          (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('s','s','0','1'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_ON,           HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_OFF},
+  {HB_TAG ('s','s','0','2'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_ON,           HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_OFF},
+  {HB_TAG ('s','s','0','3'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_ON,         HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_OFF},
+  {HB_TAG ('s','s','0','4'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_ON,          HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_OFF},
+  {HB_TAG ('s','s','0','5'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_ON,          HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_OFF},
+  {HB_TAG ('s','s','0','6'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_ON,           HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_OFF},
+  {HB_TAG ('s','s','0','7'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_ON,         HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_OFF},
+  {HB_TAG ('s','s','0','8'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_ON,         HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_OFF},
+  {HB_TAG ('s','s','0','9'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_ON,          HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_OFF},
+  {HB_TAG ('s','s','1','0'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_ON,           HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_OFF},
+  {HB_TAG ('s','s','1','1'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_OFF},
+  {HB_TAG ('s','s','1','2'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_OFF},
+  {HB_TAG ('s','s','1','3'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_OFF},
+  {HB_TAG ('s','s','1','4'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_OFF},
+  {HB_TAG ('s','s','1','5'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_ON,       HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_OFF},
+  {HB_TAG ('s','s','1','6'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_ON,       HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_OFF},
+  {HB_TAG ('s','s','1','7'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_ON,     HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_OFF},
+  {HB_TAG ('s','s','1','8'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_OFF},
+  {HB_TAG ('s','s','1','9'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_OFF},
+  {HB_TAG ('s','s','2','0'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_OFF},
+  {HB_TAG ('s','u','b','s'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,       HB_AAT_LAYOUT_FEATURE_SELECTOR_INFERIORS,                      HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
+  {HB_TAG ('s','u','p','s'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,       HB_AAT_LAYOUT_FEATURE_SELECTOR_SUPERIORS,                      HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
+  {HB_TAG ('s','w','s','h'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_ON,            HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_OFF},
+  {HB_TAG ('t','i','t','l'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS,           HB_AAT_LAYOUT_FEATURE_SELECTOR_TITLING_CAPS,                   HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLE_OPTIONS},
+  {HB_TAG ('t','n','a','m'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_NAMES_CHARACTERS,   (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('t','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING,          HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_NUMBERS,             (hb_aat_layout_feature_selector_t) 4},
+  {HB_TAG ('t','r','a','d'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_CHARACTERS,         (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('t','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_TEXT,               (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('u','n','i','c'), HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE,             (hb_aat_layout_feature_selector_t) 14,                 (hb_aat_layout_feature_selector_t) 15},
+  {HB_TAG ('v','a','l','t'), 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','e','r','t'), 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 ('v','h','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT,            (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('v','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA,          HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON,         HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF},
+  {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)
+{
+  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);
+}
+
+
+/*
+ * hb_aat_apply_context_t
+ */
+
+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)
+{
+  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;
+  if (mort.has_data ())
+  {
+    mort.compile_flags (mapper, map);
+    return;
+  }
+}
+
+
+/*
+ * hb_aat_layout_has_substitution:
+ * @face:
+ *
+ * Returns:
+ * Since: 2.3.0
+ */
+hb_bool_t
+hb_aat_layout_has_substitution (hb_face_t *face)
+{
+  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)
+{
+  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;
+  }
+
+  hb_blob_t *mort_blob = font->face->table.mort.get_blob ();
+  const AAT::mort& mort = *mort_blob->as<AAT::mort> ();
+  if (mort.has_data ())
+  {
+    AAT::hb_aat_apply_context_t c (plan, font, buffer, mort_blob);
+    mort.apply (&c);
+    return;
+  }
+}
+
+void
+hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer)
+{
+  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;
+}
+
+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)
+{
+  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)
+{
+  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)
+{
+  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);
+}
+
+
+/*
+ * hb_aat_layout_has_tracking:
+ * @face:
+ *
+ * Returns:
+ * Since: 2.3.0
+ */
+hb_bool_t
+hb_aat_layout_has_tracking (hb_face_t *face)
+{
+  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)
+{
+  const AAT::trak& trak = *font->face->table.trak;
+
+  AAT::hb_aat_apply_context_t c (plan, font, buffer);
+  trak.apply (&c);
+}
+
+
+hb_language_t
+_hb_aat_language_get (hb_face_t *face,
+                      unsigned int i)
+{
+  return face->table.ltag->get_language (i);
+}
+
+/**
+ * hb_aat_layout_get_feature_types:
+ * @face: a face object
+ * @start_offset: iteration's start offset
+ * @feature_count:(inout) (allow-none): buffer size as input, filled size as output
+ * @features: (out caller-allocates) (array length=feature_count): features buffer
+ *
+ * Return value: Number of all available feature types.
+ *
+ * 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. */)
+{
+  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)
+{
+  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
+ * @selector_count: (inout) (allow-none): buffer size as input, filled size as output
+ * @selectors: (out caller-allocates) (array length=selector_count): settings buffer
+ * @default_index: (out) (allow-none): index of default selector if any
+ *
+ * If upon return, @default_index is set to #HB_AAT_LAYOUT_NO_SELECTOR_INDEX, then
+ * the feature type is non-exclusive.  Otherwise, @default_index is the index of
+ * the selector that is selected by default.
+ *
+ * Return value: Number of all available feature selectors.
+ *
+ * Since: 2.2.0
+ */
+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. */)
+{
+  return face->table.feat->get_selector_infos (feature_type, start_offset, selector_count, selectors, default_index);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout.h	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,486 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_AAT_H_IN
+#error "Include <hb-aat.h> instead."
+#endif
+
+#ifndef HB_AAT_LAYOUT_H
+#define HB_AAT_LAYOUT_H
+
+#include "hb.h"
+
+#include "hb-ot.h"
+
+HB_BEGIN_DECLS
+
+/**
+ * hb_aat_layout_feature_type_t:
+ *
+ *
+ * Since: 2.2.0
+ */
+typedef enum
+{
+  HB_AAT_LAYOUT_FEATURE_TYPE_INVALID                            = 0xFFFF,
+
+  HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC                    = 0,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES                          = 1,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION                 = 2,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE                        = 3,
+  HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION              = 4,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT           = 5,
+  HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING                     = 6,
+  HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE                   = 8,
+  HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE                    = 9,
+  HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION                  = 10,
+  HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS                          = 11,
+  HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE        = 13,
+  HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS                 = 14,
+  HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS                = 15,
+  HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE                 = 16,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES             = 17,
+  HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE             = 18,
+  HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS                      = 19,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE                    = 20,
+  HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE                        = 21,
+  HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING                       = 22,
+  HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION                    = 23,
+  HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE                    = 24,
+  HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE                  = 25,
+  HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE           = 26,
+  HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE         = 27,
+  HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA                          = 28,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE       = 29,
+  HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE      = 30,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE  = 31,
+  HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN                   = 32,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT              = 33,
+  HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA                     = 34,
+  HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES             = 35,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES            = 36,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE                         = 37,
+  HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE                         = 38,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE                  = 39,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE             = 103,
+
+  _HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
+} hb_aat_layout_feature_type_t;
+
+/**
+ * hb_aat_layout_feature_selector_t:
+ *
+ *
+ * Since: 2.2.0
+ */
+typedef enum
+{
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID                        = 0xFFFF,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_TYPE_FEATURES_ON           = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_TYPE_FEATURES_OFF          = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_ON          = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_OFF         = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_ON            = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_OFF           = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_ON              = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_OFF             = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOGOS_ON                       = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOGOS_OFF                      = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_REBUS_PICTURES_ON              = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_REBUS_PICTURES_OFF             = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIPHTHONG_LIGATURES_ON         = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIPHTHONG_LIGATURES_OFF        = 11,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SQUARED_LIGATURES_ON           = 12,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SQUARED_LIGATURES_OFF          = 13,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ABBREV_SQUARED_LIGATURES_ON    = 14,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ABBREV_SQUARED_LIGATURES_OFF   = 15,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SYMBOL_LIGATURES_ON            = 16,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SYMBOL_LIGATURES_OFF           = 17,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_ON        = 18,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_OFF       = 19,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON        = 20,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF       = 21,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UNCONNECTED                    = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PARTIALLY_CONNECTED            = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CURSIVE                        = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_AND_LOWER_CASE           = 0, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_CAPS                       = 1, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_LOWER_CASE                 = 2, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS                     = 3, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INITIAL_CAPS                   = 4, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INITIAL_CAPS_AND_SMALL_CAPS    = 5, /* deprecated */
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON   = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF  = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINGUISTIC_REARRANGEMENT_ON    = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINGUISTIC_REARRANGEMENT_OFF   = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_NUMBERS             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS           = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_NUMBERS            = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_NUMBERS          = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_INITIAL_SWASHES_ON        = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_INITIAL_SWASHES_OFF       = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_FINAL_SWASHES_ON          = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_FINAL_SWASHES_OFF         = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_INITIAL_SWASHES_ON        = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_INITIAL_SWASHES_OFF       = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_FINAL_SWASHES_ON          = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_FINAL_SWASHES_OFF         = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NON_FINAL_SWASHES_ON           = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NON_FINAL_SWASHES_OFF          = 9,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SHOW_DIACRITICS                = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HIDE_DIACRITICS                = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DECOMPOSE_DIACRITICS           = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION                = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SUPERIORS                      = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INFERIORS                      = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ORDINALS                       = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS           = 4,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS                   = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_VERTICAL_FRACTIONS             = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS             = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PREVENT_OVERLAP_ON             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PREVENT_OVERLAP_OFF            = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHENS_TO_EM_DASH_ON          = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHENS_TO_EM_DASH_OFF         = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_EN_DASH_ON           = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_EN_DASH_OFF          = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON                = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF               = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FORM_INTERROBANG_ON            = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FORM_INTERROBANG_OFF           = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SMART_QUOTES_ON                = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SMART_QUOTES_OFF               = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIODS_TO_ELLIPSIS_ON         = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIODS_TO_ELLIPSIS_OFF        = 11,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_MINUS_ON             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_MINUS_OFF            = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ASTERISK_TO_MULTIPLY_ON        = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ASTERISK_TO_MULTIPLY_OFF       = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASH_TO_DIVIDE_ON             = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASH_TO_DIVIDE_OFF            = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INEQUALITY_LIGATURES_ON        = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INEQUALITY_LIGATURES_OFF       = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPONENTS_ON                   = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPONENTS_OFF                  = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_ON          = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_OFF         = 11,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ORNAMENTS                   = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DINGBATS                       = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PI_CHARACTERS                  = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FLEURONS                       = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DECORATIVE_BORDERS             = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INTERNATIONAL_SYMBOLS          = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MATH_SYMBOLS                   = 6,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ALTERNATES                  = 0,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL1                  = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL2                  = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL3                  = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL4                  = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL5                  = 4,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLE_OPTIONS               = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DISPLAY_TEXT                   = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ENGRAVED_TEXT                  = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ILLUMINATED_CAPS               = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TITLING_CAPS                   = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TALL_CAPS                      = 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_CHARACTERS         = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SIMPLIFIED_CHARACTERS          = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1978_CHARACTERS             = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1983_CHARACTERS             = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1990_CHARACTERS             = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_ONE            = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_TWO            = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_THREE          = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_FOUR           = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_FIVE           = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPERT_CHARACTERS              = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS2004_CHARACTERS             = 11,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HOJO_CHARACTERS                = 12,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NLCCHARACTERS                  = 13,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_NAMES_CHARACTERS   = 14,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_NUMBERS             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_NUMBERS             = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT              = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT                = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_TEXT                = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_TEXT               = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT             = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT          = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT            = 6,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL                = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HIRAGANA_TO_KATAKANA           = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_KATAKANA_TO_HIRAGANA           = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_KANA_TO_ROMANIZATION           = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMANIZATION_TO_HIRAGANA       = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMANIZATION_TO_KATAKANA       = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_ONE        = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_TWO        = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_THREE      = 9,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ANNOTATION                  = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_BOX_ANNOTATION                 = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROUNDED_BOX_ANNOTATION         = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CIRCLE_ANNOTATION              = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_CIRCLE_ANNOTATION     = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PARENTHESIS_ANNOTATION         = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIOD_ANNOTATION              = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMAN_NUMERAL_ANNOTATION       = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAMOND_ANNOTATION             = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_BOX_ANNOTATION        = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_ROUNDED_BOX_ANNOTATION= 10,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_KANA                = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_KANA              = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_IDEOGRAPHS          = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_IDEOGRAPHS        = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_IDEOGRAPHS          = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CANONICAL_COMPOSITION_ON       = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CANONICAL_COMPOSITION_OFF      = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMPATIBILITY_COMPOSITION_ON   = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMPATIBILITY_COMPOSITION_OFF  = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRANSCODING_COMPOSITION_ON     = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRANSCODING_COMPOSITION_OFF    = 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_RUBY_KANA                   = 0, /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF instead */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA                      = 1, /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON instead */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON                   = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF                  = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_CJK_SYMBOL_ALTERNATIVES     = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_ONE             = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_TWO             = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_THREE           = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_FOUR            = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_FIVE            = 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_IDEOGRAPHIC_ALTERNATIVES    = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_ONE            = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_TWO            = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_THREE          = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_FOUR           = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_FIVE           = 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_VERTICAL_ROMAN_CENTERED    = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_VERTICAL_ROMAN_HBASELINE   = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_CJK_ITALIC_ROMAN            = 0,    /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF instead */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN               = 1,    /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON instead */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON            = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF           = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_ON       = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_OFF      = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_ON      = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_OFF     = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON        = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF       = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON         = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF        = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLISTIC_ALTERNATES        = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_ON           = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_OFF          = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_ON           = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_OFF          = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_ON         = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_OFF        = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_ON          = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_OFF         = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_ON          = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_OFF         = 11,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_ON           = 12,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_OFF          = 13,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_ON         = 14,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_OFF        = 15,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_ON         = 16,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_OFF        = 17,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_ON          = 18,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_OFF         = 19,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_ON           = 20,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_OFF          = 21,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_ON        = 22,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_OFF       = 23,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_ON        = 24,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_OFF       = 25,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_ON      = 26,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_OFF     = 27,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_ON      = 28,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_OFF     = 29,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_ON       = 30,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_OFF      = 31,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_ON       = 32,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_OFF      = 33,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_ON     = 34,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_OFF    = 35,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_ON      = 36,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_OFF     = 37,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_ON      = 38,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_OFF     = 39,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_ON        = 40,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_OFF       = 41,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_ON       = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_OFF      = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_ON            = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_OFF           = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_ON = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_OFF= 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS          = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_PETITE_CAPS         = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_SMALL_CAPS          = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_PETITE_CAPS         = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_CJK_ROMAN           = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_CJK_ROMAN         = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_CJK_ROMAN              = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_CJK_ROMAN           = 3,
+
+  _HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
+} hb_aat_layout_feature_selector_t;
+
+HB_EXTERN 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. */);
+
+HB_EXTERN 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);
+
+typedef struct hb_aat_layout_feature_selector_info_t
+{
+  hb_ot_name_id_t                       name_id;
+  hb_aat_layout_feature_selector_t      enable;
+  hb_aat_layout_feature_selector_t      disable;
+  /*< private >*/
+  unsigned int                          reserved;
+} hb_aat_layout_feature_selector_info_t;
+
+#define HB_AAT_LAYOUT_NO_SELECTOR_INDEX         0xFFFFu
+
+HB_EXTERN 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. */);
+
+
+/*
+ * morx/mort
+ */
+
+HB_EXTERN hb_bool_t
+hb_aat_layout_has_substitution (hb_face_t *face);
+
+
+/*
+ * kerx
+ */
+
+HB_EXTERN hb_bool_t
+hb_aat_layout_has_positioning (hb_face_t *face);
+
+
+/*
+ * trak
+ */
+
+HB_EXTERN hb_bool_t
+hb_aat_layout_has_tracking (hb_face_t *face);
+
+
+HB_END_DECLS
+
+#endif /* HB_AAT_LAYOUT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2017  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_LAYOUT_HH
+#define HB_AAT_LAYOUT_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape.hh"
+
+
+struct hb_aat_feature_mapping_t
+{
+  hb_tag_t otFeatureTag;
+  hb_aat_layout_feature_type_t aatFeatureType;
+  hb_aat_layout_feature_selector_t selectorToEnable;
+  hb_aat_layout_feature_selector_t selectorToDisable;
+
+  static int cmp (const void *key_, const void *entry_)
+  {
+    hb_tag_t key = * (unsigned int *) key_;
+    const hb_aat_feature_mapping_t * entry = (const hb_aat_feature_mapping_t *) entry_;
+    return key < entry->otFeatureTag ? -1 :
+           key > entry->otFeatureTag ? 1 :
+           0;
+  }
+};
+
+HB_INTERNAL const hb_aat_feature_mapping_t *
+hb_aat_layout_find_feature_mapping (hb_tag_t tag);
+
+HB_INTERNAL void
+hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
+                           hb_aat_map_t *map);
+
+HB_INTERNAL void
+hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
+                          hb_font_t *font,
+                          hb_buffer_t *buffer);
+
+HB_INTERNAL void
+hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer);
+
+HB_INTERNAL void
+hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer);
+
+HB_INTERNAL void
+hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
+                        hb_font_t *font,
+                        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);
+
+HB_INTERNAL hb_language_t
+_hb_aat_language_get (hb_face_t *face,
+                      unsigned int i);
+
+
+#endif /* HB_AAT_LAYOUT_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-ltag-table.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_AAT_LTAG_TABLE_HH
+#define HB_AAT_LTAG_TABLE_HH
+
+#include "hb-open-type.hh"
+
+/*
+ * ltag -- Language Tag
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ltag.html
+ */
+#define HB_AAT_TAG_ltag HB_TAG('l','t','a','g')
+
+
+namespace AAT {
+
+using namespace OT;
+
+
+struct FTStringRange
+{
+  friend struct ltag;
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && (base+tag).sanitize (c, length));
+  }
+
+  protected:
+  NNOffsetTo<UnsizedArrayOf<HBUINT8> >
+                tag;            /* Offset from the start of the table to
+                                 * the beginning of the string */
+  HBUINT16      length;         /* String length (in bytes) */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct ltag
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_ltag;
+
+  hb_language_t get_language (unsigned int i) const
+  {
+    const FTStringRange &range = tagRanges[i];
+    return hb_language_from_string ((const char *) (this+range.tag).arrayZ,
+                                    range.length);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          version >= 1 &&
+                          tagRanges.sanitize (c, this)));
+  }
+
+  protected:
+  HBUINT32      version;        /* Table version; currently 1 */
+  HBUINT32      flags;          /* Table flags; currently none defined */
+  LArrayOf<FTStringRange>
+                tagRanges;      /* Range for each tag's string */
+  public:
+  DEFINE_SIZE_ARRAY (12, tagRanges);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LTAG_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-map.cc	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2009,2010  Red Hat, Inc.
+ * Copyright © 2010,2011,2013  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#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)
+{
+  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;
+  }
+
+  const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (tag);
+  if (!mapping) return;
+
+  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)
+{
+  /* 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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-map.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_MAP_HH
+#define HB_AAT_MAP_HH
+
+#include "hb.hh"
+
+
+struct hb_aat_map_t
+{
+  friend struct hb_aat_map_builder_t;
+
+  public:
+
+  void init ()
+  {
+    memset (this, 0, sizeof (*this));
+    chain_flags.init ();
+  }
+  void fini () { chain_flags.fini (); }
+
+  public:
+  hb_vector_t<hb_mask_t> chain_flags;
+};
+
+struct hb_aat_map_builder_t
+{
+  public:
+
+  HB_INTERNAL hb_aat_map_builder_t (hb_face_t *face_,
+                                    const hb_segment_properties_t *props_ HB_UNUSED) :
+                                      face (face_) {}
+
+  HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value=1);
+
+  HB_INTERNAL void compile (hb_aat_map_t  &m);
+
+  public:
+  struct feature_info_t
+  {
+    hb_aat_layout_feature_type_t  type;
+    hb_aat_layout_feature_selector_t  setting;
+    unsigned  seq; /* For stable sorting only. */
+
+    static int cmp (const void *pa, const void *pb)
+    {
+      const feature_info_t *a = (const feature_info_t *) pa;
+      const feature_info_t *b = (const feature_info_t *) pb;
+      return (a->type != b->type) ? (a->type < b->type ? -1 : 1) :
+             (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
+    }
+
+    int cmp (hb_aat_layout_feature_type_t ty) const
+    {
+      return (type != ty) ? (type < ty ? -1 : 1) : 0;
+    }
+  };
+
+  public:
+  hb_face_t *face;
+
+  public:
+  hb_vector_t<feature_info_t> features;
+};
+
+
+#endif /* HB_AAT_MAP_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat.h	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_AAT_H
+#define HB_AAT_H
+#define HB_AAT_H_IN
+
+#include "hb.h"
+
+#include "hb-aat-layout.h"
+
+HB_BEGIN_DECLS
+
+HB_END_DECLS
+
+#undef HB_AAT_H_IN
+#endif /* HB_AAT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-array.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,277 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_ARRAY_HH
+#define HB_ARRAY_HH
+
+#include "hb.hh"
+#include "hb-dsalgs.hh"
+#include "hb-iter.hh"
+#include "hb-null.hh"
+
+
+template <typename Type>
+struct hb_sorted_array_t;
+
+template <typename Type>
+struct hb_array_t :
+        hb_iter_t<hb_array_t<Type>, Type>,
+        hb_iter_mixin_t<hb_array_t<Type>, Type>
+{
+  /*
+   * Constructors.
+   */
+  hb_array_t () : arrayZ (nullptr), length (0) {}
+  hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
+  template <unsigned int length_> hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_) {}
+
+
+  /*
+   * Iterator implementation.
+   */
+  typedef Type __item_type__;
+  Type& __item_at__ (unsigned i) const
+  {
+    if (unlikely (i >= length)) return CrapOrNull (Type);
+    return arrayZ[i];
+  }
+  void __forward__ (unsigned n)
+  {
+    if (unlikely (n > length))
+      n = length;
+    length -= n;
+    arrayZ += n;
+  }
+  void __rewind__ (unsigned n)
+  {
+    if (unlikely (n > length))
+      n = length;
+    length -= n;
+  }
+  unsigned __len__ () const { return length; }
+  bool __random_access__ () const { return true; }
+
+  /* Extra operators.
+   */
+  Type * operator & () const { return arrayZ; }
+  operator hb_array_t<const Type> () { return hb_array_t<const Type> (arrayZ, length); }
+  template <typename T> operator T * () const { return arrayZ; }
+
+  /*
+   * Compare, Sort, and Search.
+   */
+
+  /* Note: our compare is NOT lexicographic; it also does NOT call Type::cmp. */
+  int cmp (const hb_array_t<Type> &a) const
+  {
+    if (length != a.length)
+      return (int) a.length - (int) length;
+    return hb_memcmp (a.arrayZ, arrayZ, get_size ());
+  }
+  static int cmp (const void *pa, const void *pb)
+  {
+    hb_array_t<Type> *a = (hb_array_t<Type> *) pa;
+    hb_array_t<Type> *b = (hb_array_t<Type> *) pb;
+    return b->cmp (*a);
+  }
+
+  template <typename T>
+  Type *lsearch (const T &x, Type *not_found = nullptr)
+  {
+    unsigned int count = length;
+    for (unsigned int i = 0; i < count; i++)
+      if (!this->arrayZ[i].cmp (x))
+        return &this->arrayZ[i];
+    return not_found;
+  }
+  template <typename T>
+  const Type *lsearch (const T &x, const Type *not_found = nullptr) const
+  {
+    unsigned int count = length;
+    for (unsigned int i = 0; i < count; i++)
+      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_);
+    return hb_sorted_array_t<Type> (*this);
+  }
+  hb_sorted_array_t<Type> qsort ()
+  {
+    if (likely (length))
+      ::qsort (arrayZ, length, this->item_size, Type::cmp);
+    return hb_sorted_array_t<Type> (*this);
+  }
+  void qsort (unsigned int start, unsigned int end)
+  {
+    end = MIN (end, length);
+    assert (start <= end);
+    if (likely (start < end))
+      ::qsort (arrayZ + start, end - start, this->item_size, Type::cmp);
+  }
+
+  /*
+   * Other methods.
+   */
+
+  unsigned int get_size () const { return length * this->item_size; }
+
+  hb_array_t<Type> sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const
+  {
+    if (!start_offset && !seg_count)
+      return *this;
+
+    unsigned int count = length;
+    if (unlikely (start_offset > count))
+      count = 0;
+    else
+      count -= start_offset;
+    if (seg_count)
+      count = *seg_count = MIN (count, *seg_count);
+    return hb_array_t<Type> (arrayZ + start_offset, count);
+  }
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
+  { return sub_array (start_offset, &seg_count); }
+
+  /* Only call if you allocated the underlying array using malloc() or similar. */
+  void free ()
+  { ::free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
+
+  template <typename hb_sanitize_context_t>
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return c->check_array (arrayZ, length); }
+
+  /*
+   * Members
+   */
+
+  public:
+  Type *arrayZ;
+  unsigned int length;
+};
+template <typename T> inline hb_array_t<T>
+hb_array (T *array, unsigned int length)
+{ return hb_array_t<T> (array, length); }
+template <typename T, unsigned int length_> inline hb_array_t<T>
+hb_array (T (&array_)[length_])
+{ return hb_array_t<T> (array_); }
+
+
+enum hb_bfind_not_found_t
+{
+  HB_BFIND_NOT_FOUND_DONT_STORE,
+  HB_BFIND_NOT_FOUND_STORE,
+  HB_BFIND_NOT_FOUND_STORE_CLOSEST,
+};
+
+template <typename Type>
+struct hb_sorted_array_t :
+        hb_sorted_iter_t<hb_sorted_array_t<Type>, Type>,
+        hb_array_t<Type>,
+        hb_iter_mixin_t<hb_sorted_array_t<Type>, Type>
+{
+  hb_sorted_array_t () : hb_array_t<Type> () {}
+  hb_sorted_array_t (const hb_array_t<Type> &o) : hb_array_t<Type> (o) {}
+  hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
+  template <unsigned int length_> hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
+
+  hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
+  { return hb_sorted_array_t<Type> (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
+  hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
+  { return sub_array (start_offset, &seg_count); }
+
+  template <typename T>
+  Type *bsearch (const T &x, Type *not_found = nullptr)
+  {
+    unsigned int i;
+    return bfind (x, &i) ? &this->arrayZ[i] : not_found;
+  }
+  template <typename T>
+  const Type *bsearch (const T &x, const Type *not_found = nullptr) const
+  {
+    unsigned int i;
+    return bfind (x, &i) ? &this->arrayZ[i] : not_found;
+  }
+  template <typename T>
+  bool bfind (const T &x, unsigned int *i = nullptr,
+                     hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+                     unsigned int to_store = (unsigned int) -1) const
+  {
+    int min = 0, max = (int) this->length - 1;
+    const Type *array = this->arrayZ;
+    while (min <= max)
+    {
+      int mid = ((unsigned int) min + (unsigned int) max) / 2;
+      int c = array[mid].cmp (x);
+      if (c < 0)
+        max = mid - 1;
+      else if (c > 0)
+        min = mid + 1;
+      else
+      {
+        if (i)
+          *i = mid;
+        return true;
+      }
+    }
+    if (i)
+    {
+      switch (not_found)
+      {
+        case HB_BFIND_NOT_FOUND_DONT_STORE:
+          break;
+
+        case HB_BFIND_NOT_FOUND_STORE:
+          *i = to_store;
+          break;
+
+        case HB_BFIND_NOT_FOUND_STORE_CLOSEST:
+          if (max < 0 || (max < (int) this->length && array[max].cmp (x) > 0))
+            max++;
+          *i = max;
+          break;
+      }
+    }
+    return false;
+  }
+};
+template <typename T> inline hb_sorted_array_t<T>
+hb_sorted_array (T *array, unsigned int length)
+{ return hb_sorted_array_t<T> (array, length); }
+template <typename T, unsigned int length_> inline hb_sorted_array_t<T>
+hb_sorted_array (T (&array_)[length_])
+{ return hb_sorted_array_t<T> (array_); }
+
+
+typedef hb_array_t<const char> hb_bytes_t;
+typedef hb_array_t<const unsigned char> hb_ubytes_t;
+
+
+#endif /* HB_ARRAY_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-atomic-private.hh	Mon Feb 25 17:16:03 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-/*
- * Copyright © 2007  Chris Wilson
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Contributor(s):
- *      Chris Wilson <chris@chris-wilson.co.uk>
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_ATOMIC_PRIVATE_HH
-#define HB_ATOMIC_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-/* atomic_int */
-
-/* We need external help for these */
-
-#if defined(hb_atomic_int_impl_add) \
- && defined(hb_atomic_ptr_impl_get) \
- && defined(hb_atomic_ptr_impl_cmpexch)
-
-/* Defined externally, i.e. in config.h; must have typedef'ed hb_atomic_int_impl_t as well. */
-
-
-#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
-
-#include <windows.h>
-
-/* MinGW has a convoluted history of supporting MemoryBarrier
- * properly.  As such, define a function to wrap the whole
- * thing. */
-static inline void _HBMemoryBarrier (void) {
-#if !defined(MemoryBarrier)
-  long dummy = 0;
-  InterlockedExchange (&dummy, 1);
-#else
-  MemoryBarrier ();
-#endif
-}
-
-typedef LONG hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           InterlockedExchangeAdd (&(AI), (V))
-
-#define hb_atomic_ptr_impl_get(P)               (_HBMemoryBarrier (), (void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
-
-
-#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
-
-typedef int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           __sync_fetch_and_add (&(AI), (V))
-
-#define hb_atomic_ptr_impl_get(P)               (void *) (__sync_synchronize (), *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       __sync_bool_compare_and_swap ((P), (O), (N))
-
-
-#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
-
-#include <atomic.h>
-#include <mbarrier.h>
-
-typedef unsigned int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)               ( ({__machine_rw_barrier ();}), (void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false)
-
-
-#elif !defined(HB_NO_MT) && defined(__APPLE__)
-
-#include <libkern/OSAtomic.h>
-#ifdef __MAC_OS_X_MIN_REQUIRED
-#include <AvailabilityMacros.h>
-#elif defined(__IPHONE_OS_MIN_REQUIRED)
-#include <Availability.h>
-#endif
-
-
-typedef int32_t hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)               (OSMemoryBarrier (), (void *) *(P))
-#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
-#else
-#if __ppc64__ || __x86_64__ || __aarch64__
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       OSAtomicCompareAndSwap64Barrier ((int64_t) (void *) (O), (int64_t) (void *) (N), (int64_t*) (P))
-#else
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       OSAtomicCompareAndSwap32Barrier ((int32_t) (void *) (O), (int32_t) (void *) (N), (int32_t*) (P))
-#endif
-#endif
-
-
-#elif !defined(HB_NO_MT) && defined(_AIX) && defined(__IBMCPP__)
-
-#include <builtins.h>
-
-
-static inline int _hb_fetch_and_add(volatile int* AI, unsigned int V) {
-  __lwsync();
-  int result = __fetch_and_add(AI, V);
-  __isync();
-  return result;
-}
-static inline int _hb_compare_and_swaplp(volatile long* P, long O, long N) {
-  __sync();
-  int result = __compare_and_swaplp (P, &O, N);
-  __sync();
-  return result;
-}
-
-typedef int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           _hb_fetch_and_add (&(AI), (V))
-
-#define hb_atomic_ptr_impl_get(P)               (__sync(), (void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N))
-
-#elif !defined(HB_NO_MT)
-
-#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
-
-typedef volatile int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           (((AI) += (V)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)               ((void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       (* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false)
-
-
-#else /* HB_NO_MT */
-
-typedef int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           (((AI) += (V)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)               ((void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
-
-
-#endif
-
-
-#define HB_ATOMIC_INT_INIT(V)          {V}
-
-struct hb_atomic_int_t
-{
-  hb_atomic_int_impl_t v;
-
-  inline void set_unsafe (int v_) { v = v_; }
-  inline int get_unsafe (void) const { return v; }
-  inline int inc (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v),  1); }
-  inline int dec (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v), -1); }
-};
-
-
-#define hb_atomic_ptr_get(P) hb_atomic_ptr_impl_get(P)
-#define hb_atomic_ptr_cmpexch(P,O,N) hb_atomic_ptr_impl_cmpexch((P),(O),(N))
-
-
-#endif /* HB_ATOMIC_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-atomic.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,300 @@
+/*
+ * Copyright © 2007  Chris Wilson
+ * Copyright © 2009,2010  Red Hat, Inc.
+ * Copyright © 2011,2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Contributor(s):
+ *      Chris Wilson <chris@chris-wilson.co.uk>
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_ATOMIC_HH
+#define HB_ATOMIC_HH
+
+#include "hb.hh"
+
+
+/*
+ * Atomic integers and pointers.
+ */
+
+
+/* We need external help for these */
+
+#if defined(hb_atomic_int_impl_add) \
+ && defined(hb_atomic_ptr_impl_get) \
+ && defined(hb_atomic_ptr_impl_cmpexch)
+
+/* Defined externally, i.e. in config.h. */
+
+
+#elif !defined(HB_NO_MT) && defined(__ATOMIC_ACQUIRE)
+
+/* C++11-style GCC primitives. */
+
+#define _hb_memory_barrier()                    __sync_synchronize ()
+
+#define hb_atomic_int_impl_add(AI, V)           __atomic_fetch_add ((AI), (V), __ATOMIC_ACQ_REL)
+#define hb_atomic_int_impl_set_relaxed(AI, V)   __atomic_store_n ((AI), (V), __ATOMIC_RELAXED)
+#define hb_atomic_int_impl_set(AI, V)           __atomic_store_n ((AI), (V), __ATOMIC_RELEASE)
+#define hb_atomic_int_impl_get_relaxed(AI)      __atomic_load_n ((AI), __ATOMIC_RELAXED)
+#define hb_atomic_int_impl_get(AI)              __atomic_load_n ((AI), __ATOMIC_ACQUIRE)
+
+#define hb_atomic_ptr_impl_set_relaxed(P, V)    __atomic_store_n ((P), (V), __ATOMIC_RELAXED)
+#define hb_atomic_ptr_impl_get_relaxed(P)       __atomic_load_n ((P), __ATOMIC_RELAXED)
+#define hb_atomic_ptr_impl_get(P)               __atomic_load_n ((P), __ATOMIC_ACQUIRE)
+static inline bool
+_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
+{
+  const void *O = O_; // Need lvalue
+  return __atomic_compare_exchange_n ((void **) P, (void **) &O, (void *) N, true, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
+
+#elif !defined(HB_NO_MT) && __cplusplus >= 201103L
+
+/* C++11 atomics. */
+
+#include <atomic>
+
+#define _hb_memory_barrier()                    std::atomic_thread_fence(std::memory_order_ack_rel)
+#define _hb_memory_r_barrier()                  std::atomic_thread_fence(std::memory_order_acquire)
+#define _hb_memory_w_barrier()                  std::atomic_thread_fence(std::memory_order_release)
+
+#define hb_atomic_int_impl_add(AI, V)           (reinterpret_cast<std::atomic<int> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
+#define hb_atomic_int_impl_set_relaxed(AI, V)   (reinterpret_cast<std::atomic<int> *> (AI)->store ((V), std::memory_order_relaxed))
+#define hb_atomic_int_impl_set(AI, V)           (reinterpret_cast<std::atomic<int> *> (AI)->store ((V), std::memory_order_release))
+#define hb_atomic_int_impl_get_relaxed(AI)      (reinterpret_cast<std::atomic<int> *> (AI)->load (std::memory_order_relaxed))
+#define hb_atomic_int_impl_get(AI)              (reinterpret_cast<std::atomic<int> *> (AI)->load (std::memory_order_acquire))
+
+#define hb_atomic_ptr_impl_set_relaxed(P, V)    (reinterpret_cast<std::atomic<void*> *> (P)->store ((V), std::memory_order_relaxed))
+#define hb_atomic_ptr_impl_get_relaxed(P)       (reinterpret_cast<std::atomic<void*> *> (P)->load (std::memory_order_relaxed))
+#define hb_atomic_ptr_impl_get(P)               (reinterpret_cast<std::atomic<void*> *> (P)->load (std::memory_order_acquire))
+static inline bool
+_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
+{
+  const void *O = O_; // Need lvalue
+  return reinterpret_cast<std::atomic<const void*> *> (P)->compare_exchange_weak (O, N, std::memory_order_acq_rel, std::memory_order_relaxed);
+}
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
+
+
+#elif !defined(HB_NO_MT) && defined(_WIN32)
+
+#include <windows.h>
+
+static inline void _hb_memory_barrier ()
+{
+#if !defined(MemoryBarrier)
+  /* MinGW has a convoluted history of supporting MemoryBarrier. */
+  LONG dummy = 0;
+  InterlockedExchange (&dummy, 1);
+#else
+  MemoryBarrier ();
+#endif
+}
+#define _hb_memory_barrier()                    _hb_memory_barrier ()
+
+#define hb_atomic_int_impl_add(AI, V)           InterlockedExchangeAdd ((LONG *) (AI), (V))
+static_assert ((sizeof (LONG) == sizeof (int)), "");
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       (InterlockedCompareExchangePointer ((P), (N), (O)) == (O))
+
+
+#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
+
+#define _hb_memory_barrier()                    __sync_synchronize ()
+
+#define hb_atomic_int_impl_add(AI, V)           __sync_fetch_and_add ((AI), (V))
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       __sync_bool_compare_and_swap ((P), (O), (N))
+
+
+#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
+
+#include <atomic.h>
+#include <mbarrier.h>
+
+#define _hb_memory_r_barrier()                  __machine_r_barrier ()
+#define _hb_memory_w_barrier()                  __machine_w_barrier ()
+#define _hb_memory_barrier()                    __machine_rw_barrier ()
+
+static inline int _hb_fetch_and_add (int *AI, int V)
+{
+  _hb_memory_w_barrier ();
+  int result = atomic_add_int_nv ((uint_t *) AI, V) - V;
+  _hb_memory_r_barrier ();
+  return result;
+}
+static inline bool _hb_compare_and_swap_ptr (void **P, void *O, void *N)
+{
+  _hb_memory_w_barrier ();
+  bool result = atomic_cas_ptr (P, O, N) == O;
+  _hb_memory_r_barrier ();
+  return result;
+}
+
+#define hb_atomic_int_impl_add(AI, V)           _hb_fetch_and_add ((AI), (V))
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_compare_and_swap_ptr ((P), (O), (N))
+
+
+#elif !defined(HB_NO_MT) && defined(__APPLE__)
+
+#include <libkern/OSAtomic.h>
+#ifdef __MAC_OS_X_MIN_REQUIRED
+#include <AvailabilityMacros.h>
+#elif defined(__IPHONE_OS_MIN_REQUIRED)
+#include <Availability.h>
+#endif
+
+#define _hb_memory_barrier()                    OSMemoryBarrier ()
+
+#define hb_atomic_int_impl_add(AI, V)           (OSAtomicAdd32Barrier ((V), (AI)) - (V))
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       OSAtomicCompareAndSwapPtrBarrier ((O), (N), (P))
+#else
+#if __ppc64__ || __x86_64__ || __aarch64__
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P))
+#else
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P))
+#endif
+#endif
+
+
+#elif !defined(HB_NO_MT) && defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__))
+
+#include <builtins.h>
+
+#define _hb_memory_barrier()                    __lwsync ()
+
+static inline int _hb_fetch_and_add (int *AI, int V)
+{
+  _hb_memory_barrier ();
+  int result = __fetch_and_add (AI, V);
+  _hb_memory_barrier ();
+  return result;
+}
+static inline bool _hb_compare_and_swaplp (long *P, long O, long N)
+{
+  _hb_memory_barrier ();
+  bool result = __compare_and_swaplp (P, &O, N);
+  _hb_memory_barrier ();
+  return result;
+}
+
+#define hb_atomic_int_impl_add(AI, V)           _hb_fetch_and_add ((AI), (V))
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_compare_and_swaplp ((long *) (P), (long) (O), (long) (N))
+static_assert ((sizeof (long) == sizeof (void *)), "");
+
+
+#elif !defined(HB_NO_MT)
+
+#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
+
+#define _hb_memory_barrier()
+
+#define hb_atomic_int_impl_add(AI, V)           ((*(AI) += (V)) - (V))
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
+
+
+#else /* HB_NO_MT */
+
+#define hb_atomic_int_impl_add(AI, V)           ((*(AI) += (V)) - (V))
+
+#define _hb_memory_barrier()
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
+
+
+#endif
+
+
+#ifndef _hb_memory_r_barrier
+#define _hb_memory_r_barrier()                  _hb_memory_barrier ()
+#endif
+#ifndef _hb_memory_w_barrier
+#define _hb_memory_w_barrier()                  _hb_memory_barrier ()
+#endif
+#ifndef hb_atomic_int_impl_set_relaxed
+#define hb_atomic_int_impl_set_relaxed(AI, V)   (*(AI) = (V))
+#endif
+#ifndef hb_atomic_int_impl_get_relaxed
+#define hb_atomic_int_impl_get_relaxed(AI)      (*(AI))
+#endif
+
+#ifndef hb_atomic_ptr_impl_set_relaxed
+#define hb_atomic_ptr_impl_set_relaxed(P, V)    (*(P) = (V))
+#endif
+#ifndef hb_atomic_ptr_impl_get_relaxed
+#define hb_atomic_ptr_impl_get_relaxed(P)       (*(P))
+#endif
+#ifndef hb_atomic_int_impl_set
+inline void hb_atomic_int_impl_set (int *AI, int v)     { _hb_memory_w_barrier (); *AI = v; }
+#endif
+#ifndef hb_atomic_int_impl_get
+inline int hb_atomic_int_impl_get (const int *AI)       { int v = *AI; _hb_memory_r_barrier (); return v; }
+#endif
+#ifndef hb_atomic_ptr_impl_get
+inline void *hb_atomic_ptr_impl_get (void ** const P)   { void *v = *P; _hb_memory_r_barrier (); return v; }
+#endif
+
+
+#define HB_ATOMIC_INT_INIT(V)          {V}
+struct hb_atomic_int_t
+{
+  void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
+  void set (int v_) { hb_atomic_int_impl_set (&v, v_); }
+  int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
+  int get () const { return hb_atomic_int_impl_get (&v); }
+  int inc () { return hb_atomic_int_impl_add (&v,  1); }
+  int dec () { return hb_atomic_int_impl_add (&v, -1); }
+
+  int v;
+};
+
+
+#define HB_ATOMIC_PTR_INIT(V)          {V}
+template <typename P>
+struct hb_atomic_ptr_t
+{
+  typedef typename hb_remove_pointer (P) T;
+
+  void init (T* v_ = nullptr) { set_relaxed (v_); }
+  void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
+  T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); }
+  T *get () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); }
+  bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
+
+  T * operator -> () const                    { return get (); }
+  template <typename C> operator C * () const { return get (); }
+
+  T *v;
+};
+
+
+#endif /* HB_ATOMIC_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob-private.hh	Mon Feb 25 17:16:03 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_BLOB_PRIVATE_HH
-#define HB_BLOB_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-object-private.hh"
-
-
-/*
- * hb_blob_t
- */
-
-struct hb_blob_t
-{
-  inline void fini_shallow (void)
-  {
-    destroy_user_data ();
-  }
-
-  inline void destroy_user_data (void)
-  {
-    if (destroy)
-    {
-      destroy (user_data);
-      user_data = nullptr;
-      destroy = nullptr;
-    }
-  }
-
-  HB_INTERNAL bool try_make_writable (void);
-  HB_INTERNAL bool try_make_writable_inplace (void);
-  HB_INTERNAL bool try_make_writable_inplace_unix (void);
-
-  inline void lock (void)
-  {
-    hb_blob_make_immutable (this);
-  }
-
-  template <typename Type>
-  inline const Type* as (void) const
-  {
-    return unlikely (!data) ? &Null(Type) : reinterpret_cast<const Type *> (data);
-  }
-
-  public:
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  bool immutable;
-
-  const char *data;
-  unsigned int length;
-  hb_memory_mode_t mode;
-
-  void *user_data;
-  hb_destroy_func_t destroy;
-};
-
-
-#endif /* HB_BLOB_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.cc	Mon Feb 25 17:16:03 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.cc	Sun Mar 10 03:34:59 2019 -0700
@@ -25,14 +25,20 @@
  * Red Hat Author(s): Behdad Esfahbod
  */
 
-/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */
+
+/* https://github.com/harfbuzz/harfbuzz/issues/1308
+ * http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
+ * https://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html
+ */
 #ifndef _POSIX_C_SOURCE
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
 #define _POSIX_C_SOURCE 200809L
+#pragma GCC diagnostic pop
 #endif
 
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-blob-private.hh"
+#include "hb.hh"
+#include "hb-blob.hh"
 
 #ifdef HAVE_SYS_MMAN_H
 #ifdef HAVE_UNISTD_H
@@ -47,6 +53,19 @@
 
 
 /**
+ * SECTION: hb-blob
+ * @title: hb-blob
+ * @short_description: Binary data containers
+ * @include: hb.h
+ *
+ * Blobs wrap a chunk of binary data to handle lifecycle management of data
+ * while it is passed between client and HarfBuzz.  Blobs are primarily used
+ * to create font faces, but also to access font face tables, as well as
+ * pass around other binary data.
+ **/
+
+
+/**
  * hb_blob_create: (skip)
  * @data: Pointer to blob data.
  * @length: Length of @data in bytes.
@@ -130,7 +149,7 @@
 {
   hb_blob_t *blob;
 
-  if (!length || offset >= parent->length)
+  if (!length || !parent || offset >= parent->length)
     return hb_blob_get_empty ();
 
   hb_blob_make_immutable (parent);
@@ -181,22 +200,9 @@
  * Since: 0.9.2
  **/
 hb_blob_t *
-hb_blob_get_empty (void)
+hb_blob_get_empty ()
 {
-  static const hb_blob_t _hb_blob_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* immutable */
-
-    nullptr, /* data */
-    0, /* length */
-    HB_MEMORY_MODE_READONLY, /* mode */
-
-    nullptr, /* user_data */
-    nullptr  /* destroy */
-  };
-
-  return const_cast<hb_blob_t *> (&_hb_blob_nil);
+  return const_cast<hb_blob_t *> (&Null(hb_blob_t));
 }
 
 /**
@@ -291,10 +297,10 @@
 void
 hb_blob_make_immutable (hb_blob_t *blob)
 {
-  if (hb_object_is_inert (blob))
+  if (hb_object_is_immutable (blob))
     return;
 
-  blob->immutable = true;
+  hb_object_make_immutable (blob);
 }
 
 /**
@@ -310,7 +316,7 @@
 hb_bool_t
 hb_blob_is_immutable (hb_blob_t *blob)
 {
-  return blob->immutable;
+  return hb_object_is_immutable (blob);
 }
 
 
@@ -384,7 +390,7 @@
 
 
 bool
-hb_blob_t::try_make_writable_inplace_unix (void)
+hb_blob_t::try_make_writable_inplace_unix ()
 {
 #if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT)
   uintptr_t pagesize = -1, mask, length;
@@ -427,7 +433,7 @@
 }
 
 bool
-hb_blob_t::try_make_writable_inplace (void)
+hb_blob_t::try_make_writable_inplace ()
 {
   DEBUG_MSG_FUNC (BLOB, this, "making writable inplace\n");
 
@@ -442,9 +448,9 @@
 }
 
 bool
-hb_blob_t::try_make_writable (void)
+hb_blob_t::try_make_writable ()
 {
-  if (this->immutable)
+  if (hb_object_is_immutable (this))
     return false;
 
   if (this->mode == HB_MEMORY_MODE_WRITABLE)
@@ -487,11 +493,11 @@
 # include <fcntl.h>
 #endif
 
-#if defined(_WIN32) || defined(__CYGWIN__)
+#ifdef _WIN32
 # include <windows.h>
 #else
-# ifndef _O_BINARY
-#  define _O_BINARY 0
+# ifndef O_BINARY
+#  define O_BINARY 0
 # endif
 #endif
 
@@ -503,17 +509,19 @@
 {
   char *contents;
   unsigned long length;
-#if defined(_WIN32) || defined(__CYGWIN__)
+#ifdef _WIN32
   HANDLE mapping;
 #endif
 };
 
+#if (defined(HAVE_MMAP) || defined(_WIN32)) && !defined(HB_NO_MMAP)
 static void
-_hb_mapped_file_destroy (hb_mapped_file_t *file)
+_hb_mapped_file_destroy (void *file_)
 {
+  hb_mapped_file_t *file = (hb_mapped_file_t *) file_;
 #ifdef HAVE_MMAP
   munmap (file->contents, file->length);
-#elif defined(_WIN32) || defined(__CYGWIN__)
+#elif defined(_WIN32)
   UnmapViewOfFile (file->contents);
   CloseHandle (file->mapping);
 #else
@@ -522,6 +530,7 @@
 
   free (file);
 }
+#endif
 
 /**
  * hb_blob_create_from_file:
@@ -540,7 +549,7 @@
   hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
   if (unlikely (!file)) return hb_blob_get_empty ();
 
-  int fd = open (file_name, O_RDONLY | _O_BINARY, 0);
+  int fd = open (file_name, O_RDONLY | O_BINARY, 0);
   if (unlikely (fd == -1)) goto fail_without_close;
 
   struct stat st;
@@ -563,21 +572,54 @@
 fail_without_close:
   free (file);
 
-#elif (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_MMAP)
+#elif defined(_WIN32) && !defined(HB_NO_MMAP)
   hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
   if (unlikely (!file)) return hb_blob_get_empty ();
 
-  HANDLE fd = CreateFile (file_name, GENERIC_READ, FILE_SHARE_READ, nullptr,
-                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
-                          nullptr);
+  HANDLE fd;
+  unsigned int size = strlen (file_name) + 1;
+  wchar_t * wchar_file_name = (wchar_t *) malloc (sizeof (wchar_t) * size);
+  if (unlikely (wchar_file_name == nullptr)) goto fail_without_close;
+  mbstowcs (wchar_file_name, file_name, size);
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+  {
+    CREATEFILE2_EXTENDED_PARAMETERS ceparams = { 0 };
+    ceparams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
+    ceparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0xFFFF;
+    ceparams.dwFileFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0xFFF00000;
+    ceparams.dwSecurityQosFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0x000F0000;
+    ceparams.lpSecurityAttributes = nullptr;
+    ceparams.hTemplateFile = nullptr;
+    fd = CreateFile2 (wchar_file_name, GENERIC_READ, FILE_SHARE_READ,
+                      OPEN_EXISTING, &ceparams);
+  }
+#else
+  fd = CreateFileW (wchar_file_name, GENERIC_READ, FILE_SHARE_READ, nullptr,
+                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
+                    nullptr);
+#endif
+  free (wchar_file_name);
 
   if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close;
 
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+  {
+    LARGE_INTEGER length;
+    GetFileSizeEx (fd, &length);
+    file->length = length.LowPart;
+    file->mapping = CreateFileMappingFromApp (fd, nullptr, PAGE_READONLY, length.QuadPart, nullptr);
+  }
+#else
   file->length = (unsigned long) GetFileSize (fd, nullptr);
   file->mapping = CreateFileMapping (fd, nullptr, PAGE_READONLY, 0, 0, nullptr);
+#endif
   if (unlikely (file->mapping == nullptr)) goto fail;
 
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+  file->contents = (char *) MapViewOfFileFromApp (file->mapping, FILE_MAP_READ, 0, 0);
+#else
   file->contents = (char *) MapViewOfFile (file->mapping, FILE_MAP_READ, 0, 0, 0);
+#endif
   if (unlikely (file->contents == nullptr)) goto fail;
 
   CloseHandle (fd);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,101 @@
+/*
+ * Copyright © 2009  Red Hat, Inc.
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_BLOB_HH
+#define HB_BLOB_HH
+
+#include "hb.hh"
+
+
+/*
+ * hb_blob_t
+ */
+
+struct hb_blob_t
+{
+  void fini_shallow () { destroy_user_data (); }
+
+  void destroy_user_data ()
+  {
+    if (destroy)
+    {
+      destroy (user_data);
+      user_data = nullptr;
+      destroy = nullptr;
+    }
+  }
+
+  HB_INTERNAL bool try_make_writable ();
+  HB_INTERNAL bool try_make_writable_inplace ();
+  HB_INTERNAL bool try_make_writable_inplace_unix ();
+
+  template <typename Type>
+  const Type* as () const
+  {
+    return length < hb_null_size (Type) ? &Null(Type) : reinterpret_cast<const Type *> (data);
+  }
+  hb_bytes_t as_bytes () const
+  { return hb_bytes_t (data, length); }
+
+  public:
+  hb_object_header_t header;
+
+  const char *data;
+  unsigned int length;
+  hb_memory_mode_t mode;
+
+  void *user_data;
+  hb_destroy_func_t destroy;
+};
+
+
+/*
+ * hb_blob_ptr_t
+ */
+
+template <typename P>
+struct hb_blob_ptr_t
+{
+  typedef typename hb_remove_pointer (P) T;
+
+  hb_blob_ptr_t (hb_blob_t *b_ = nullptr) : b (b_) {}
+  hb_blob_t * operator = (hb_blob_t *b_) { return b = b_; }
+  const T * operator -> () const { return get (); }
+  const T & operator * () const  { return *get (); }
+  template <typename C> operator const C * () const { return get (); }
+  operator const char * () const { return (const char *) get (); }
+  const T * get () const { return b->as<T> (); }
+  hb_blob_t * get_blob () const { return b.get_raw (); }
+  unsigned int get_length () const { return b.get ()->length; }
+  void destroy () { hb_blob_destroy (b.get ()); b = nullptr; }
+
+  hb_nonnull_ptr_t<hb_blob_t> b;
+};
+
+
+#endif /* HB_BLOB_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-json.hh	Mon Feb 25 17:16:03 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-json.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -29,7 +29,7 @@
 #ifndef HB_BUFFER_DESERIALIZE_JSON_HH
 #define HB_BUFFER_DESERIALIZE_JSON_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-buffer-deserialize-json.hh"
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-text.hh	Mon Feb 25 17:16:03 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-text.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -29,7 +29,7 @@
 #ifndef HB_BUFFER_DESERIALIZE_TEXT_HH
 #define HB_BUFFER_DESERIALIZE_TEXT_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-buffer-deserialize-text.hh"
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-private.hh	Mon Feb 25 17:16:03 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,388 +0,0 @@
-/*
- * Copyright © 1998-2004  David Turner and Werner Lemberg
- * Copyright © 2004,2007,2009,2010  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_BUFFER_PRIVATE_HH
-#define HB_BUFFER_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-#include "hb-unicode-private.hh"
-
-
-#ifndef HB_BUFFER_MAX_LEN_FACTOR
-#define HB_BUFFER_MAX_LEN_FACTOR 32
-#endif
-#ifndef HB_BUFFER_MAX_LEN_MIN
-#define HB_BUFFER_MAX_LEN_MIN 8192
-#endif
-#ifndef HB_BUFFER_MAX_LEN_DEFAULT
-#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
-#endif
-
-#ifndef HB_BUFFER_MAX_OPS_FACTOR
-#define HB_BUFFER_MAX_OPS_FACTOR 64
-#endif
-#ifndef HB_BUFFER_MAX_OPS_MIN
-#define HB_BUFFER_MAX_OPS_MIN 1024
-#endif
-#ifndef HB_BUFFER_MAX_OPS_DEFAULT
-#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */
-#endif
-
-static_assert ((sizeof (hb_glyph_info_t) == 20), "");
-static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
-
-HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
-HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
-HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
-
-enum hb_buffer_scratch_flags_t {
-  HB_BUFFER_SCRATCH_FLAG_DEFAULT                        = 0x00000000u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII                  = 0x00000001u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES         = 0x00000002u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK             = 0x00000004u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT            = 0x00000008u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK            = 0x00000010u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_CGJ                        = 0x00000020u,
-
-  /* Reserved for complex shapers' internal use. */
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX0                       = 0x01000000u,
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX1                       = 0x02000000u,
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX2                       = 0x04000000u,
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX3                       = 0x08000000u,
-};
-HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
-
-
-/*
- * hb_buffer_t
- */
-
-struct hb_buffer_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  /* Information about how the text in the buffer should be treated */
-  hb_unicode_funcs_t *unicode; /* Unicode functions */
-  hb_buffer_flags_t flags; /* BOT / EOT / etc. */
-  hb_buffer_cluster_level_t cluster_level;
-  hb_codepoint_t replacement; /* U+FFFD or something else. */
-  hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
-  unsigned int max_len; /* Maximum allowed len. */
-  int max_ops; /* Maximum allowed operations. */
-
-  /* Buffer contents */
-  hb_buffer_content_type_t content_type;
-  hb_segment_properties_t props; /* Script, language, direction */
-
-  bool successful; /* Allocations successful */
-  bool have_output; /* Whether we have an output buffer going on */
-  bool have_positions; /* Whether we have positions */
-
-  unsigned int idx; /* Cursor into ->info and ->pos arrays */
-  unsigned int len; /* Length of ->info and ->pos arrays */
-  unsigned int out_len; /* Length of ->out array if have_output */
-
-  unsigned int allocated; /* Length of allocated arrays */
-  hb_glyph_info_t     *info;
-  hb_glyph_info_t     *out_info;
-  hb_glyph_position_t *pos;
-
-  unsigned int serial;
-
-  /* Text before / after the main buffer contents.
-   * Always in Unicode, and ordered outward.
-   * Index 0 is for "pre-context", 1 for "post-context". */
-  static const unsigned int CONTEXT_LENGTH = 5;
-  hb_codepoint_t context[2][CONTEXT_LENGTH];
-  unsigned int context_len[2];
-
-  /* Debugging API */
-  hb_buffer_message_func_t message_func;
-  void *message_data;
-  hb_destroy_func_t message_destroy;
-
-  /* Internal debugging. */
-  /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
-#ifndef HB_NDEBUG
-  uint8_t allocated_var_bits;
-#endif
-
-
-  /* Methods */
-
-  inline void allocate_var (unsigned int start, unsigned int count)
-  {
-#ifndef HB_NDEBUG
-    unsigned int end = start + count;
-    assert (end <= 8);
-    unsigned int bits = (1u<<end) - (1u<<start);
-    assert (0 == (allocated_var_bits & bits));
-    allocated_var_bits |= bits;
-#endif
-  }
-  inline void deallocate_var (unsigned int start, unsigned int count)
-  {
-#ifndef HB_NDEBUG
-    unsigned int end = start + count;
-    assert (end <= 8);
-    unsigned int bits = (1u<<end) - (1u<<start);
-    assert (bits == (allocated_var_bits & bits));
-    allocated_var_bits &= ~bits;
-#endif
-  }
-  inline void assert_var (unsigned int start, unsigned int count)
-  {
-#ifndef HB_NDEBUG
-    unsigned int end = start + count;
-    assert (end <= 8);
-    unsigned int bits = (1u<<end) - (1u<<start);
-    assert (bits == (allocated_var_bits & bits));
-#endif
-  }
-  inline void deallocate_var_all (void)
-  {
-#ifndef HB_NDEBUG
-    allocated_var_bits = 0;
-#endif
-  }
-
-  inline hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
-  inline hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
-
-  inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
-  inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
-
-  inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; }
-  inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; }
-
-  inline bool has_separate_output (void) const { return info != out_info; }
-
-
-  HB_INTERNAL void reset (void);
-  HB_INTERNAL void clear (void);
-
-  inline unsigned int backtrack_len (void) const
-  { return have_output? out_len : idx; }
-  inline unsigned int lookahead_len (void) const
-  { return len - idx; }
-  inline unsigned int next_serial (void) { return serial++; }
-
-  HB_INTERNAL void add (hb_codepoint_t  codepoint,
-                        unsigned int    cluster);
-  HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
-
-  HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
-  HB_INTERNAL void reverse (void);
-  HB_INTERNAL void reverse_clusters (void);
-  HB_INTERNAL void guess_segment_properties (void);
-
-  HB_INTERNAL void swap_buffers (void);
-  HB_INTERNAL void remove_output (void);
-  HB_INTERNAL void clear_output (void);
-  HB_INTERNAL void clear_positions (void);
-
-  HB_INTERNAL void replace_glyphs (unsigned int num_in,
-                                   unsigned int num_out,
-                                   const hb_codepoint_t *glyph_data);
-
-  HB_INTERNAL void replace_glyph (hb_codepoint_t glyph_index);
-  /* Makes a copy of the glyph at idx to output and replace glyph_index */
-  HB_INTERNAL void output_glyph (hb_codepoint_t glyph_index);
-  HB_INTERNAL void output_info (const hb_glyph_info_t &glyph_info);
-  /* Copies glyph at idx to output but doesn't advance idx */
-  HB_INTERNAL void copy_glyph (void);
-  HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */
-  /* Copies glyph at idx to output and advance idx.
-   * If there's no output, just advance idx. */
-  inline void
-  next_glyph (void)
-  {
-    if (have_output)
-    {
-      if (unlikely (out_info != info || out_len != idx)) {
-        if (unlikely (!make_room_for (1, 1))) return;
-        out_info[out_len] = info[idx];
-      }
-      out_len++;
-    }
-
-    idx++;
-  }
-
-  /* Advance idx without copying to output. */
-  inline void skip_glyph (void) { idx++; }
-
-  inline void reset_masks (hb_mask_t mask)
-  {
-    for (unsigned int j = 0; j < len; j++)
-      info[j].mask = mask;
-  }
-  inline void add_masks (hb_mask_t mask)
-  {
-    for (unsigned int j = 0; j < len; j++)
-      info[j].mask |= mask;
-  }
-  HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask,
-                              unsigned int cluster_start, unsigned int cluster_end);
-
-  inline void merge_clusters (unsigned int start, unsigned int end)
-  {
-    if (end - start < 2)
-      return;
-    merge_clusters_impl (start, end);
-  }
-  HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end);
-  HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
-  /* Merge clusters for deleting current glyph, and skip it. */
-  HB_INTERNAL void delete_glyph (void);
-
-  inline void unsafe_to_break (unsigned int start,
-                               unsigned int end)
-  {
-    if (end - start < 2)
-      return;
-    unsafe_to_break_impl (start, end);
-  }
-  HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
-  HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);
-
-
-  /* Internal methods */
-  HB_INTERNAL bool enlarge (unsigned int size);
-
-  inline bool ensure (unsigned int size)
-  { return likely (!size || size < allocated) ? true : enlarge (size); }
-
-  inline bool ensure_inplace (unsigned int size)
-  { return likely (!size || size < allocated); }
-
-  HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
-  HB_INTERNAL bool shift_forward (unsigned int count);
-
-  typedef long scratch_buffer_t;
-  HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);
-
-  inline 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 *));
-
-  inline bool messaging (void) { return unlikely (message_func); }
-  inline bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
-  {
-    if (!messaging ())
-      return true;
-    va_list ap;
-    va_start (ap, fmt);
-    bool ret = message_impl (font, fmt, ap);
-    va_end (ap);
-    return ret;
-  }
-  HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
-
-  static inline void
-  set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
-  {
-    if (inf.cluster != cluster)
-    {
-      if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
-        inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-      else
-        inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-    }
-    inf.cluster = cluster;
-  }
-
-  inline int
-  _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
-                                     unsigned int start, unsigned int end,
-                                     unsigned int cluster) const
-  {
-    for (unsigned int i = start; i < end; i++)
-      cluster = MIN<unsigned int> (cluster, infos[i].cluster);
-    return cluster;
-  }
-  inline void
-  _unsafe_to_break_set_mask (hb_glyph_info_t *infos,
-                             unsigned int start, unsigned int end,
-                             unsigned int cluster)
-  {
-    for (unsigned int i = start; i < end; i++)
-      if (cluster != infos[i].cluster)
-      {
-        scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
-        infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-      }
-  }
-
-  inline void
-  unsafe_to_break_all (void)
-  {
-    unsafe_to_break_impl (0, len);
-  }
-  inline void
-  safe_to_break_all (void)
-  {
-    for (unsigned int i = 0; i < len; i++)
-      info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-  }
-};
-
-
-/* Loop over clusters. Duplicated in foreach_syllable(). */
-#define foreach_cluster(buffer, start, end) \
-  for (unsigned int \
-       _count = buffer->len, \
-       start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
-       start < _count; \
-       start = end, end = _next_cluster (buffer, start))
-
-static inline unsigned int
-_next_cluster (hb_buffer_t *buffer, unsigned int start)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  unsigned int cluster = info[start].cluster;
-  while (++start < count && cluster == info[start].cluster)
-    ;
-
-  return start;
-}
-
-
-#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
-  b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
-           sizeof (b->info[0].var))
-#define HB_BUFFER_ALLOCATE_VAR(b, var)          HB_BUFFER_XALLOCATE_VAR (b, allocate_var,   var ())
-#define HB_BUFFER_DEALLOCATE_VAR(b, var)        HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
-#define HB_BUFFER_ASSERT_VAR(b, var)            HB_BUFFER_XALLOCATE_VAR (b, assert_var,     var ())
-
-
-#endif /* HB_BUFFER_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-serialize.cc	Mon Feb 25 17:16:03 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-serialize.cc	Sun Mar 10 03:34:59 2019 -0700
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-buffer-private.hh"
+#include "hb-buffer.hh"
 
 
 static const char *serialize_formats[] = {
@@ -44,7 +44,7 @@
  * Since: 0.9.7
  **/
 const char **
-hb_buffer_serialize_list_formats (void)
+hb_buffer_serialize_list_formats ()
 {
   return serialize_formats;
 }
@@ -246,7 +246,7 @@
 
     if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
     {
-      if (info[i].mask &HB_GLYPH_FLAG_DEFINED)
+      if (info[i].mask & HB_GLYPH_FLAG_DEFINED)
         p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED));
     }
 
@@ -440,8 +440,8 @@
 hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
                               const char *buf,
                               int buf_len, /* -1 means nul-terminated */
-                              const char **end_ptr, /* May be nullptr */
-                              hb_font_t *font, /* May be nullptr */
+                              const char **end_ptr, /* May be NULL */
+                              hb_font_t *font, /* May be NULL */
                               hb_buffer_serialize_format_t format)
 {
   const char *end;
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.cc	Mon Feb 25 17:16:03 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.cc	Sun Mar 10 03:34:59 2019 -0700
@@ -27,20 +27,21 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-buffer-private.hh"
-#include "hb-utf-private.hh"
+#include "hb-buffer.hh"
+#include "hb-utf.hh"
 
 
 /**
  * SECTION: hb-buffer
- * @title: Buffers
+ * @title: hb-buffer
  * @short_description: Input and output buffers
  * @include: hb.h
  *
  * Buffers serve dual role in HarfBuzz; they hold the input characters that are
- * passed hb_shape(), and after shaping they hold the output glyphs.
+ * passed to hb_shape(), and after shaping they hold the output glyphs.
  **/
 
+
 /**
  * hb_segment_properties_equal:
  * @a: first #hb_segment_properties_t to compare.
@@ -124,14 +125,14 @@
   hb_glyph_info_t *new_info = nullptr;
   bool separate_out = out_info != info;
 
-  if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
+  if (unlikely (hb_unsigned_mul_overflows (size, sizeof (info[0]))))
     goto done;
 
   while (size >= new_allocated)
     new_allocated += (new_allocated >> 1) + 32;
 
   static_assert ((sizeof (info[0]) == sizeof (pos[0])), "");
-  if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0]))))
+  if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]))))
     goto done;
 
   new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0]));
@@ -182,7 +183,11 @@
   if (idx + count > len)
   {
     /* Under memory failure we might expose this area.  At least
-     * clean it up.  Oh well... */
+     * clean it up.  Oh well...
+     *
+     * Ideally, we should at least set Default_Ignorable bits on
+     * these, as well as consistent cluster values.  But the former
+     * is layering violation... */
     memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
   }
   len += count;
@@ -210,23 +215,24 @@
 /* HarfBuzz-Internal API */
 
 void
-hb_buffer_t::reset (void)
+hb_buffer_t::reset ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   hb_unicode_funcs_destroy (unicode);
-  unicode = hb_unicode_funcs_get_default ();
+  unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ());
   flags = HB_BUFFER_FLAG_DEFAULT;
   replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
+  invisible = 0;
 
   clear ();
 }
 
 void
-hb_buffer_t::clear (void)
+hb_buffer_t::clear ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
@@ -281,9 +287,9 @@
 
 
 void
-hb_buffer_t::remove_output (void)
+hb_buffer_t::remove_output ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   have_output = false;
@@ -294,9 +300,9 @@
 }
 
 void
-hb_buffer_t::clear_output (void)
+hb_buffer_t::clear_output ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   have_output = true;
@@ -307,9 +313,9 @@
 }
 
 void
-hb_buffer_t::clear_positions (void)
+hb_buffer_t::clear_positions ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   have_output = false;
@@ -322,7 +328,7 @@
 }
 
 void
-hb_buffer_t::swap_buffers (void)
+hb_buffer_t::swap_buffers ()
 {
   if (unlikely (!successful)) return;
 
@@ -354,6 +360,8 @@
 {
   if (unlikely (!make_room_for (num_in, num_out))) return;
 
+  assert (idx + num_in <= len);
+
   merge_clusters (idx, idx + num_in);
 
   hb_glyph_info_t orig_info = info[idx];
@@ -369,37 +377,6 @@
   out_len += num_out;
 }
 
-void
-hb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = info[idx];
-  out_info[out_len].codepoint = glyph_index;
-
-  out_len++;
-}
-
-void
-hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = glyph_info;
-
-  out_len++;
-}
-
-void
-hb_buffer_t::copy_glyph (void)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = info[idx];
-
-  out_len++;
-}
-
 bool
 hb_buffer_t::move_to (unsigned int i)
 {
@@ -429,8 +406,14 @@
     unsigned int count = out_len - i;
 
     /* This will blow in our face if memory allocation fails later
-     * in this same lookup... */
-    if (unlikely (idx < count && !shift_forward (count + 32))) return false;
+     * in this same lookup...
+     *
+     * We used to shift with extra 32 items, instead of the 0 below.
+     * But that would leave empty slots in the buffer in case of allocation
+     * failures.  Setting to zero for now to avoid other problems (see
+     * comments in shift_forward().  This can cause O(N^2) behavior more
+     * severely than adding 32 empty slots can... */
+    if (unlikely (idx < count && !shift_forward (count + 0))) return false;
 
     assert (idx >= count);
 
@@ -442,19 +425,6 @@
   return true;
 }
 
-void
-hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
-{
-  if (unlikely (out_info != info || out_len != idx)) {
-    if (unlikely (!make_room_for (1, 1))) return;
-    out_info[out_len] = info[idx];
-  }
-  out_info[out_len].codepoint = glyph_index;
-
-  idx++;
-  out_len++;
-}
-
 
 void
 hb_buffer_t::set_masks (hb_mask_t    value,
@@ -510,7 +480,7 @@
 }
 
 void
-hb_buffer_t::reverse (void)
+hb_buffer_t::reverse ()
 {
   if (unlikely (!len))
     return;
@@ -519,7 +489,7 @@
 }
 
 void
-hb_buffer_t::reverse_clusters (void)
+hb_buffer_t::reverse_clusters ()
 {
   unsigned int i, start, count, last_cluster;
 
@@ -666,7 +636,7 @@
 }
 
 void
-hb_buffer_t::guess_segment_properties (void)
+hb_buffer_t::guess_segment_properties ()
 {
   assert (content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
           (!len && content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
@@ -701,6 +671,29 @@
 
 /* Public API */
 
+DEFINE_NULL_INSTANCE (hb_buffer_t) =
+{
+  HB_OBJECT_HEADER_STATIC,
+
+  const_cast<hb_unicode_funcs_t *> (&_hb_Null_hb_unicode_funcs_t),
+  HB_BUFFER_FLAG_DEFAULT,
+  HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
+  HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
+  0, /* invisible */
+  HB_BUFFER_SCRATCH_FLAG_DEFAULT,
+  HB_BUFFER_MAX_LEN_DEFAULT,
+  HB_BUFFER_MAX_OPS_DEFAULT,
+
+  HB_BUFFER_CONTENT_TYPE_INVALID,
+  HB_SEGMENT_PROPERTIES_DEFAULT,
+  false, /* successful */
+  true, /* have_output */
+  true  /* have_positions */
+
+  /* Zero is good enough for everything else. */
+};
+
+
 /**
  * hb_buffer_create: (Xconstructor)
  *
@@ -716,7 +709,7 @@
  * Since: 0.9.2
  **/
 hb_buffer_t *
-hb_buffer_create (void)
+hb_buffer_create ()
 {
   hb_buffer_t *buffer;
 
@@ -741,29 +734,9 @@
  * Since: 0.9.2
  **/
 hb_buffer_t *
-hb_buffer_get_empty (void)
+hb_buffer_get_empty ()
 {
-  static const hb_buffer_t _hb_buffer_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
-    HB_BUFFER_FLAG_DEFAULT,
-    HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
-    HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
-    HB_BUFFER_SCRATCH_FLAG_DEFAULT,
-    HB_BUFFER_MAX_LEN_DEFAULT,
-    HB_BUFFER_MAX_OPS_DEFAULT,
-
-    HB_BUFFER_CONTENT_TYPE_INVALID,
-    HB_SEGMENT_PROPERTIES_DEFAULT,
-    false, /* successful */
-    true, /* have_output */
-    true  /* have_positions */
-
-    /* Zero is good enough for everything else. */
-  };
-
-  return const_cast<hb_buffer_t *> (&_hb_buffer_nil);
+  return const_cast<hb_buffer_t *> (&Null(hb_buffer_t));
 }
 
 /**
@@ -900,13 +873,12 @@
 hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
                              hb_unicode_funcs_t *unicode_funcs)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   if (!unicode_funcs)
     unicode_funcs = hb_unicode_funcs_get_default ();
 
-
   hb_unicode_funcs_reference (unicode_funcs);
   hb_unicode_funcs_destroy (buffer->unicode);
   buffer->unicode = unicode_funcs;
@@ -948,7 +920,7 @@
                          hb_direction_t  direction)
 
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props.direction = direction;
@@ -992,7 +964,7 @@
 hb_buffer_set_script (hb_buffer_t *buffer,
                       hb_script_t  script)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props.script = script;
@@ -1027,7 +999,7 @@
  * are orthogonal to the scripts, and though they are related, they are
  * different concepts and should not be confused with each other.
  *
- * Use hb_language_from_string() to convert from ISO 639 language codes to
+ * Use hb_language_from_string() to convert from BCP 47 language tags to
  * #hb_language_t.
  *
  * Since: 0.9.2
@@ -1036,7 +1008,7 @@
 hb_buffer_set_language (hb_buffer_t   *buffer,
                         hb_language_t  language)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props.language = language;
@@ -1074,7 +1046,7 @@
 hb_buffer_set_segment_properties (hb_buffer_t *buffer,
                                   const hb_segment_properties_t *props)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props = *props;
@@ -1110,7 +1082,7 @@
 hb_buffer_set_flags (hb_buffer_t       *buffer,
                      hb_buffer_flags_t  flags)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->flags = flags;
@@ -1146,7 +1118,7 @@
 hb_buffer_set_cluster_level (hb_buffer_t       *buffer,
                      hb_buffer_cluster_level_t  cluster_level)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->cluster_level = cluster_level;
@@ -1185,7 +1157,7 @@
 hb_buffer_set_replacement_codepoint (hb_buffer_t    *buffer,
                                      hb_codepoint_t  replacement)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->replacement = replacement;
@@ -1210,6 +1182,46 @@
 
 
 /**
+ * hb_buffer_set_invisible_glyph:
+ * @buffer: an #hb_buffer_t.
+ * @invisible: the invisible #hb_codepoint_t
+ *
+ * Sets the #hb_codepoint_t that replaces invisible characters in
+ * the shaping result.  If set to zero (default), the glyph for the
+ * U+0020 SPACE character is used.  Otherwise, this value is used
+ * verbatim.
+ *
+ * Since: 2.0.0
+ **/
+void
+hb_buffer_set_invisible_glyph (hb_buffer_t    *buffer,
+                               hb_codepoint_t  invisible)
+{
+  if (unlikely (hb_object_is_immutable (buffer)))
+    return;
+
+  buffer->invisible = invisible;
+}
+
+/**
+ * hb_buffer_get_invisible_glyph:
+ * @buffer: an #hb_buffer_t.
+ *
+ * See hb_buffer_set_invisible_glyph().
+ *
+ * Return value:
+ * The @buffer invisible #hb_codepoint_t.
+ *
+ * Since: 2.0.0
+ **/
+hb_codepoint_t
+hb_buffer_get_invisible_glyph (hb_buffer_t    *buffer)
+{
+  return buffer->invisible;
+}
+
+
+/**
  * hb_buffer_reset:
  * @buffer: an #hb_buffer_t.
  *
@@ -1317,7 +1329,7 @@
 hb_buffer_set_length (hb_buffer_t  *buffer,
                       unsigned int  length)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return length == 0;
 
   if (!buffer->ensure (length))
@@ -1498,6 +1510,8 @@
  * it will be set to the process's default language as returned by
  * hb_language_get_default().  This may change in the future by
  * taking buffer script into consideration when choosing a language.
+ * Note that hb_language_get_default() is NOT threadsafe the first time
+ * it is called.  See documentation for that function for details.
  *
  * Since: 0.9.7
  **/
@@ -1521,7 +1535,7 @@
   assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
           (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
 
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   if (text_length == -1)
@@ -1652,7 +1666,7 @@
                      unsigned int    item_offset,
                      int             item_length)
 {
-  hb_buffer_add_utf<hb_utf32_t<> > (buffer, text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<hb_utf32_t> (buffer, text, text_length, item_offset, item_length);
 }
 
 /**
@@ -1713,7 +1727,7 @@
                           unsigned int          item_offset,
                           int                   item_length)
 {
-  hb_buffer_add_utf<hb_utf32_t<false> > (buffer, text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<hb_utf32_novalidate_t> (buffer, text, text_length, item_offset, item_length);
 }
 
 
@@ -1886,6 +1900,10 @@
 
 /**
  * hb_buffer_diff:
+ * @buffer: a buffer.
+ * @reference: other buffer to compare to.
+ * @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepont_t) -1.
+ * @position_fuzz: allowed absolute difference in position values.
  *
  * If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
  * and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned.  This should be used by most
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.h	Mon Feb 25 17:16:03 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.h	Sun Mar 10 03:34:59 2019 -0700
@@ -44,7 +44,6 @@
  * hb_glyph_info_t:
  * @codepoint: either a Unicode code point (before shaping) or a glyph index
  *             (after shaping).
- * @mask:
  * @cluster: the index of the character in the original text that corresponds
  *           to this #hb_glyph_info_t, or whatever the client passes to
  *           hb_buffer_add(). More than one #hb_glyph_info_t can have the same
@@ -59,11 +58,13 @@
  *
  * The #hb_glyph_info_t is the structure that holds information about the
  * glyphs and their relation to input text.
- *
  */
-typedef struct hb_glyph_info_t {
+typedef struct hb_glyph_info_t
+{
   hb_codepoint_t codepoint;
-  hb_mask_t      mask; /* Holds hb_glyph_flags_t after hb_shape(), plus other things. */
+  /*< private >*/
+  hb_mask_t      mask;
+  /*< public >*/
   uint32_t       cluster;
 
   /*< private >*/
@@ -88,6 +89,9 @@
  *                                 of each line after line-breaking, or limiting
  *                                 the reshaping to a small piece around the
  *                                 breaking point only.
+ * @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
+ *
+ * Since: 1.5.0
  */
 typedef enum { /*< flags >*/
   HB_GLYPH_FLAG_UNSAFE_TO_BREAK         = 0x00000001,
@@ -298,7 +302,15 @@
 HB_EXTERN hb_buffer_flags_t
 hb_buffer_get_flags (hb_buffer_t *buffer);
 
-/*
+/**
+ * hb_buffer_cluster_level_t:
+ * @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES: Return cluster values grouped by graphemes into
+ *   monotone order.
+ * @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS: Return cluster values grouped into monotone order.
+ * @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS: Don't group cluster values.
+ * @HB_BUFFER_CLUSTER_LEVEL_DEFAULT: Default cluster level,
+ *   equal to @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES.
+ *
  * Since: 0.9.42
  */
 typedef enum {
@@ -332,6 +344,13 @@
 HB_EXTERN hb_codepoint_t
 hb_buffer_get_replacement_codepoint (hb_buffer_t    *buffer);
 
+HB_EXTERN void
+hb_buffer_set_invisible_glyph (hb_buffer_t    *buffer,
+                               hb_codepoint_t  invisible);
+
+HB_EXTERN hb_codepoint_t
+hb_buffer_get_invisible_glyph (hb_buffer_t    *buffer);
+
 
 HB_EXTERN void
 hb_buffer_reset (hb_buffer_t *buffer);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,439 @@
+/*
+ * Copyright © 1998-2004  David Turner and Werner Lemberg
+ * Copyright © 2004,2007,2009,2010  Red Hat, Inc.
+ * Copyright © 2011,2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_BUFFER_HH
+#define HB_BUFFER_HH
+
+#include "hb.hh"
+#include "hb-unicode.hh"
+
+
+#ifndef HB_BUFFER_MAX_LEN_FACTOR
+#define HB_BUFFER_MAX_LEN_FACTOR 32
+#endif
+#ifndef HB_BUFFER_MAX_LEN_MIN
+#define HB_BUFFER_MAX_LEN_MIN 8192
+#endif
+#ifndef HB_BUFFER_MAX_LEN_DEFAULT
+#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
+#endif
+
+#ifndef HB_BUFFER_MAX_OPS_FACTOR
+#define HB_BUFFER_MAX_OPS_FACTOR 64
+#endif
+#ifndef HB_BUFFER_MAX_OPS_MIN
+#define HB_BUFFER_MAX_OPS_MIN 1024
+#endif
+#ifndef HB_BUFFER_MAX_OPS_DEFAULT
+#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */
+#endif
+
+static_assert ((sizeof (hb_glyph_info_t) == 20), "");
+static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
+
+HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
+HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
+HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
+
+enum hb_buffer_scratch_flags_t {
+  HB_BUFFER_SCRATCH_FLAG_DEFAULT                        = 0x00000000u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII                  = 0x00000001u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES         = 0x00000002u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK             = 0x00000004u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT            = 0x00000008u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK            = 0x00000010u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_CGJ                        = 0x00000020u,
+
+  /* Reserved for complex shapers' internal use. */
+  HB_BUFFER_SCRATCH_FLAG_COMPLEX0                       = 0x01000000u,
+  HB_BUFFER_SCRATCH_FLAG_COMPLEX1                       = 0x02000000u,
+  HB_BUFFER_SCRATCH_FLAG_COMPLEX2                       = 0x04000000u,
+  HB_BUFFER_SCRATCH_FLAG_COMPLEX3                       = 0x08000000u,
+};
+HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
+
+
+/*
+ * hb_buffer_t
+ */
+
+struct hb_buffer_t
+{
+  hb_object_header_t header;
+
+  /* Information about how the text in the buffer should be treated */
+  hb_unicode_funcs_t *unicode; /* Unicode functions */
+  hb_buffer_flags_t flags; /* BOT / EOT / etc. */
+  hb_buffer_cluster_level_t cluster_level;
+  hb_codepoint_t replacement; /* U+FFFD or something else. */
+  hb_codepoint_t invisible; /* 0 or something else. */
+  hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
+  unsigned int max_len; /* Maximum allowed len. */
+  int max_ops; /* Maximum allowed operations. */
+
+  /* Buffer contents */
+  hb_buffer_content_type_t content_type;
+  hb_segment_properties_t props; /* Script, language, direction */
+
+  bool successful; /* Allocations successful */
+  bool have_output; /* Whether we have an output buffer going on */
+  bool have_positions; /* Whether we have positions */
+
+  unsigned int idx; /* Cursor into ->info and ->pos arrays */
+  unsigned int len; /* Length of ->info and ->pos arrays */
+  unsigned int out_len; /* Length of ->out array if have_output */
+
+  unsigned int allocated; /* Length of allocated arrays */
+  hb_glyph_info_t     *info;
+  hb_glyph_info_t     *out_info;
+  hb_glyph_position_t *pos;
+
+  unsigned int serial;
+
+  /* Text before / after the main buffer contents.
+   * Always in Unicode, and ordered outward.
+   * Index 0 is for "pre-context", 1 for "post-context". */
+  static constexpr unsigned CONTEXT_LENGTH = 5u;
+  hb_codepoint_t context[2][CONTEXT_LENGTH];
+  unsigned int context_len[2];
+
+  /* Debugging API */
+  hb_buffer_message_func_t message_func;
+  void *message_data;
+  hb_destroy_func_t message_destroy;
+
+  /* Internal debugging. */
+  /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
+#ifndef HB_NDEBUG
+  uint8_t allocated_var_bits;
+#endif
+
+
+  /* Methods */
+
+  bool in_error () const { return !successful; }
+
+  void allocate_var (unsigned int start, unsigned int count)
+  {
+#ifndef HB_NDEBUG
+    unsigned int end = start + count;
+    assert (end <= 8);
+    unsigned int bits = (1u<<end) - (1u<<start);
+    assert (0 == (allocated_var_bits & bits));
+    allocated_var_bits |= bits;
+#endif
+  }
+  void deallocate_var (unsigned int start, unsigned int count)
+  {
+#ifndef HB_NDEBUG
+    unsigned int end = start + count;
+    assert (end <= 8);
+    unsigned int bits = (1u<<end) - (1u<<start);
+    assert (bits == (allocated_var_bits & bits));
+    allocated_var_bits &= ~bits;
+#endif
+  }
+  void assert_var (unsigned int start, unsigned int count)
+  {
+#ifndef HB_NDEBUG
+    unsigned int end = start + count;
+    assert (end <= 8);
+    unsigned int bits = (1u<<end) - (1u<<start);
+    assert (bits == (allocated_var_bits & bits));
+#endif
+  }
+  void deallocate_var_all ()
+  {
+#ifndef HB_NDEBUG
+    allocated_var_bits = 0;
+#endif
+  }
+
+  hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
+  hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
+
+  hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
+  hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
+
+  hb_glyph_info_t &prev ()      { return out_info[out_len ? out_len - 1 : 0]; }
+  hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
+
+  bool has_separate_output () const { return info != out_info; }
+
+
+  HB_INTERNAL void reset ();
+  HB_INTERNAL void clear ();
+
+  unsigned int backtrack_len () const { return have_output? out_len : idx; }
+  unsigned int lookahead_len () const { return len - idx; }
+  unsigned int next_serial () { return serial++; }
+
+  HB_INTERNAL void add (hb_codepoint_t  codepoint,
+                        unsigned int    cluster);
+  HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
+
+  HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
+  HB_INTERNAL void reverse ();
+  HB_INTERNAL void reverse_clusters ();
+  HB_INTERNAL void guess_segment_properties ();
+
+  HB_INTERNAL void swap_buffers ();
+  HB_INTERNAL void remove_output ();
+  HB_INTERNAL void clear_output ();
+  HB_INTERNAL void clear_positions ();
+
+  HB_INTERNAL void replace_glyphs (unsigned int num_in,
+                                   unsigned int num_out,
+                                   const hb_codepoint_t *glyph_data);
+
+  void replace_glyph (hb_codepoint_t glyph_index)
+  {
+    if (unlikely (out_info != info || out_len != idx)) {
+      if (unlikely (!make_room_for (1, 1))) return;
+      out_info[out_len] = info[idx];
+    }
+    out_info[out_len].codepoint = glyph_index;
+
+    idx++;
+    out_len++;
+  }
+  /* Makes a copy of the glyph at idx to output and replace glyph_index */
+  hb_glyph_info_t & output_glyph (hb_codepoint_t glyph_index)
+  {
+    if (unlikely (!make_room_for (0, 1))) return Crap(hb_glyph_info_t);
+
+    if (unlikely (idx == len && !out_len))
+      return Crap(hb_glyph_info_t);
+
+    out_info[out_len] = idx < len ? info[idx] : out_info[out_len - 1];
+    out_info[out_len].codepoint = glyph_index;
+
+    out_len++;
+
+    return out_info[out_len - 1];
+  }
+  void output_info (const hb_glyph_info_t &glyph_info)
+  {
+    if (unlikely (!make_room_for (0, 1))) return;
+
+    out_info[out_len] = glyph_info;
+
+    out_len++;
+  }
+  /* Copies glyph at idx to output but doesn't advance idx */
+  void copy_glyph ()
+  {
+    if (unlikely (!make_room_for (0, 1))) return;
+
+    out_info[out_len] = info[idx];
+
+    out_len++;
+  }
+  /* Copies glyph at idx to output and advance idx.
+   * If there's no output, just advance idx. */
+  void
+  next_glyph ()
+  {
+    if (have_output)
+    {
+      if (out_info != info || out_len != idx)
+      {
+        if (unlikely (!make_room_for (1, 1))) return;
+        out_info[out_len] = info[idx];
+      }
+      out_len++;
+    }
+
+    idx++;
+  }
+  /* Copies n glyphs at idx to output and advance idx.
+   * If there's no output, just advance idx. */
+  void
+  next_glyphs (unsigned int n)
+  {
+    if (have_output)
+    {
+      if (out_info != info || out_len != idx)
+      {
+        if (unlikely (!make_room_for (n, n))) return;
+        memmove (out_info + out_len, info + idx, n * sizeof (out_info[0]));
+      }
+      out_len += n;
+    }
+
+    idx += n;
+  }
+  /* Advance idx without copying to output. */
+  void skip_glyph () { idx++; }
+  void reset_masks (hb_mask_t mask)
+  {
+    for (unsigned int j = 0; j < len; j++)
+      info[j].mask = mask;
+  }
+  void add_masks (hb_mask_t mask)
+  {
+    for (unsigned int j = 0; j < len; j++)
+      info[j].mask |= mask;
+  }
+  HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask,
+                              unsigned int cluster_start, unsigned int cluster_end);
+
+  void merge_clusters (unsigned int start, unsigned int end)
+  {
+    if (end - start < 2)
+      return;
+    merge_clusters_impl (start, end);
+  }
+  HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end);
+  HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
+  /* Merge clusters for deleting current glyph, and skip it. */
+  HB_INTERNAL void delete_glyph ();
+
+  void unsafe_to_break (unsigned int start,
+                               unsigned int end)
+  {
+    if (end - start < 2)
+      return;
+    unsafe_to_break_impl (start, end);
+  }
+  HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
+  HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);
+
+
+  /* Internal methods */
+  HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */
+
+  HB_INTERNAL bool enlarge (unsigned int size);
+
+  bool ensure (unsigned int size)
+  { return likely (!size || size < allocated) ? true : enlarge (size); }
+
+  bool ensure_inplace (unsigned int size)
+  { return likely (!size || size < allocated); }
+
+  HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
+  HB_INTERNAL bool shift_forward (unsigned int count);
+
+  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 message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
+  {
+    if (!messaging ())
+      return true;
+    va_list ap;
+    va_start (ap, fmt);
+    bool ret = message_impl (font, fmt, ap);
+    va_end (ap);
+    return ret;
+  }
+  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)
+    {
+      if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
+        inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+      else
+        inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+    }
+    inf.cluster = cluster;
+  }
+
+  int
+  _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
+                                     unsigned int start, unsigned int end,
+                                     unsigned int cluster) const
+  {
+    for (unsigned int i = start; i < end; i++)
+      cluster = MIN<unsigned int> (cluster, infos[i].cluster);
+    return cluster;
+  }
+  void
+  _unsafe_to_break_set_mask (hb_glyph_info_t *infos,
+                             unsigned int start, unsigned int end,
+                             unsigned int cluster)
+  {
+    for (unsigned int i = start; i < end; i++)
+      if (cluster != infos[i].cluster)
+      {
+        scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
+        infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+      }
+  }
+
+  void unsafe_to_break_all ()
+  { unsafe_to_break_impl (0, len); }
+  void safe_to_break_all ()
+  {
+    for (unsigned int i = 0; i < len; i++)
+      info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+  }
+};
+DECLARE_NULL_INSTANCE (hb_buffer_t);
+
+
+/* Loop over clusters. Duplicated in foreach_syllable(). */
+#define foreach_cluster(buffer, start, end) \
+  for (unsigned int \
+       _count = buffer->len, \
+       start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
+       start < _count; \
+       start = end, end = _next_cluster (buffer, start))
+
+static inline unsigned int
+_next_cluster (hb_buffer_t *buffer, unsigned int start)
+{
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+
+  unsigned int cluster = info[start].cluster;
+  while (++start < count && cluster == info[start].cluster)
+    ;
+
+  return start;
+}
+
+
+#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
+  b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
+           sizeof (b->info[0].var))
+#define HB_BUFFER_ALLOCATE_VAR(b, var)          HB_BUFFER_XALLOCATE_VAR (b, allocate_var,   var ())
+#define HB_BUFFER_DEALLOCATE_VAR(b, var)        HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
+#define HB_BUFFER_ASSERT_VAR(b, var)            HB_BUFFER_XALLOCATE_VAR (b, assert_var,     var ())
+
+
+#endif /* HB_BUFFER_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff-interp-common.hh	Sun Mar 10 03:34:59 2019 -0700
@@ -0,0 +1,725 @@
+/*
+ * Copyright © 2018 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_CFF_INTERP_COMMON_HH
+#define HB_CFF_INTERP_COMMON_HH
+
+namespace CFF {
+
+using namespace OT;
+
+typedef unsigned int op_code_t;
+
+
+/* === Dict operators === */
+
+/* One byte operators (0-31) */
+#define OpCode_version            0 /* CFF Top */
+#define OpCode_Notice             1 /* CFF Top */
+#define OpCode_FullName           2 /* CFF Top */
+#define OpCode_FamilyName         3 /* CFF Top */
+#define OpCode_Weight             4 /* CFF Top */
+#define OpCode_FontBBox           5 /* CFF Top */
+#define OpCode_BlueValues         6 /* CFF Private, CFF2 Private */
+#define OpCode_OtherBlues         7 /* CFF Private, CFF2 Private */
+#define OpCode_FamilyBlues        8 /* CFF Private, CFF2 Private */
+#define OpCode_FamilyOtherBlues   9 /* CFF Private, CFF2 Private */
+#define OpCode_StdHW             10 /* CFF Private, CFF2 Private */
+#define OpCode_StdVW             11 /* CFF Private, CFF2 Private */
+#define OpCode_escape            12 /* All. Shared with CS */
+#define OpCode_UniqueID          13 /* CFF Top */
+#define OpCode_XUID              14 /* CFF Top */
+#define OpCode_charset           15 /* CFF Top (0) */
+#define OpCode_Encoding          16 /* CFF Top (0) */
+#define OpCode_CharStrings       17 /* CFF Top, CFF2 Top */
+#define OpCode_Private           18 /* CFF Top, CFF2 FD */
+#define OpCode_Subrs             19 /* CFF Private, CFF2 Private */
+#define OpCode_defaultWidthX     20 /* CFF Private (0) */
+#define OpCode_nominalWidthX     21 /* CFF Private (0) */
+#define OpCode_vsindexdict       22 /* CFF2 Private/CS */
+#define OpCode_blenddict         23 /* CFF2 Private/CS */
+#define OpCode_vstore            24 /* CFF2 Top */
+#define OpCode_reserved25        25
+#define OpCode_reserved26        26
+#define OpCode_reserved27        27
+
+/* Numbers */
+#define OpCode_shortint          28 /* 16-bit integer, All */
+#define OpCode_longintdict       29 /* 32-bit integer, All */
+#define OpCode_BCD               30 /* Real number, CFF2 Top/FD */
+#define OpCode_reserved31        31
+
+/* 1-byte integers */
+#define OpCode_OneByteIntFirst   32 /* All. beginning of the range of first byte ints */
+#define OpCode_OneByteIntLast   246 /* All. ending of the range of first byte int */
+
+/* 2-byte integers */
+#define OpCode_TwoBytePosInt0   247 /* All. first byte of two byte positive int (+108 to +1131) */
+#define OpCode_TwoBytePosInt1   248
+#define OpCode_TwoBytePosInt2   249
+#define OpCode_TwoBytePosInt3   250
+
+#define OpCode_TwoByteNegInt0   251 /* All. first byte of two byte negative int (-1131 to -108) */
+#define OpCode_TwoByteNegInt1   252
+#define OpCode_TwoByteNegInt2   253
+#define OpCode_TwoByteNegInt3   254
+
+/* Two byte escape operators 12, (0-41) */
+#define OpCode_ESC_Base         256
+#define Make_OpCode_ESC(byte2)  ((op_code_t)(OpCode_ESC_Base + (byte2)))
+
+inline op_code_t Unmake_OpCode_ESC (op_code_t op)  { return (op_code_t)(op - OpCode_ESC_Base); }
+inline bool Is_OpCode_ESC (op_code_t op) { return op >= OpCode_ESC_Base; }
+inline unsigned int OpCode_Size (op_code_t op) { return Is_OpCode_ESC (op) ? 2: 1; }
+
+#define OpCode_Copyright        Make_OpCode_ESC(0) /* CFF Top */
+#define OpCode_isFixedPitch     Make_OpCode_ESC(1) /* CFF Top (false) */
+#define OpCode_ItalicAngle      Make_OpCode_ESC(2) /* CFF Top (0) */
+#define OpCode_UnderlinePosition Make_OpCode_ESC(3) /* CFF Top (-100) */
+#define OpCode_UnderlineThickness Make_OpCode_ESC(4) /* CFF Top (50) */
+#define OpCode_PaintType        Make_OpCode_ESC(5) /* CFF Top (0) */
+#define OpCode_CharstringType   Make_OpCode_ESC(6) /* CFF Top (2) */
+#define OpCode_FontMatrix       Make_OpCode_ESC(7) /* CFF Top, CFF2 Top (.001 0 0 .001 0 0)*/
+#define OpCode_StrokeWidth      Make_OpCode_ESC(8) /* CFF Top (0) */
+#define OpCode_BlueScale        Make_OpCode_ESC(9) /* CFF Private, CFF2 Private (0.039625) */
+#define OpCode_BlueShift        Make_OpCode_ESC(10) /* CFF Private, CFF2 Private (7) */
+#define OpCode_BlueFuzz         Make_OpCode_ESC(11) /* CFF Private, CFF2 Private (1) */
+#define OpCode_StemSnapH        Make_OpCode_ESC(12) /* CFF Private, CFF2 Private */
+#define OpCode_StemSnapV        Make_OpCode_ESC(13) /* CFF Private, CFF2 Private */
+#define OpCode_ForceBold        Make_OpCode_ESC(14) /* CFF Private (false) */
+#define OpCode_reservedESC15    Make_OpCode_ESC(15)
+#define OpCode_reservedESC16    Make_OpCode_ESC(16)
+#define OpCode_LanguageGroup    Make_OpCode_ESC(17) /* CFF Private, CFF2 Private (0) */
+#define OpCode_ExpansionFactor  Make_OpCode_ESC(18) /* CFF Private, CFF2 Private (0.06) */
+#define OpCode_initialRandomSeed Make_OpCode_ESC(19) /* CFF Private (0) */
+#define OpCode_SyntheticBase    Make_OpCode_ESC(20) /* CFF Top */
+#define OpCode_PostScript       Make_OpCode_ESC(21) /* CFF Top */
+#define OpCode_BaseFontName     Make_OpCode_ESC(22) /* CFF Top */
+#define OpCode_BaseFontBlend    Make_OpCode_ESC(23) /* CFF Top */
+#define OpCode_reservedESC24    Make_OpCode_ESC(24)
+#define OpCode_reservedESC25    Make_OpCode_ESC(25)
+#define OpCode_reservedESC26    Make_OpCode_ESC(26)
+#define OpCode_reservedESC27    Make_OpCode_ESC(27)
+#define OpCode_reservedESC28    Make_OpCode_ESC(28)
+#define OpCode_reservedESC29    Make_OpCode_ESC(29)
+#define OpCode_ROS              Make_OpCode_ESC(30) /* CFF Top_CID */
+#define OpCode_CIDFontVersion   Make_OpCode_ESC(31) /* CFF Top_CID (0) */
+#define OpCode_CIDFontRevision  Make_OpCode_ESC(32) /* CFF Top_CID (0) */
+#define OpCode_CIDFontType      Make_OpCode_ESC(33) /* CFF Top_CID (0) */
+#define OpCode_CIDCount         Make_OpCode_ESC(34) /* CFF Top_CID (8720) */
+#define OpCode_UIDBase          Make_OpCode_ESC(35) /* CFF Top_CID */
+#define OpCode_FDArray          Make_OpCode_ESC(36) /* CFF Top_CID, CFF2 Top */
+#define OpCode_FDSelect         Make_OpCode_ESC(37) /* CFF Top_CID, CFF2 Top */
+#define OpCode_FontName         Make_OpCode_ESC(38) /* CFF Top_CID */
+
+
+/* === CharString operators === */
+
+#define OpCode_hstem              1 /* CFF, CFF2 */
+#define OpCode_Reserved2          2
+#define OpCode_vstem              3 /* CFF, CFF2 */
+#define OpCode_vmoveto            4 /* CFF, CFF2 */
+#define OpCode_rlineto            5 /* CFF, CFF2 */
+#define OpCode_hlineto            6 /* CFF, CFF2 */
+#define OpCode_vlineto            7 /* CFF, CFF2 */
+#define OpCode_rrcurveto          8 /* CFF, CFF2 */
+#define OpCode_Reserved9          9
+#define OpCode_callsubr          10 /* CFF, CFF2 */
+#define OpCode_return            11 /* CFF */
+//#define OpCode_escape          12 /* CFF, CFF2 */
+#define OpCode_Reserved13        13
+#define OpCode_endchar           14 /* CFF */
+#define OpCode_vsindexcs         15 /* CFF2 */
+#define OpCode_blendcs           16 /* CFF2 */
+#define OpCode_Reserved17        17
+#define OpCode_hstemhm           18 /* CFF, CFF2 */
+#define OpCode_hintmask          19 /* CFF, CFF2 */
+#define OpCode_cntrmask          20 /* CFF, CFF2 */
+#define OpCode_rmoveto           21 /* CFF, CFF2 */
+#define OpCode_hmoveto           22 /* CFF, CFF2 */
+#define OpCode_vstemhm           23 /* CFF, CFF2 */
+#define OpCode_rcurveline        24 /* CFF, CFF2 */
+#define OpCode_rlinecurve        25 /* CFF, CFF2 */
+#define OpCode_vvcurveto         26 /* CFF, CFF2 */
+#define OpCode_hhcurveto         27 /* CFF, CFF2 */
+//#define OpCode_shortint        28 /* CFF, CFF2 */
+#define OpCode_callgsubr         29 /* CFF, CFF2 */
+#define OpCode_vhcurveto         30 /* CFF, CFF2 */
+#define OpCode_hvcurveto         31 /* CFF, CFF2 */
+
+#define OpCode_fixedcs          255 /* 32-bit fixed */
+
+/* Two byte escape operators 12, (0-41) */
+#define OpCode_dotsection       Make_OpCode_ESC(0) /* CFF (obsoleted) */
+#define OpCode_ReservedESC1     Make_OpCode_ESC(1)
+#define OpCode_ReservedESC2     Make_OpCode_ESC(2)
+#define OpCode_and              Make_OpCode_ESC(3) /* CFF */
+#define OpCode_or               Make_OpCode_ESC(4) /* CFF */
+#define OpCode_not              Make_OpCode_ESC(5) /* CFF */
+#define OpCode_ReservedESC6     Make_OpCode_ESC(6)
+#define OpCode_ReservedESC7     Make_OpCode_ESC(7)
+#define OpCode_ReservedESC8     Make_OpCode_ESC(8)
+#define OpCode_abs              Make_OpCode_ESC(9) /* CFF */
+#define OpCode_add              Make_OpCode_ESC(10) /* CFF */
+#define OpCode_sub              Make_OpCode_ESC(11) /* CFF */
+#define OpCode_div              Make_OpCode_ESC(12) /* CFF */
+#define OpCode_ReservedESC13    Make_OpCode_ESC(13)
+#define OpCode_neg              Make_OpCode_ESC(14) /* CFF */
+#define OpCode_eq               Make_OpCode_ESC(15) /* CFF */
+#define OpCode_ReservedESC16    Make_OpCode_ESC(16)
+#define OpCode_ReservedESC17    Make_OpCode_ESC(17)
+#define OpCode_drop             Make_OpCode_ESC(18) /* CFF */
+#define OpCode_ReservedESC19    Make_OpCode_ESC(19)
+#define OpCode_put              Make_OpCode_ESC(20) /* CFF */
+#define OpCode_get              Make_OpCode_ESC(21) /* CFF */
+#define OpCode_ifelse           Make_OpCode_ESC(22) /* CFF */
+#define OpCode_random           Make_OpCode_ESC(23) /* CFF */
+#define OpCode_mul              Make_OpCode_ESC(24) /* CFF */
+//#define OpCode_reservedESC25  Make_OpCode_ESC(25)
+#define OpCode_sqrt             Make_OpCode_ESC(26) /* CFF */
+#define OpCode_dup              Make_OpCode_ESC(27) /* CFF */
+#define OpCode_exch             Make_OpCode_ESC(28) /* CFF */
+#define OpCode_index            Make_OpCode_ESC(29) /* CFF */
+#define OpCode_roll             Make_OpCode_ESC(30) /* CFF */
+#define OpCode_reservedESC31    Make_OpCode_ESC(31)
+#define OpCode_reservedESC32    Make_OpCode_ESC(32)
+#define OpCode_reservedESC33    Make_OpCode_ESC(33)
+#define OpCode_hflex            Make_OpCode_ESC(34) /* CFF, CFF2 */
+#define OpCode_flex             Make_OpCode_ESC(35) /* CFF, CFF2 */
+#define OpCode_hflex1           Make_OpCode_ESC(36) /* CFF, CFF2 */
+#define OpCode_flex1            Make_OpCode_ESC(37) /* CFF, CFF2 */
+
+
+#define OpCode_Invalid          0xFFFFu
+
+
+struct number_t
+{
+  void init () { set_real (0.0); }
+  void fini () {}
+
+  void set_int (int v)       { value = (double) v; }
+  int to_int () const        { return (int) value; }
+
+  void set_fixed (int32_t v) { value = v / 65536.0; }
+  int32_t to_fixed () const  { return (int32_t) (value * 65536.0); }
+
+  void set_real (double v)       { value = v; }
+  double to_real () const    { return value; }
+
+  int ceil () const          { return (int) ::ceil (value); }
+  int floor () const         { return (int) ::floor (value); }
+
+  bool in_int_range () const
+  { return ((double) (int16_t) to_int () == value); }
+
+  bool operator > (const number_t &n) const
+  { return value > n.to_real (); }
+
+  bool operator < (const number_t &n) const
+  { return n > *this; }
+
+  bool operator >= (const number_t &n) const
+  { return !(*this < n); }
+
+  bool operator <= (const number_t &n) const
+  { return !(*this > n); }
+
+  const number_t &operator += (const number_t &n)
+  {
+    set_real (to_real () + n.to_real ());
+
+    return *this;
+  }
+
+  protected:
+  double  value;
+};
+
+/* byte string */
+struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
+{
+  // encode 2-byte int (Dict/CharString) or 4-byte int (Dict)
+  template <typename INTTYPE, int minVal, int maxVal>
+  static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, int value)
+  {
+    TRACE_SERIALIZE (this);
+
+    if (unlikely ((value < minVal || value > maxVal)))
+      return_trace (false);
+
+    HBUINT8 *p = c->allocate_size<HBUINT8> (1);
+    if (unlikely (p == nullptr)) return_trace (false);
+    p->set (intOp);
+
+    INTTYPE *ip = c->allocate_size<INTTYPE> (INTTYPE::static_size);
+    if (unlikely (ip == nullptr)) return_trace (false);
+    ip->set ((unsigned int)value);
+
+    return_trace (true);
+  }
+
+  static bool serialize_int4 (hb_serialize_context_t *c, int value)
+  { return serialize_int<HBUINT32, 0, 0x7FFFFFFF> (c, OpCode_longintdict, value); }
+
+  static bool serialize_int2 (hb_serialize_context_t *c, int value)
+  { return serialize_int<HBUINT16, 0, 0x7FFF> (c, OpCode_shortint, value); }
+
+  /* Defining null_size allows a Null object may be created. Should be safe because:
+   * A descendent struct Dict uses a Null pointer to indicate a missing table,
+   * checked before access.
+   * byte_str_t, a wrapper struct pairing a byte pointer along with its length, always
+   * checks the length before access. A Null pointer is used as the initial pointer
+   * along with zero length by the default ctor.
+   */
+  DEFINE_SIZE_MIN(0);
+};
+
+/* Holder of a section of byte string within a CFFIndex entry */
+struct byte_str_t : hb_ubytes_t
+{
+  byte_str_t ()
+    : hb_ubytes_t () {}
+  byte_str_t (const UnsizedByteStr& s, unsigned int l)
+    : hb_ubytes_t ((const unsigned char*)&s, l) {}
+  byte_str_t (const unsigned char *s, unsigned int l)
+    : hb_ubytes_t (s, l) {}
+  byte_str_t (const hb_ubytes_t &ub)    /* conversion from hb_ubytes_t */
+    : hb_ubytes_t (ub) {}
+
+  /* sub-string */
+  byte_str_t sub_str (unsigned int offset, unsigned int len_) const
+  { return byte_str_t (hb_ubytes_t::sub_array (offset, len_)); }
+
+  bool check_limit (unsigned int offset, unsigned int count) const
+  { return (offset + count <= length); }
+};
+
+/* A byte string associated with the current offset and an error condition */
+struct byte_str_ref_t
+{
+  byte_str_ref_t ()
+  { init (); }
+
+  void init ()
+  {
+    str = byte_str_t ();
+    offset = 0;
+    error = false;
+  }
+
+  void fini () {}
+
+  byte_str_ref_t (const byte_str_t &str_, unsigned int offset_ = 0)
+    : str (str_), offset (offset_), error (false) {}
+
+  void reset (const byte_str_t &str_, unsigned int offset_ = 0)
+  {
+    str = str_;
+    offset = offset_;
+    error = false;
+  }
+
+  const unsigned char& operator [] (int i) {
+    if (unlikely ((unsigned int)(offset + i) >= str.length))
+    {
+      set_error ();
+      return Null(unsigned char);
+    }
+    else
+      return str[offset + i];
+  }
+
+  /* Conversion to byte_str_t */
+  operator byte_str_t () const { return str.sub_str (offset, str.length - offset); }
+
+  byte_str_t sub_str (unsigned int offset_, unsigned int len_) const
+  { return str.sub_str (offset_, len_); }
+
+  bool avail (unsigned int count=1) const
+  {
+    return (!in_error () && str.check_limit (offset, count));
+  }
+  void inc (unsigned int count=1)
+  {
+    if (likely (!in_error () && (offset <= str.length) && (offset + count <= str.length)))
+    {
+      offset += count;
+    }
+    else
+    {
+      offset = str.length;
+      set_error ();
+    }
+  }
+
+  void set_error ()      { error = true; }
+  bool in_error () const { return error; }
+
+  byte_str_t       str;
+  unsigned int  offset; /* beginning of the sub-string within str */
+
+  protected:
+  bool    error;
+};
+
+typedef hb_vector_t<byte_str_t> byte_str_array_t;
+
+/* stack */
+template <typename ELEM, int LIMIT>
+struct stack_t
+{
+  void init ()
+  {
+    error = false;
+    count = 0;
+    elements.init ();
+    elements.resize (kSizeLimit);
+    for (unsigned int i = 0; i < elements.length; i++)
+      elements[i].init ();
+  }
+
+  void fini ()
+  {
+    elements.fini_deep ();
+  }
+
+  ELEM& operator [] (unsigned int i)
+  {
+    if (unlikely (i >= count)) set_error ();
+    return elements[i];
+  }
+
+  void push (const ELEM &v)
+  {
+    if (likely (count < elements.length))
+      elements[count++] = v;
+    else
+      set_error ();
+  }
+
+  ELEM &push ()
+  {
+    if (likely (count < elements.length))
+      return elements[count++];
+    else
+    {
+      set_error ();
+      return Crap(ELEM);
+    }
+  }
+
+  ELEM& pop ()
+  {
+    if (likely (count > 0))
+      return elements[--count];
+    else
+    {
+      set_error ();
+      return Crap(ELEM);
+    }
+  }
+
+  void pop (unsigned int n)
+  {
+    if (likely (count >= n))
+      count -= n;
+    else
+      set_error ();
+  }
+
+  const ELEM& peek ()
+  {
+    if (likely (count > 0))
+      return elements[count-1];
+    else
+    {
+      set_error ();
+      return Null(ELEM);
+    }
+  }
+
+  void unpop ()
+  {
+    if (likely (count < elements.length))
+      count++;
+    else
+      set_error ();
+  }
+
+  void clear () { count = 0; }
+
+  bool in_error () const { return (error || elements.in_error ()); }
+  void set_error ()      { error = true; }
+
+  unsigned int get_count () const { return count; }
+  bool is_empty () const { return count == 0; }
+
+  static constexpr unsigned kSizeLimit = LIMIT;
+
+  protected:
+  bool error;
+  unsigned int count;
+  hb_vector_t<ELEM> elements;
+};
+
+/* argument stack */
+template <typename ARG=number_t>
+struct arg_stack_t : stack_t<ARG, 513>
+{
+  void push_int (int v)
+  {
+    ARG &n = S::push ();
+    n.set_int (v);
+  }
+
+  void push_fixed (int32_t v)
+  {
+    ARG &n = S::push ();
+    n.set_fixed (v);
+  }
+
+  void push_real (double v)
+  {
+    ARG &n = S::push ();
+    n.set_real (v);
+  }
+
+  ARG& pop_num () { return this->pop (); }
+
+  int pop_int ()  { return this->pop ().to_int (); }
+
+  unsigned int pop_uint ()
+  {
+    int i = pop_int ();
+    if (unlikely (i < 0))
+    {
+      i = 0;
+      S::set_error ();
+    }
+    return (unsigned)i;
+  }
+
+  void push_longint_from_substr (byte_str_ref_t& str_ref)
+  {
+    push_int ((str_ref[0] << 24) | (str_ref[1] << 16) | (str_ref[2] << 8) | (str_ref[3]));
+    str_ref.inc (4);
+  }
+
+  bool push_fixed_from_substr (byte_str_ref_t& str_ref)
+  {
+    if (unlikely (!str_ref.avail (4)))
+      return false;
+    push_fixed ((int32_t)*(const HBUINT32*)&str_ref[0]);
+    str_ref.inc (4);
+    return true;
+  }
+
+  hb_array_t<const ARG> get_subarray (unsigned int start) const
+  {
+    return S::elements.sub_array (start);
+  }
+
+  private:
+  typedef stack_t<ARG, 513> S;
+};
+
+/* an operator prefixed by its operands in a byte string */
+struct op_str_t
+{
+  void init () {}
+  void fini () {}
+
+  op_code_t  op;
+  byte_str_t str;
+};
+
+/* base of OP_SERIALIZER */
+struct op_serializer_t
+{
+  protected:
+  bool copy_opstr (hb_serialize_context_t *c, const op_str_t& opstr) const
+  {
+    TRACE_SERIALIZE (this);
+
+    HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
+    if (unlikely (d == nullptr)) return_trace (false);
+    memcpy (d, &opstr.str[0], opstr.str.length);
+    return_trace (true);
+  }
+};
+
+template <typename VAL>
+struct parsed_values_t
+{
+  void init ()
+  {
+    opStart = 0;
+    values.init ();
+  }
+  void fini () { values.fini_deep (); }
+
+  void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t ())
+  {
+    VAL *val = values.push ();
+    val->op = op;
+    val->str = str_ref.str.sub_str (opStart, str_ref.offset - opStart);
+    opStart = str_ref.offset;
+  }
+
+  void add_op (op_code_t op, const byte_str_ref_t& str_ref, const VAL &v)
+  {
+    VAL *val = values.push (v);
+    val->op = op;
+    val->str = str_ref.sub_str ( opStart, str_ref.offset - opStart);
+    opStart = str_ref.offset;
+  }
+
+  bool has_op (op_code_t op) const
+  {
+    for (unsigned int i = 0; i < get_count (); i++)
+      if (get_value (i).op == op) return true;
+    return false;
+  }
+
+  unsigned get_count () const { return values.length; }
+  const VAL &get_value (unsigned int i) const { return values[i]; }
+  const VAL &operator [] (unsigned int i) const { return get_value (i); }
+
+  unsigned int       opStart;
+  hb_vector_t<VAL>   values;
+};
+
+template <typename ARG=number_t>
+struct interp_env_t
+{
+  void init (const byte_str_t &str_)
+  {
+    str_ref.reset (str_);
+    argStack.init ();
+    error = false;
+  }
+  void fini () { argStack.fini (); }
+
+  bool in_error