8210782: Upgrade HarfBuzz to the latest 2.3.1
authorprr
Fri, 01 Mar 2019 16:59:19 -0800
changeset 54232 7c11a7cc7c1d
parent 54231 e4813eded7cb
child 54233 9413f1a4dc2b
8210782: Upgrade HarfBuzz to the latest 2.3.1 Reviewed-by: serb, ihse, erikj
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
--- a/make/lib/Awt2dLibraries.gmk	Wed Feb 27 18:46:55 2019 -0800
+++ b/make/lib/Awt2dLibraries.gmk	Fri Mar 01 16:59:19 2019 -0800
@@ -536,7 +536,8 @@
 
 ifeq ($(call isTargetOs, windows), false)
   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
 ifeq ($(call isTargetOs, linux macosx), true)
   HARFBUZZ_CFLAGS += -DHAVE_INTEL_ATOMIC_PRIMITIVES
@@ -613,8 +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 \
-        missing-attributes class-memaccess, \
+        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, \
@@ -624,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	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/legal/harfbuzz.md	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Wed Feb 27 18:46:55 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__) || defined(__ibmxl__))
-
-#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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Wed Feb 27 18:46:55 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	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-json.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-text.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Wed Feb 27 18:46:55 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	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-serialize.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.h	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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	Fri Mar 01 16:59:19 2019 -0800
@@ -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 () const
+  { return error || str_ref.in_error () || argStack.in_error (); }
+
+  void set_error () { error = true; }
+
+  op_code_t fetch_op ()
+  {
+    op_code_t  op = OpCode_Invalid;
+    if (unlikely (!str_ref.avail ()))
+      return OpCode_Invalid;
+    op = (op_code_t)(unsigned char)str_ref[0];
+    if (op == OpCode_escape) {
+      if (unlikely (!str_ref.avail ()))
+        return OpCode_Invalid;
+      op = Make_OpCode_ESC(str_ref[1]);
+      str_ref.inc ();
+    }
+    str_ref.inc ();
+    return op;
+  }
+
+  const ARG& eval_arg (unsigned int i)
+  {
+    return argStack[i];
+  }
+
+  ARG& pop_arg ()
+  {
+    return argStack.pop ();
+  }
+
+  void pop_n_args (unsigned int n)
+  {
+    argStack.pop (n);
+  }
+
+  void clear_args ()
+  {
+    pop_n_args (argStack.get_count ());
+  }
+
+  byte_str_ref_t    str_ref;
+  arg_stack_t<ARG> argStack;
+  protected:
+  bool    error;
+};
+
+typedef interp_env_t<> num_interp_env_t;
+
+template <typename ARG=number_t>
+struct opset_t
+{
+  static void process_op (op_code_t op, interp_env_t<ARG>& env)
+  {
+    switch (op) {
+      case OpCode_shortint:
+        env.argStack.push_int ((int16_t)((env.str_ref[0] << 8) | env.str_ref[1]));
+        env.str_ref.inc (2);
+        break;
+
+      case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1:
+      case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3:
+        env.argStack.push_int ((int16_t)((op - OpCode_TwoBytePosInt0) * 256 + env.str_ref[0] + 108));
+        env.str_ref.inc ();
+        break;
+
+      case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1:
+      case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3:
+        env.argStack.push_int ((int16_t)(-(op - OpCode_TwoByteNegInt0) * 256 - env.str_ref[0] - 108));
+        env.str_ref.inc ();
+        break;
+
+      default:
+        /* 1-byte integer */
+        if (likely ((OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast)))
+        {
+          env.argStack.push_int ((int)op - 139);
+        } else {
+          /* invalid unknown operator */
+          env.clear_args ();
+          env.set_error ();
+        }
+        break;
+    }
+  }
+};
+
+template <typename ENV>
+struct interpreter_t {
+
+  ~interpreter_t() { fini (); }
+
+  void fini () { env.fini (); }
+
+  ENV env;
+};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF_INTERP_COMMON_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff-interp-cs-common.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,905 @@
+/*
+ * 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_CS_COMMON_HH
+#define HB_CFF_INTERP_CS_COMMON_HH
+
+#include "hb.hh"
+#include "hb-cff-interp-common.hh"
+
+namespace CFF {
+
+using namespace OT;
+
+enum cs_type_t {
+  CSType_CharString,
+  CSType_GlobalSubr,
+  CSType_LocalSubr
+};
+
+struct call_context_t
+{
+  void init (const byte_str_ref_t substr_=byte_str_ref_t (), cs_type_t type_=CSType_CharString, unsigned int subr_num_=0)
+  {
+    str_ref = substr_;
+    type = type_;
+    subr_num = subr_num_;
+  }
+
+  void fini () {}
+
+  byte_str_ref_t  str_ref;
+  cs_type_t       type;
+  unsigned int    subr_num;
+};
+
+/* call stack */
+const unsigned int kMaxCallLimit = 10;
+struct call_stack_t : stack_t<call_context_t, kMaxCallLimit> {};
+
+template <typename SUBRS>
+struct biased_subrs_t
+{
+  void init (const SUBRS &subrs_)
+  {
+    subrs = &subrs_;
+    unsigned int  nSubrs = get_count ();
+    if (nSubrs < 1240)
+      bias = 107;
+    else if (nSubrs < 33900)
+      bias = 1131;
+    else
+      bias = 32768;
+  }
+
+  void fini () {}
+
+  unsigned int get_count () const { return (subrs == nullptr)? 0: subrs->count; }
+  unsigned int get_bias () const { return bias; }
+
+  byte_str_t operator [] (unsigned int index) const
+  {
+    if (unlikely ((subrs == nullptr) || index >= subrs->count))
+      return Null(byte_str_t);
+    else
+      return (*subrs)[index];
+  }
+
+  protected:
+  unsigned int  bias;
+  const SUBRS   *subrs;
+};
+
+struct point_t
+{
+  void init ()
+  {
+    x.init ();
+    y.init ();
+  }
+
+  void set_int (int _x, int _y)
+  {
+    x.set_int (_x);
+    y.set_int (_y);
+  }
+
+  void move_x (const number_t &dx) { x += dx; }
+  void move_y (const number_t &dy) { y += dy; }
+  void move (const number_t &dx, const number_t &dy) { move_x (dx); move_y (dy); }
+  void move (const point_t &d) { move_x (d.x); move_y (d.y); }
+
+  number_t  x;
+  number_t  y;
+};
+
+template <typename ARG, typename SUBRS>
+struct cs_interp_env_t : interp_env_t<ARG>
+{
+  void init (const byte_str_t &str, const SUBRS &globalSubrs_, const SUBRS &localSubrs_)
+  {
+    interp_env_t<ARG>::init (str);
+
+    context.init (str, CSType_CharString);
+    seen_moveto = true;
+    seen_hintmask = false;
+    hstem_count = 0;
+    vstem_count = 0;
+    hintmask_size = 0;
+    pt.init ();
+    callStack.init ();
+    globalSubrs.init (globalSubrs_);
+    localSubrs.init (localSubrs_);
+  }
+  void fini ()
+  {
+    interp_env_t<ARG>::fini ();
+
+    callStack.fini ();
+    globalSubrs.fini ();
+    localSubrs.fini ();
+  }
+
+  bool in_error () const
+  {
+    return callStack.in_error () || SUPER::in_error ();
+  }
+
+  bool popSubrNum (const biased_subrs_t<SUBRS>& biasedSubrs, unsigned int &subr_num)
+  {
+    int n = SUPER::argStack.pop_int ();
+    n += biasedSubrs.get_bias ();
+    if (unlikely ((n < 0) || ((unsigned int)n >= biasedSubrs.get_count ())))
+      return false;
+
+    subr_num = (unsigned int)n;
+    return true;
+  }
+
+  void callSubr (const biased_subrs_t<SUBRS>& biasedSubrs, cs_type_t type)
+  {
+    unsigned int subr_num;
+
+    if (unlikely (!popSubrNum (biasedSubrs, subr_num)
+                 || callStack.get_count () >= kMaxCallLimit))
+    {
+      SUPER::set_error ();
+      return;
+    }
+    context.str_ref = SUPER::str_ref;
+    callStack.push (context);
+
+    context.init ( biasedSubrs[subr_num], type, subr_num);
+    SUPER::str_ref = context.str_ref;
+  }
+
+  void returnFromSubr ()
+  {
+    if (unlikely (SUPER::str_ref.in_error ()))
+      SUPER::set_error ();
+    context = callStack.pop ();
+    SUPER::str_ref = context.str_ref;
+  }
+
+  void determine_hintmask_size ()
+  {
+    if (!seen_hintmask)
+    {
+      vstem_count += SUPER::argStack.get_count() / 2;
+      hintmask_size = (hstem_count + vstem_count + 7) >> 3;
+      seen_hintmask = true;
+    }
+  }
+
+  void set_endchar (bool endchar_flag_) { endchar_flag = endchar_flag_; }
+  bool is_endchar () const { return endchar_flag; }
+
+  const number_t &get_x () const { return pt.x; }
+  const number_t &get_y () const { return pt.y; }
+  const point_t &get_pt () const { return pt; }
+
+  void moveto (const point_t &pt_ ) { pt = pt_; }
+
+  public:
+  call_context_t   context;
+  bool    endchar_flag;
+  bool    seen_moveto;
+  bool    seen_hintmask;
+
+  unsigned int  hstem_count;
+  unsigned int  vstem_count;
+  unsigned int  hintmask_size;
+  call_stack_t  callStack;
+  biased_subrs_t<SUBRS>   globalSubrs;
+  biased_subrs_t<SUBRS>   localSubrs;
+
+  private:
+  point_t        pt;
+
+  typedef interp_env_t<ARG> SUPER;
+};
+
+template <typename ENV, typename PARAM>
+struct path_procs_null_t
+{
+  static void rmoveto (ENV &env, PARAM& param) {}
+  static void hmoveto (ENV &env, PARAM& param) {}
+  static void vmoveto (ENV &env, PARAM& param) {}
+  static void rlineto (ENV &env, PARAM& param) {}
+  static void hlineto (ENV &env, PARAM& param) {}
+  static void vlineto (ENV &env, PARAM& param) {}
+  static void rrcurveto (ENV &env, PARAM& param) {}
+  static void rcurveline (ENV &env, PARAM& param) {}
+  static void rlinecurve (ENV &env, PARAM& param) {}
+  static void vvcurveto (ENV &env, PARAM& param) {}
+  static void hhcurveto (ENV &env, PARAM& param) {}
+  static void vhcurveto (ENV &env, PARAM& param) {}
+  static void hvcurveto (ENV &env, PARAM& param) {}
+  static void moveto (ENV &env, PARAM& param, const point_t &pt) {}
+  static void line (ENV &env, PARAM& param, const point_t &pt1) {}
+  static void curve (ENV &env, PARAM& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) {}
+  static void hflex (ENV &env, PARAM& param) {}
+  static void flex (ENV &env, PARAM& param) {}
+  static void hflex1 (ENV &env, PARAM& param) {}
+  static void flex1 (ENV &env, PARAM& param) {}
+};
+
+template <typename ARG, typename OPSET, typename ENV, typename PARAM, typename PATH=path_procs_null_t<ENV, PARAM> >
+struct cs_opset_t : opset_t<ARG>
+{
+  static void process_op (op_code_t op, ENV &env, PARAM& param)
+  {
+    switch (op) {
+
+      case OpCode_return:
+        env.returnFromSubr ();
+        break;
+      case OpCode_endchar:
+        OPSET::check_width (op, env, param);
+        env.set_endchar (true);
+        OPSET::flush_args_and_op (op, env, param);
+        break;
+
+      case OpCode_fixedcs:
+        env.argStack.push_fixed_from_substr (env.str_ref);
+        break;
+
+      case OpCode_callsubr:
+        env.callSubr (env.localSubrs, CSType_LocalSubr);
+        break;
+
+      case OpCode_callgsubr:
+        env.callSubr (env.globalSubrs, CSType_GlobalSubr);
+        break;
+
+      case OpCode_hstem:
+      case OpCode_hstemhm:
+        OPSET::check_width (op, env, param);
+        OPSET::process_hstem (op, env, param);
+        break;
+      case OpCode_vstem:
+      case OpCode_vstemhm:
+        OPSET::check_width (op, env, param);
+        OPSET::process_vstem (op, env, param);
+        break;
+      case OpCode_hintmask:
+      case OpCode_cntrmask:
+        OPSET::check_width (op, env, param);
+        OPSET::process_hintmask (op, env, param);
+        break;
+      case OpCode_rmoveto:
+        OPSET::check_width (op, env, param);
+        PATH::rmoveto (env, param);
+        OPSET::process_post_move (op, env, param);
+        break;
+      case OpCode_hmoveto:
+        OPSET::check_width (op, env, param);
+        PATH::hmoveto (env, param);
+        OPSET::process_post_move (op, env, param);
+        break;
+      case OpCode_vmoveto:
+        OPSET::check_width (op, env, param);
+        PATH::vmoveto (env, param);
+        OPSET::process_post_move (op, env, param);
+        break;
+      case OpCode_rlineto:
+        PATH::rlineto (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_hlineto:
+        PATH::hlineto (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_vlineto:
+        PATH::vlineto (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_rrcurveto:
+        PATH::rrcurveto (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_rcurveline:
+        PATH::rcurveline (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_rlinecurve:
+        PATH::rlinecurve (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_vvcurveto:
+        PATH::vvcurveto (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_hhcurveto:
+        PATH::hhcurveto (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_vhcurveto:
+        PATH::vhcurveto (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_hvcurveto:
+        PATH::hvcurveto (env, param);
+        process_post_path (op, env, param);
+        break;
+
+      case OpCode_hflex:
+        PATH::hflex (env, param);
+        OPSET::process_post_flex (op, env, param);
+        break;
+
+      case OpCode_flex:
+        PATH::flex (env, param);
+        OPSET::process_post_flex (op, env, param);
+        break;
+
+      case OpCode_hflex1:
+        PATH::hflex1 (env, param);
+        OPSET::process_post_flex (op, env, param);
+        break;
+
+      case OpCode_flex1:
+        PATH::flex1 (env, param);
+        OPSET::process_post_flex (op, env, param);
+        break;
+
+      default:
+        SUPER::process_op (op, env);
+        break;
+    }
+  }
+
+  static void process_hstem (op_code_t op, ENV &env, PARAM& param)
+  {
+    env.hstem_count += env.argStack.get_count () / 2;
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void process_vstem (op_code_t op, ENV &env, PARAM& param)
+  {
+    env.vstem_count += env.argStack.get_count () / 2;
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void process_hintmask (op_code_t op, ENV &env, PARAM& param)
+  {
+    env.determine_hintmask_size ();
+    if (likely (env.str_ref.avail (env.hintmask_size)))
+    {
+      OPSET::flush_hintmask (op, env, param);
+      env.str_ref.inc (env.hintmask_size);
+    }
+  }
+
+  static void process_post_flex (op_code_t op, ENV &env, PARAM& param)
+  {
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void check_width (op_code_t op, ENV &env, PARAM& param)
+  {}
+
+  static void process_post_move (op_code_t op, ENV &env, PARAM& param)
+  {
+    if (!env.seen_moveto)
+    {
+      env.determine_hintmask_size ();
+      env.seen_moveto = true;
+    }
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void process_post_path (op_code_t op, ENV &env, PARAM& param)
+  {
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void flush_args_and_op (op_code_t op, ENV &env, PARAM& param)
+  {
+    OPSET::flush_args (env, param);
+    OPSET::flush_op (op, env, param);
+  }
+
+  static void flush_args (ENV &env, PARAM& param)
+  {
+    env.pop_n_args (env.argStack.get_count ());
+  }
+
+  static void flush_op (op_code_t op, ENV &env, PARAM& param)
+  {
+  }
+
+  static void flush_hintmask (op_code_t op, ENV &env, PARAM& param)
+  {
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static bool is_number_op (op_code_t op)
+  {
+    switch (op)
+    {
+      case OpCode_shortint:
+      case OpCode_fixedcs:
+      case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1:
+      case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3:
+      case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1:
+      case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3:
+        return true;
+
+      default:
+        /* 1-byte integer */
+        return (OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast);
+    }
+  }
+
+  protected:
+  typedef opset_t<ARG>  SUPER;
+};
+
+template <typename PATH, typename ENV, typename PARAM>
+struct path_procs_t
+{
+  static void rmoveto (ENV &env, PARAM& param)
+  {
+    point_t pt1 = env.get_pt ();
+    const number_t &dy = env.pop_arg ();
+    const number_t &dx = env.pop_arg ();
+    pt1.move (dx, dy);
+    PATH::moveto (env, param, pt1);
+  }
+
+  static void hmoveto (ENV &env, PARAM& param)
+  {
+    point_t pt1 = env.get_pt ();
+    pt1.move_x (env.pop_arg ());
+    PATH::moveto (env, param, pt1);
+  }
+
+  static void vmoveto (ENV &env, PARAM& param)
+  {
+    point_t pt1 = env.get_pt ();
+    pt1.move_y (env.pop_arg ());
+    PATH::moveto (env, param, pt1);
+  }
+
+  static void rlineto (ENV &env, PARAM& param)
+  {
+    for (unsigned int i = 0; i + 2 <= env.argStack.get_count (); i += 2)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+  }
+
+  static void hlineto (ENV &env, PARAM& param)
+  {
+    point_t pt1;
+    unsigned int i = 0;
+    for (; i + 2 <= env.argStack.get_count (); i += 2)
+    {
+      pt1 = env.get_pt ();
+      pt1.move_x (env.eval_arg (i));
+      PATH::line (env, param, pt1);
+      pt1.move_y (env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+    if (i < env.argStack.get_count ())
+    {
+      pt1 = env.get_pt ();
+      pt1.move_x (env.eval_arg (i));
+      PATH::line (env, param, pt1);
+    }
+  }
+
+  static void vlineto (ENV &env, PARAM& param)
+  {
+    point_t pt1;
+    unsigned int i = 0;
+    for (; i + 2 <= env.argStack.get_count (); i += 2)
+    {
+      pt1 = env.get_pt ();
+      pt1.move_y (env.eval_arg (i));
+      PATH::line (env, param, pt1);
+      pt1.move_x (env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+    if (i < env.argStack.get_count ())
+    {
+      pt1 = env.get_pt ();
+      pt1.move_y (env.eval_arg (i));
+      PATH::line (env, param, pt1);
+    }
+  }
+
+  static void rrcurveto (ENV &env, PARAM& param)
+  {
+    for (unsigned int i = 0; i + 6 <= env.argStack.get_count (); i += 6)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+  }
+
+  static void rcurveline (ENV &env, PARAM& param)
+  {
+    unsigned int i = 0;
+    for (; i + 6 <= env.argStack.get_count (); i += 6)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+    for (; i + 2 <= env.argStack.get_count (); i += 2)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+  }
+
+  static void rlinecurve (ENV &env, PARAM& param)
+  {
+    unsigned int i = 0;
+    unsigned int line_limit = (env.argStack.get_count () % 6);
+    for (; i + 2 <= line_limit; i += 2)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+    for (; i + 6 <= env.argStack.get_count (); i += 6)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+  }
+
+  static void vvcurveto (ENV &env, PARAM& param)
+  {
+    unsigned int i = 0;
+    point_t pt1 = env.get_pt ();
+    if ((env.argStack.get_count () & 1) != 0)
+      pt1.move_x (env.eval_arg (i++));
+    for (; i + 4 <= env.argStack.get_count (); i += 4)
+    {
+      pt1.move_y (env.eval_arg (i));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+      point_t pt3 = pt2;
+      pt3.move_y (env.eval_arg (i+3));
+      PATH::curve (env, param, pt1, pt2, pt3);
+      pt1 = env.get_pt ();
+    }
+  }
+
+  static void hhcurveto (ENV &env, PARAM& param)
+  {
+    unsigned int i = 0;
+    point_t pt1 = env.get_pt ();
+    if ((env.argStack.get_count () & 1) != 0)
+      pt1.move_y (env.eval_arg (i++));
+    for (; i + 4 <= env.argStack.get_count (); i += 4)
+    {
+      pt1.move_x (env.eval_arg (i));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+      point_t pt3 = pt2;
+      pt3.move_x (env.eval_arg (i+3));
+      PATH::curve (env, param, pt1, pt2, pt3);
+      pt1 = env.get_pt ();
+    }
+  }
+
+  static void vhcurveto (ENV &env, PARAM& param)
+  {
+    point_t pt1, pt2, pt3;
+    unsigned int i = 0;
+    if ((env.argStack.get_count () % 8) >= 4)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move_y (env.eval_arg (i));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+      point_t pt3 = pt2;
+      pt3.move_x (env.eval_arg (i+3));
+      i += 4;
+
+      for (; i + 8 <= env.argStack.get_count (); i += 8)
+      {
+        PATH::curve (env, param, pt1, pt2, pt3);
+        pt1 = env.get_pt ();
+        pt1.move_x (env.eval_arg (i));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+        pt3 = pt2;
+        pt3.move_y (env.eval_arg (i+3));
+        PATH::curve (env, param, pt1, pt2, pt3);
+
+        pt1 = pt3;
+        pt1.move_y (env.eval_arg (i+4));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
+        pt3 = pt2;
+        pt3.move_x (env.eval_arg (i+7));
+      }
+      if (i < env.argStack.get_count ())
+        pt3.move_y (env.eval_arg (i));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+    else
+    {
+      for (; i + 8 <= env.argStack.get_count (); i += 8)
+      {
+        pt1 = env.get_pt ();
+        pt1.move_y (env.eval_arg (i));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+        pt3 = pt2;
+        pt3.move_x (env.eval_arg (i+3));
+        PATH::curve (env, param, pt1, pt2, pt3);
+
+        pt1 = pt3;
+        pt1.move_x (env.eval_arg (i+4));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
+        pt3 = pt2;
+        pt3.move_y (env.eval_arg (i+7));
+        if ((env.argStack.get_count () - i < 16) && ((env.argStack.get_count () & 1) != 0))
+          pt3.move_x (env.eval_arg (i+8));
+        PATH::curve (env, param, pt1, pt2, pt3);
+      }
+    }
+  }
+
+  static void hvcurveto (ENV &env, PARAM& param)
+  {
+    point_t pt1, pt2, pt3;
+    unsigned int i = 0;
+    if ((env.argStack.get_count () % 8) >= 4)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move_x (env.eval_arg (i));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+      point_t pt3 = pt2;
+      pt3.move_y (env.eval_arg (i+3));
+      i += 4;
+
+      for (; i + 8 <= env.argStack.get_count (); i += 8)
+      {
+        PATH::curve (env, param, pt1, pt2, pt3);
+        pt1 = env.get_pt ();
+        pt1.move_y (env.eval_arg (i));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+        pt3 = pt2;
+        pt3.move_x (env.eval_arg (i+3));
+        PATH::curve (env, param, pt1, pt2, pt3);
+
+        pt1 = pt3;
+        pt1.move_x (env.eval_arg (i+4));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
+        pt3 = pt2;
+        pt3.move_y (env.eval_arg (i+7));
+      }
+      if (i < env.argStack.get_count ())
+        pt3.move_x (env.eval_arg (i));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+    else
+    {
+      for (; i + 8 <= env.argStack.get_count (); i += 8)
+      {
+        pt1 = env.get_pt ();
+        pt1.move_x (env.eval_arg (i));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+        pt3 = pt2;
+        pt3.move_y (env.eval_arg (i+3));
+        PATH::curve (env, param, pt1, pt2, pt3);
+
+        pt1 = pt3;
+        pt1.move_y (env.eval_arg (i+4));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
+        pt3 = pt2;
+        pt3.move_x (env.eval_arg (i+7));
+        if ((env.argStack.get_count () - i < 16) && ((env.argStack.get_count () & 1) != 0))
+          pt3.move_y (env.eval_arg (i+8));
+        PATH::curve (env, param, pt1, pt2, pt3);
+      }
+    }
+  }
+
+  /* default actions to be overridden */
+  static void moveto (ENV &env, PARAM& param, const point_t &pt)
+  { env.moveto (pt); }
+
+  static void line (ENV &env, PARAM& param, const point_t &pt1)
+  { PATH::moveto (env, param, pt1); }
+
+  static void curve (ENV &env, PARAM& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+  { PATH::moveto (env, param, pt3); }
+
+  static void hflex (ENV &env, PARAM& param)
+  {
+    if (likely (env.argStack.get_count () == 7))
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move_x (env.eval_arg (0));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (1), env.eval_arg (2));
+      point_t pt3 = pt2;
+      pt3.move_x (env.eval_arg (3));
+      point_t pt4 = pt3;
+      pt4.move_x (env.eval_arg (4));
+      point_t pt5 = pt4;
+      pt5.move_x (env.eval_arg (5));
+      pt5.y = pt1.y;
+      point_t pt6 = pt5;
+      pt6.move_x (env.eval_arg (6));
+
+      curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6);
+    }
+    else
+      env.set_error ();
+  }
+
+  static void flex (ENV &env, PARAM& param)
+  {
+    if (likely (env.argStack.get_count () == 13))
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (0), env.eval_arg (1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (2), env.eval_arg (3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (4), env.eval_arg (5));
+      point_t pt4 = pt3;
+      pt4.move (env.eval_arg (6), env.eval_arg (7));
+      point_t pt5 = pt4;
+      pt5.move (env.eval_arg (8), env.eval_arg (9));
+      point_t pt6 = pt5;
+      pt6.move (env.eval_arg (10), env.eval_arg (11));
+
+      curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6);
+    }
+    else
+      env.set_error ();
+  }
+
+  static void hflex1 (ENV &env, PARAM& param)
+  {
+    if (likely (env.argStack.get_count () == 9))
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (0), env.eval_arg (1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (2), env.eval_arg (3));
+      point_t pt3 = pt2;
+      pt3.move_x (env.eval_arg (4));
+      point_t pt4 = pt3;
+      pt4.move_x (env.eval_arg (5));
+      point_t pt5 = pt4;
+      pt5.move (env.eval_arg (6), env.eval_arg (7));
+      point_t pt6 = pt5;
+      pt6.move_x (env.eval_arg (8));
+      pt6.y = env.get_pt ().y;
+
+      curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6);
+    }
+    else
+      env.set_error ();
+  }
+
+  static void flex1 (ENV &env, PARAM& param)
+  {
+    if (likely (env.argStack.get_count () == 11))
+    {
+      point_t d;
+      d.init ();
+      for (unsigned int i = 0; i < 10; i += 2)
+        d.move (env.eval_arg (i), env.eval_arg (i+1));
+
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (0), env.eval_arg (1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (2), env.eval_arg (3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (4), env.eval_arg (5));
+      point_t pt4 = pt3;
+      pt4.move (env.eval_arg (6), env.eval_arg (7));
+      point_t pt5 = pt4;
+      pt5.move (env.eval_arg (8), env.eval_arg (9));
+      point_t pt6 = pt5;
+
+      if (fabs (d.x.to_real ()) > fabs (d.y.to_real ()))
+      {
+        pt6.move_x (env.eval_arg (10));
+        pt6.y = env.get_pt ().y;
+      }
+      else
+      {
+        pt6.x = env.get_pt ().x;
+        pt6.move_y (env.eval_arg (10));
+      }
+
+      curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6);
+    }
+    else
+      env.set_error ();
+  }
+
+  protected:
+  static void curve2 (ENV &env, PARAM& param,
+                      const point_t &pt1, const point_t &pt2, const point_t &pt3,
+                      const point_t &pt4, const point_t &pt5, const point_t &pt6)
+  {
+    PATH::curve (env, param, pt1, pt2, pt3);
+    PATH::curve (env, param, pt4, pt5, pt6);
+  }
+};
+
+template <typename ENV, typename OPSET, typename PARAM>
+struct cs_interpreter_t : interpreter_t<ENV>
+{
+  bool interpret (PARAM& param)
+  {
+    SUPER::env.set_endchar (false);
+
+    for (;;) {
+      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
+      if (unlikely (SUPER::env.in_error ()))
+        return false;
+      if (SUPER::env.is_endchar ())
+        break;
+    }
+
+    return true;
+  }
+
+  private:
+  typedef interpreter_t<ENV> SUPER;
+};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF_INTERP_CS_COMMON_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff-interp-dict-common.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,294 @@
+/*
+ * 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_DICT_COMMON_HH
+#define HB_CFF_INTERP_DICT_COMMON_HH
+
+#include "hb-cff-interp-common.hh"
+#include <math.h>
+#include <float.h>
+
+namespace CFF {
+
+using namespace OT;
+
+/* an opstr and the parsed out dict value(s) */
+struct dict_val_t : op_str_t
+{
+  void init () { single_val.set_int (0); }
+  void fini () {}
+
+  number_t            single_val;
+};
+
+typedef dict_val_t num_dict_val_t;
+
+template <typename VAL> struct dict_values_t : parsed_values_t<VAL> {};
+
+template <typename OPSTR=op_str_t>
+struct top_dict_values_t : dict_values_t<OPSTR>
+{
+  void init ()
+  {
+    dict_values_t<OPSTR>::init ();
+    charStringsOffset = 0;
+    FDArrayOffset = 0;
+  }
+  void fini () { dict_values_t<OPSTR>::fini (); }
+
+  unsigned int calculate_serialized_op_size (const OPSTR& opstr) const
+  {
+    switch (opstr.op)
+    {
+      case OpCode_CharStrings:
+      case OpCode_FDArray:
+        return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
+
+      default:
+        return opstr.str.length;
+    }
+  }
+
+  unsigned int  charStringsOffset;
+  unsigned int  FDArrayOffset;
+};
+
+struct dict_opset_t : opset_t<number_t>
+{
+  static void process_op (op_code_t op, interp_env_t<number_t>& env)
+  {
+    switch (op) {
+      case OpCode_longintdict:  /* 5-byte integer */
+        env.argStack.push_longint_from_substr (env.str_ref);
+        break;
+
+      case OpCode_BCD:  /* real number */
+        env.argStack.push_real (parse_bcd (env.str_ref));
+        break;
+
+      default:
+        opset_t<number_t>::process_op (op, env);
+        break;
+    }
+  }
+
+  static double parse_bcd (byte_str_ref_t& str_ref)
+  {
+    bool    neg = false;
+    double  int_part = 0;
+    uint64_t frac_part = 0;
+    uint32_t  frac_count = 0;
+    bool    exp_neg = false;
+    uint32_t  exp_part = 0;
+    bool    exp_overflow = false;
+    enum Part { INT_PART=0, FRAC_PART, EXP_PART } part = INT_PART;
+    enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END };
+    const uint64_t MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 1^52-1 */
+    const uint32_t MAX_EXP = 0x7FFu; /* 1^11-1 */
+
+    double  value = 0.0;
+    unsigned char byte = 0;
+    for (uint32_t i = 0;; i++)
+    {
+      char d;
+      if ((i & 1) == 0)
+      {
+        if (!str_ref.avail ())
+        {
+          str_ref.set_error ();
+          return 0.0;
+        }
+        byte = str_ref[0];
+        str_ref.inc ();
+        d = byte >> 4;
+      }
+      else
+        d = byte & 0x0F;
+
+      switch (d)
+      {
+        case RESERVED:
+          str_ref.set_error ();
+          return value;
+
+        case END:
+          value = (double)(neg? -int_part: int_part);
+          if (frac_count > 0)
+          {
+            double frac = (frac_part / pow (10.0, (double)frac_count));
+            if (neg) frac = -frac;
+            value += frac;
+          }
+          if (unlikely (exp_overflow))
+          {
+            if (value == 0.0)
+              return value;
+            if (exp_neg)
+              return neg? -DBL_MIN: DBL_MIN;
+            else
+              return neg? -DBL_MAX: DBL_MAX;
+          }
+          if (exp_part != 0)
+          {
+            if (exp_neg)
+              value /= pow (10.0, (double)exp_part);
+            else
+              value *= pow (10.0, (double)exp_part);
+          }
+          return value;
+
+        case NEG:
+          if (i != 0)
+          {
+            str_ref.set_error ();
+            return 0.0;
+          }
+          neg = true;
+          break;
+
+        case DECIMAL:
+          if (part != INT_PART)
+          {
+            str_ref.set_error ();
+            return value;
+          }
+          part = FRAC_PART;
+          break;
+
+        case EXP_NEG:
+          exp_neg = true;
+          HB_FALLTHROUGH;
+
+        case EXP_POS:
+          if (part == EXP_PART)
+          {
+            str_ref.set_error ();
+            return value;
+          }
+          part = EXP_PART;
+          break;
+
+        default:
+          switch (part) {
+            default:
+            case INT_PART:
+              int_part = (int_part * 10) + d;
+              break;
+
+            case FRAC_PART:
+              if (likely (frac_part <= MAX_FRACT / 10))
+              {
+                frac_part = (frac_part * 10) + (unsigned)d;
+                frac_count++;
+              }
+              break;
+
+            case EXP_PART:
+              if (likely (exp_part * 10 + d <= MAX_EXP))
+              {
+                exp_part = (exp_part * 10) + d;
+              }
+              else
+                exp_overflow = true;
+              break;
+          }
+      }
+    }
+
+    return value;
+  }
+
+  static bool is_hint_op (op_code_t op)
+  {
+    switch (op)
+    {
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_ForceBold:
+      case OpCode_LanguageGroup:
+      case OpCode_ExpansionFactor:
+        return true;
+      default:
+        return false;
+    }
+  }
+};
+
+template <typename VAL=op_str_t>
+struct top_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, interp_env_t<number_t>& env, top_dict_values_t<VAL> & dictval)
+  {
+    switch (op) {
+      case OpCode_CharStrings:
+        dictval.charStringsOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+      case OpCode_FDArray:
+        dictval.FDArrayOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+      case OpCode_FontMatrix:
+        env.clear_args ();
+        break;
+      default:
+        dict_opset_t::process_op (op, env);
+        break;
+    }
+  }
+};
+
+template <typename OPSET, typename PARAM, typename ENV=num_interp_env_t>
+struct dict_interpreter_t : interpreter_t<ENV>
+{
+  bool interpret (PARAM& param)
+  {
+    param.init ();
+    while (SUPER::env.str_ref.avail ())
+    {
+      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
+      if (unlikely (SUPER::env.in_error ()))
+        return false;
+    }
+
+    return true;
+  }
+
+  private:
+  typedef interpreter_t<ENV> SUPER;
+};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF_INTERP_DICT_COMMON_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff1-interp-cs.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,161 @@
+/*
+ * 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_CFF1_INTERP_CS_HH
+#define HB_CFF1_INTERP_CS_HH
+
+#include "hb.hh"
+#include "hb-cff-interp-cs-common.hh"
+
+namespace CFF {
+
+using namespace OT;
+
+typedef biased_subrs_t<CFF1Subrs>   cff1_biased_subrs_t;
+
+struct cff1_cs_interp_env_t : cs_interp_env_t<number_t, CFF1Subrs>
+{
+  template <typename ACC>
+  void init (const byte_str_t &str, ACC &acc, unsigned int fd)
+  {
+    SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
+    processed_width = false;
+    has_width = false;
+    arg_start = 0;
+    in_seac = false;
+  }
+
+  void fini () { SUPER::fini (); }
+
+  void set_width (bool has_width_)
+  {
+    if (likely (!processed_width && (SUPER::argStack.get_count () > 0)))
+    {
+      if (has_width_)
+      {
+        width = SUPER::argStack[0];
+        has_width = true;
+        arg_start = 1;
+      }
+    }
+    processed_width = true;
+  }
+
+  void clear_args ()
+  {
+    arg_start = 0;
+    SUPER::clear_args ();
+  }
+
+  void set_in_seac (bool _in_seac) { in_seac = _in_seac; }
+
+  bool    processed_width;
+  bool    has_width;
+  unsigned int  arg_start;
+  number_t      width;
+  bool    in_seac;
+
+  private:
+  typedef cs_interp_env_t<number_t, CFF1Subrs> SUPER;
+};
+
+template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff1_cs_interp_env_t, PARAM> >
+struct cff1_cs_opset_t : cs_opset_t<number_t, OPSET, cff1_cs_interp_env_t, PARAM, PATH>
+{
+  /* PostScript-originated legacy opcodes (OpCode_add etc) are unsupported */
+  /* Type 1-originated deprecated opcodes, seac behavior of endchar and dotsection are supported */
+
+  static void process_op (op_code_t op, cff1_cs_interp_env_t &env, PARAM& param)
+  {
+    switch (op) {
+      case OpCode_dotsection:
+        SUPER::flush_args_and_op (op, env, param);
+        break;
+
+      case OpCode_endchar:
+        OPSET::check_width (op, env, param);
+        if (env.argStack.get_count () >= 4)
+        {
+          OPSET::process_seac (env, param);
+        }
+        OPSET::flush_args_and_op (op, env, param);
+        env.set_endchar (true);
+        break;
+
+      default:
+        SUPER::process_op (op, env, param);
+    }
+  }
+
+  static void check_width (op_code_t op, cff1_cs_interp_env_t &env, PARAM& param)
+  {
+    if (!env.processed_width)
+    {
+      bool  has_width = false;
+      switch (op)
+      {
+        case OpCode_endchar:
+        case OpCode_hstem:
+        case OpCode_hstemhm:
+        case OpCode_vstem:
+        case OpCode_vstemhm:
+        case OpCode_hintmask:
+        case OpCode_cntrmask:
+          has_width = ((env.argStack.get_count () & 1) != 0);
+          break;
+        case OpCode_hmoveto:
+        case OpCode_vmoveto:
+          has_width = (env.argStack.get_count () > 1);
+          break;
+        case OpCode_rmoveto:
+          has_width = (env.argStack.get_count () > 2);
+          break;
+        default:
+          return;
+      }
+      env.set_width (has_width);
+    }
+  }
+
+  static void process_seac (cff1_cs_interp_env_t &env, PARAM& param)
+  {
+  }
+
+  static void flush_args (cff1_cs_interp_env_t &env, PARAM& param)
+  {
+    SUPER::flush_args (env, param);
+    env.clear_args ();  /* pop off width */
+  }
+
+  private:
+  typedef cs_opset_t<number_t, OPSET, cff1_cs_interp_env_t, PARAM, PATH>  SUPER;
+};
+
+template <typename OPSET, typename PARAM>
+struct cff1_cs_interpreter_t : cs_interpreter_t<cff1_cs_interp_env_t, OPSET, PARAM> {};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF1_INTERP_CS_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff2-interp-cs.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,271 @@
+/*
+ * 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_CFF2_INTERP_CS_HH
+#define HB_CFF2_INTERP_CS_HH
+
+#include "hb.hh"
+#include "hb-cff-interp-cs-common.hh"
+
+namespace CFF {
+
+using namespace OT;
+
+struct blend_arg_t : number_t
+{
+  void init ()
+  {
+    number_t::init ();
+    deltas.init ();
+  }
+
+  void fini ()
+  {
+    number_t::fini ();
+    deltas.fini_deep ();
+  }
+
+  void set_int (int v) { reset_blends (); number_t::set_int (v); }
+  void set_fixed (int32_t v) { reset_blends (); number_t::set_fixed (v); }
+  void set_real (double v) { reset_blends (); number_t::set_real (v); }
+
+  void set_blends (unsigned int numValues_, unsigned int valueIndex_,
+                          unsigned int numBlends, hb_array_t<const blend_arg_t> blends_)
+  {
+    numValues = numValues_;
+    valueIndex = valueIndex_;
+    deltas.resize (numBlends);
+    for (unsigned int i = 0; i < numBlends; i++)
+      deltas[i] = blends_[i];
+  }
+
+  bool blending () const { return deltas.length > 0; }
+  void reset_blends ()
+  {
+    numValues = valueIndex = 0;
+    deltas.resize (0);
+  }
+
+  unsigned int numValues;
+  unsigned int valueIndex;
+  hb_vector_t<number_t> deltas;
+};
+
+typedef interp_env_t<blend_arg_t> BlendInterpEnv;
+typedef biased_subrs_t<CFF2Subrs>   cff2_biased_subrs_t;
+
+struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
+{
+  template <typename ACC>
+  void init (const byte_str_t &str, ACC &acc, unsigned int fd,
+                    const int *coords_=nullptr, unsigned int num_coords_=0)
+  {
+    SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
+
+    coords = coords_;
+    num_coords = num_coords_;
+    varStore = acc.varStore;
+    seen_blend = false;
+    seen_vsindex_ = false;
+    scalars.init ();
+    do_blend = (coords != nullptr) && num_coords && (varStore != &Null(CFF2VariationStore));
+    set_ivs (acc.privateDicts[fd].ivs);
+  }
+
+  void fini ()
+  {
+    scalars.fini ();
+    SUPER::fini ();
+  }
+
+  op_code_t fetch_op ()
+  {
+    if (this->str_ref.avail ())
+      return SUPER::fetch_op ();
+
+    /* make up return or endchar op */
+    if (this->callStack.is_empty ())
+      return OpCode_endchar;
+    else
+      return OpCode_return;
+  }
+
+  const blend_arg_t& eval_arg (unsigned int i)
+  {
+    blend_arg_t  &arg = argStack[i];
+    blend_arg (arg);
+    return arg;
+  }
+
+  const blend_arg_t& pop_arg ()
+  {
+    blend_arg_t  &arg = argStack.pop ();
+    blend_arg (arg);
+    return arg;
+  }
+
+  void process_blend ()
+  {
+    if (!seen_blend)
+    {
+      region_count = varStore->varStore.get_region_index_count (get_ivs ());
+      if (do_blend)
+      {
+        scalars.resize (region_count);
+        varStore->varStore.get_scalars (get_ivs (),
+                                        (int *)coords, num_coords,
+                                        &scalars[0], region_count);
+      }
+      seen_blend = true;
+    }
+  }
+
+  void process_vsindex ()
+  {
+    unsigned int  index = argStack.pop_uint ();
+    if (unlikely (seen_vsindex () || seen_blend))
+    {
+      set_error ();
+    }
+    else
+    {
+      set_ivs (index);
+    }
+    seen_vsindex_ = true;
+  }
+
+  unsigned int get_region_count () const { return region_count; }
+  void   set_region_count (unsigned int region_count_) { region_count = region_count_; }
+  unsigned int get_ivs () const { return ivs; }
+  void   set_ivs (unsigned int ivs_) { ivs = ivs_; }
+  bool   seen_vsindex () const { return seen_vsindex_; }
+
+  protected:
+  void blend_arg (blend_arg_t &arg)
+  {
+    if (do_blend && arg.blending ())
+    {
+      if (likely (scalars.length == arg.deltas.length))
+      {
+        double v = arg.to_real ();
+        for (unsigned int i = 0; i < scalars.length; i++)
+        {
+          v += (double)scalars[i] * arg.deltas[i].to_real ();
+        }
+        arg.set_real (v);
+        arg.deltas.resize (0);
+      }
+    }
+  }
+
+  protected:
+  const int     *coords;
+  unsigned int  num_coords;
+  const  CFF2VariationStore *varStore;
+  unsigned int  region_count;
+  unsigned int  ivs;
+  hb_vector_t<float>  scalars;
+  bool    do_blend;
+  bool    seen_vsindex_;
+  bool    seen_blend;
+
+  typedef cs_interp_env_t<blend_arg_t, CFF2Subrs> SUPER;
+};
+template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t, PARAM> >
+struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH>
+{
+  static void process_op (op_code_t op, cff2_cs_interp_env_t &env, PARAM& param)
+  {
+    switch (op) {
+      case OpCode_callsubr:
+      case OpCode_callgsubr:
+        /* a subroutine number shoudln't be a blended value */
+        if (unlikely (env.argStack.peek ().blending ()))
+        {
+          env.set_error ();
+          break;
+        }
+        SUPER::process_op (op, env, param);
+        break;
+
+      case OpCode_blendcs:
+        OPSET::process_blend (env, param);
+        break;
+
+      case OpCode_vsindexcs:
+        if (unlikely (env.argStack.peek ().blending ()))
+        {
+          env.set_error ();
+          break;
+        }
+        OPSET::process_vsindex (env, param);
+        break;
+
+      default:
+        SUPER::process_op (op, env, param);
+    }
+  }
+
+  static void process_blend (cff2_cs_interp_env_t &env, PARAM& param)
+  {
+    unsigned int n, k;
+
+    env.process_blend ();
+    k = env.get_region_count ();
+    n = env.argStack.pop_uint ();
+    /* copy the blend values into blend array of the default values */
+    unsigned int start = env.argStack.get_count () - ((k+1) * n);
+    /* let an obvious error case fail, but note CFF2 spec doesn't forbid n==0 */
+    if (unlikely (start > env.argStack.get_count ()))
+    {
+      env.set_error ();
+      return;
+    }
+    for (unsigned int i = 0; i < n; i++)
+    {
+      const hb_array_t<const blend_arg_t>       blends = env.argStack.get_subarray (start + n + (i * k));
+      env.argStack[start + i].set_blends (n, i, k, blends);
+    }
+
+    /* pop off blend values leaving default values now adorned with blend values */
+    env.argStack.pop (k * n);
+  }
+
+  static void process_vsindex (cff2_cs_interp_env_t &env, PARAM& param)
+  {
+    env.process_vsindex ();
+    env.clear_args ();
+  }
+
+  private:
+  typedef cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH>  SUPER;
+};
+
+template <typename OPSET, typename PARAM>
+struct cff2_cs_interpreter_t : cs_interpreter_t<cff2_cs_interp_env_t, OPSET, PARAM> {};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF2_INTERP_CS_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -26,10 +26,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-mutex-private.hh"
-#include "hb-object-private.hh"
+#include "hb-machinery.hh"
 
 #include <locale.h>
 #ifdef HAVE_XLOCALE_H
@@ -37,22 +36,51 @@
 #endif
 
 
+/**
+ * SECTION:hb-common
+ * @title: hb-common
+ * @short_description: Common data types
+ * @include: hb.h
+ *
+ * Common data types used across HarfBuzz are defined here.
+ **/
+
+
 /* hb_options_t */
 
-hb_options_union_t _hb_options;
+hb_atomic_int_t _hb_options;
 
 void
-_hb_options_init (void)
+_hb_options_init ()
 {
   hb_options_union_t u;
   u.i = 0;
-  u.opts.initialized = 1;
+  u.opts.initialized = true;
+
+  const char *c = getenv ("HB_OPTIONS");
+  if (c)
+  {
+    while (*c)
+    {
+      const char *p = strchr (c, ':');
+      if (!p)
+        p = c + strlen (c);
 
-  char *c = getenv ("HB_OPTIONS");
-  u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible");
+#define OPTION(name, symbol) \
+        if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) u.opts.symbol = true;
+
+      OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible);
+      OPTION ("aat", aat);
+
+#undef OPTION
+
+      c = *p ? p + 1 : p;
+    }
+
+  }
 
   /* This is idempotent and threadsafe. */
-  _hb_options = u;
+  _hb_options.set_relaxed (u.i);
 }
 
 
@@ -176,7 +204,7 @@
    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,  '-',  0,   0,
   '0', '1', '2', '3', '4', '5', '6', '7',  '8', '9',  0,   0,   0,   0,   0,   0,
-  '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+   0,  'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,  '-',
    0,  'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,   0
@@ -219,11 +247,10 @@
   struct hb_language_item_t *next;
   hb_language_t lang;
 
-  inline bool operator == (const char *s) const {
-    return lang_equal (lang, s);
-  }
+  bool operator == (const char *s) const
+  { return lang_equal (lang, s); }
 
-  inline hb_language_item_t & operator = (const char *s) {
+  hb_language_item_t & operator = (const char *s) {
     /* If a custom allocated is used calling strdup() pairs
     badly with a call to the custom free() in fini() below.
     Therefore don't call strdup(), implement its behavior.
@@ -240,21 +267,21 @@
     return *this;
   }
 
-  void fini (void) { free ((void *) lang); }
+  void fini () { free ((void *) lang); }
 };
 
 
 /* Thread-safe lock-free language list */
 
-static hb_language_item_t *langs;
+static hb_atomic_ptr_t <hb_language_item_t> langs;
 
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
 static void
-free_langs (void)
+free_langs ()
 {
 retry:
-  hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs);
-  if (!hb_atomic_ptr_cmpexch (&langs, first_lang, nullptr))
+  hb_language_item_t *first_lang = langs;
+  if (unlikely (!langs.cmpexch (first_lang, nullptr)))
     goto retry;
 
   while (first_lang) {
@@ -270,7 +297,7 @@
 lang_find_or_insert (const char *key)
 {
 retry:
-  hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs);
+  hb_language_item_t *first_lang = langs;
 
   for (hb_language_item_t *lang = first_lang; lang; lang = lang->next)
     if (*lang == key)
@@ -288,13 +315,14 @@
     return nullptr;
   }
 
-  if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) {
+  if (unlikely (!langs.cmpexch (first_lang, lang)))
+  {
     lang->fini ();
     free (lang);
     goto retry;
   }
 
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
   if (!first_lang)
     atexit (free_langs); /* First person registers atexit() callback. */
 #endif
@@ -306,14 +334,14 @@
 /**
  * hb_language_from_string:
  * @str: (array length=len) (element-type uint8_t): a string representing
- *       ISO 639 language code
+ *       a BCP 47 language tag
  * @len: length of the @str, or -1 if it is %NULL-terminated.
  *
- * Converts @str representing an ISO 639 language code to the corresponding
+ * Converts @str representing a BCP 47 language tag to the corresponding
  * #hb_language_t.
  *
  * Return value: (transfer none):
- * The #hb_language_t corresponding to the ISO 639 language code.
+ * The #hb_language_t corresponding to the BCP 47 language tag.
  *
  * Since: 0.9.2
  **/
@@ -361,24 +389,32 @@
 /**
  * hb_language_get_default:
  *
+ * Get default language from current locale.
  *
+ * Note that the first time this function is called, it calls
+ * "setlocale (LC_CTYPE, nullptr)" to fetch current locale.  The underlying
+ * setlocale function is, in many implementations, NOT threadsafe.  To avoid
+ * problems, call this function once before multiple threads can call it.
+ * This function is only used from hb_buffer_guess_segment_properties() by
+ * HarfBuzz itself.
  *
  * Return value: (transfer none):
  *
  * Since: 0.9.2
  **/
 hb_language_t
-hb_language_get_default (void)
+hb_language_get_default ()
 {
-  static hb_language_t default_language = HB_LANGUAGE_INVALID;
+  static hb_atomic_ptr_t <hb_language_t> default_language;
 
-  hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
-  if (unlikely (language == HB_LANGUAGE_INVALID)) {
+  hb_language_t language = default_language;
+  if (unlikely (language == HB_LANGUAGE_INVALID))
+  {
     language = hb_language_from_string (setlocale (LC_CTYPE, nullptr), -1);
-    (void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
+    (void) default_language.cmpexch (HB_LANGUAGE_INVALID, language);
   }
 
-  return default_language;
+  return language;
 }
 
 
@@ -530,7 +566,6 @@
 
     /* Unicode-8.0 additions */
     case HB_SCRIPT_HATRAN:
-    case HB_SCRIPT_OLD_HUNGARIAN:
 
     /* Unicode-9.0 additions */
     case HB_SCRIPT_ADLAM:
@@ -544,7 +579,9 @@
 
 
     /* https://github.com/harfbuzz/harfbuzz/issues/1000 */
+    case HB_SCRIPT_OLD_HUNGARIAN:
     case HB_SCRIPT_OLD_ITALIC:
+    case HB_SCRIPT_RUNIC:
 
       return HB_DIRECTION_INVALID;
   }
@@ -587,6 +624,19 @@
 
 /* hb_version */
 
+
+/**
+ * SECTION:hb-version
+ * @title: hb-version
+ * @short_description: Information about the version of HarfBuzz in use
+ * @include: hb.h
+ *
+ * These functions and macros allow accessing version of the HarfBuzz
+ * library used at compile- as well as run-time, and to direct code
+ * conditionally based on those versions, again, at compile- or run-time.
+ **/
+
+
 /**
  * hb_version:
  * @major: (out): Library major version component.
@@ -617,7 +667,7 @@
  * Since: 0.9.2
  **/
 const char *
-hb_version_string (void)
+hb_version_string ()
 {
   return HB_VERSION_STRING;
 }
@@ -729,47 +779,47 @@
 
 #ifdef USE_XLOCALE
 
-static HB_LOCALE_T C_locale;
+#if HB_USE_ATEXIT
+static void free_static_C_locale ();
+#endif
 
-#ifdef HB_USE_ATEXIT
-static void
-free_C_locale (void)
+static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer (HB_LOCALE_T),
+                                                          hb_C_locale_lazy_loader_t>
 {
-retry:
-  HB_LOCALE_T locale = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale);
+  static HB_LOCALE_T create ()
+  {
+    HB_LOCALE_T C_locale = HB_CREATE_LOCALE ("C");
+
+#if HB_USE_ATEXIT
+    atexit (free_static_C_locale);
+#endif
 
-  if (!hb_atomic_ptr_cmpexch (&C_locale, locale, nullptr))
-    goto retry;
+    return C_locale;
+  }
+  static void destroy (HB_LOCALE_T p)
+  {
+    HB_FREE_LOCALE (p);
+  }
+  static HB_LOCALE_T get_null ()
+  {
+    return nullptr;
+  }
+} static_C_locale;
 
-  if (locale)
-    HB_FREE_LOCALE (locale);
+#if HB_USE_ATEXIT
+static
+void free_static_C_locale ()
+{
+  static_C_locale.free_instance ();
 }
 #endif
 
 static HB_LOCALE_T
-get_C_locale (void)
+get_C_locale ()
 {
-retry:
-  HB_LOCALE_T C = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale);
-
-  if (unlikely (!C))
-  {
-    C = HB_CREATE_LOCALE ("C");
-
-    if (!hb_atomic_ptr_cmpexch (&C_locale, nullptr, C))
-    {
-      HB_FREE_LOCALE (C_locale);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_C_locale); /* First person registers atexit() callback. */
-#endif
-  }
-
-  return C;
+  return static_C_locale.get_unconst ();
 }
-#endif
+#endif /* USE_XLOCALE */
 
 static bool
 parse_float (const char **pp, const char *end, float *pv)
@@ -846,7 +896,7 @@
   }
 
   const char *p = *pp;
-  while (*pp < end && ISALNUM(**pp))
+  while (*pp < end && (ISALNUM(**pp) || **pp == '_'))
     (*pp)++;
 
   if (p == *pp || *pp - p > 4)
@@ -875,15 +925,15 @@
 
   bool has_start;
 
-  feature->start = 0;
-  feature->end = (unsigned int) -1;
+  feature->start = HB_FEATURE_GLOBAL_START;
+  feature->end = HB_FEATURE_GLOBAL_END;
 
   if (!parse_char (pp, end, '['))
     return true;
 
   has_start = parse_uint (pp, end, &feature->start);
 
-  if (parse_char (pp, end, ':')) {
+  if (parse_char (pp, end, ':') || parse_char (pp, end, ';')) {
     parse_uint (pp, end, &feature->end);
   } else {
     if (has_start)
@@ -1063,10 +1113,19 @@
   while (len && s[len - 1] == ' ')
     len--;
   s[len++] = '=';
-  len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", variation->value));
+  len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value));
 
   assert (len < ARRAY_LENGTH (s));
   len = MIN (len, size - 1);
   memcpy (buf, s, len);
   buf[len] = '\0';
 }
+
+/* If there is no visibility control, then hb-static.cc will NOT
+ * define anything.  Instead, we get it to define one set in here
+ * only, so only libharfbuzz.so defines them, not other libs. */
+#ifdef HB_NO_VISIBILITY
+#undef HB_NO_VISIBILITY
+#include "hb-static.cc"
+#define HB_NO_VISIBILITY 1
+#endif
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.h	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.h	Fri Mar 01 16:59:19 2019 -0800
@@ -33,6 +33,10 @@
 #ifndef HB_COMMON_H
 #define HB_COMMON_H
 
+#ifndef HB_EXTERN
+#define HB_EXTERN extern
+#endif
+
 #ifndef HB_BEGIN_DECLS
 # ifdef __cplusplus
 #  define HB_BEGIN_DECLS        extern "C" {
@@ -63,6 +67,23 @@
 #  include <stdint.h>
 #endif
 
+#if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#define HB_DEPRECATED __attribute__((__deprecated__))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1300)
+#define HB_DEPRECATED __declspec(deprecated)
+#else
+#define HB_DEPRECATED
+#endif
+
+#if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+#define HB_DEPRECATED_FOR(f) __attribute__((__deprecated__("Use '" #f "' instead")))
+#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER > 140050320)
+#define HB_DEPRECATED_FOR(f) __declspec(deprecated("is deprecated. Use '" #f "' instead"))
+#else
+#define HB_DEPRECATED_FOR(f) HB_DEPRECATED
+#endif
+
+
 HB_BEGIN_DECLS
 
 
@@ -86,8 +107,8 @@
 
 typedef uint32_t hb_tag_t;
 
-#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint8_t)(c1))<<24)|(((uint8_t)(c2))<<16)|(((uint8_t)(c3))<<8)|((uint8_t)(c4))))
-#define HB_UNTAG(tag)   ((uint8_t)((tag)>>24)), ((uint8_t)((tag)>>16)), ((uint8_t)((tag)>>8)), ((uint8_t)(tag))
+#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint32_t)(c1)&0xFF)<<24)|(((uint32_t)(c2)&0xFF)<<16)|(((uint32_t)(c3)&0xFF)<<8)|((uint32_t)(c4)&0xFF)))
+#define HB_UNTAG(tag)   (uint8_t)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>16)&0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t)((tag)&0xFF)
 
 #define HB_TAG_NONE HB_TAG(0,0,0,0)
 #define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff)
@@ -340,13 +361,15 @@
   HB_SCRIPT_INVALID                             = HB_TAG_NONE,
 
   /* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t
-   * without risking undefined behavior.  Include both a signed and unsigned max,
-   * since technically enums are int, and indeed, hb_script_t ends up being signed.
+   * without risking undefined behavior.  We have two, for historical reasons.
+   * HB_TAG_MAX used to be unsigned, but that was invalid Ansi C, so was changed
+   * to _HB_SCRIPT_MAX_VALUE to be equal to HB_TAG_MAX_SIGNED as well.
+   *
    * See this thread for technicalities:
    *
    *   https://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html
    */
-  _HB_SCRIPT_MAX_VALUE                          = HB_TAG_MAX, /*< skip >*/
+  _HB_SCRIPT_MAX_VALUE                          = HB_TAG_MAX_SIGNED, /*< skip >*/
   _HB_SCRIPT_MAX_VALUE_SIGNED                   = HB_TAG_MAX_SIGNED /*< skip >*/
 
 } hb_script_t;
@@ -379,6 +402,19 @@
 
 /* Font features and variations. */
 
+/**
+ * HB_FEATURE_GLOBAL_START
+ *
+ * Since: 2.0.0
+ */
+#define HB_FEATURE_GLOBAL_START 0
+/**
+ * HB_FEATURE_GLOBAL_END
+ *
+ * Since: 2.0.0
+ */
+#define HB_FEATURE_GLOBAL_END   ((unsigned int) -1)
+
 typedef struct hb_feature_t {
   hb_tag_t      tag;
   uint32_t      value;
@@ -412,6 +448,50 @@
 hb_variation_to_string (hb_variation_t *variation,
                         char *buf, unsigned int size);
 
+/**
+ * hb_color_t:
+ *
+ * Data type for holding color values.
+ *
+ * Since: 2.1.0
+ */
+typedef uint32_t hb_color_t;
+
+#define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a)))
+
+/**
+ * hb_color_get_alpha:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
+#define hb_color_get_alpha(color)       ((color) & 0xFF)
+/**
+ * hb_color_get_red:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
+#define hb_color_get_red(color)         (((color) >> 8) & 0xFF)
+/**
+ * hb_color_get_green:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
+#define hb_color_get_green(color)       (((color) >> 16) & 0xFF)
+/**
+ * hb_color_get_blue:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
+#define hb_color_get_blue(color)        (((color) >> 24) & 0xFF)
+
 
 HB_END_DECLS
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-coretext.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-coretext.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -26,15 +26,23 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#define HB_SHAPER coretext
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-shaper-impl-private.hh"
+#include "hb.hh"
+#include "hb-shaper-impl.hh"
 
 #include "hb-coretext.h"
+#include "hb-aat-layout.hh"
 #include <math.h>
 
+
+/**
+ * SECTION:hb-coretext
+ * @title: hb-coretext
+ * @short_description: CoreText integration
+ * @include: hb-coretext.h
+ *
+ * Functions for using HarfBuzz with the CoreText fonts.
+ **/
+
 /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
 #define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
 
@@ -91,13 +99,8 @@
 }
 
 
-HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face)
-HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font,
-        fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) <= .5
-)
-
 static CTFontDescriptorRef
-get_last_resort_font_desc (void)
+get_last_resort_font_desc ()
 {
   // TODO Handle allocation failures?
   CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0);
@@ -211,7 +214,7 @@
   }
 
   CFURLRef original_url = nullptr;
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+#if TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
   ATSFontRef atsFont;
   FSRef fsref;
   OSStatus status;
@@ -241,7 +244,7 @@
        * process in Blink. This can be detected by the new file URL location
        * that the newly found font points to. */
       CFURLRef new_url = nullptr;
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+#if TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
       atsFont = CTFontGetPlatformFont (new_ct_font, NULL);
       status = ATSFontGetFileReference (atsFont, &fsref);
       if (status == noErr)
@@ -270,7 +273,7 @@
   return ct_font;
 }
 
-hb_coretext_shaper_face_data_t *
+hb_coretext_face_data_t *
 _hb_coretext_shaper_face_data_create (hb_face_t *face)
 {
   CGFontRef cg_font = create_cg_font (face);
@@ -281,11 +284,11 @@
     return nullptr;
   }
 
-  return (hb_coretext_shaper_face_data_t *) cg_font;
+  return (hb_coretext_face_data_t *) cg_font;
 }
 
 void
-_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
+_hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data)
 {
   CFRelease ((CGFontRef) data);
 }
@@ -302,17 +305,17 @@
 CGFontRef
 hb_coretext_face_get_cg_font (hb_face_t *face)
 {
-  if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
-  return (CGFontRef) HB_SHAPER_DATA_GET (face);
+  return (CGFontRef) (const void *) face->data.coretext;
 }
 
 
-hb_coretext_shaper_font_data_t *
+hb_coretext_font_data_t *
 _hb_coretext_shaper_font_data_create (hb_font_t *font)
 {
   hb_face_t *face = font->face;
-  if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
-  CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
+  const hb_coretext_face_data_t *face_data = face->data.coretext;
+  if (unlikely (!face_data)) return nullptr;
+  CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
 
   CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size_from_ptem (font->ptem));
 
@@ -322,15 +325,47 @@
     return nullptr;
   }
 
-  return (hb_coretext_shaper_font_data_t *) ct_font;
+  return (hb_coretext_font_data_t *) ct_font;
 }
 
 void
-_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
+_hb_coretext_shaper_font_data_destroy (hb_coretext_font_data_t *data)
 {
   CFRelease ((CTFontRef) data);
 }
 
+static const hb_coretext_font_data_t *
+hb_coretext_font_data_sync (hb_font_t *font)
+{
+retry:
+  const hb_coretext_font_data_t *data = font->data.coretext;
+  if (unlikely (!data)) return nullptr;
+
+  if (fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) > .5)
+  {
+    /* XXX-MT-bug
+     * Note that evaluating condition above can be dangerous if another thread
+     * got here first and destructed data.  That's, as always, bad use pattern.
+     * If you modify the font (change font size), other threads must not be
+     * using it at the same time.  However, since this check is delayed to
+     * when one actually tries to shape something, this is a XXX race condition
+     * (and the only one we have that I know of) right now.  Ie. you modify the
+     * font size in one thread, then (supposedly safely) try to use it from two
+     * or more threads and BOOM!  I'm not sure how to fix this.  We want RCU.
+     */
+
+    /* Drop and recreate. */
+    /* If someone dropped it in the mean time, throw it away and don't touch it.
+     * Otherwise, destruct it. */
+    if (likely (font->data.coretext.cmpexch (const_cast<hb_coretext_font_data_t *> (data), nullptr)))
+      _hb_coretext_shaper_font_data_destroy (const_cast<hb_coretext_font_data_t *> (data));
+    else
+      goto retry;
+  }
+  return font->data.coretext;
+}
+
+
 /*
  * Since: 1.7.2
  */
@@ -343,13 +378,13 @@
   hb_font_t *font = hb_font_create (face);
   hb_face_destroy (face);
 
-  if (unlikely (hb_object_is_inert (font)))
+  if (unlikely (hb_object_is_immutable (font)))
     return font;
 
   hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font)));
 
   /* Let there be dragons here... */
-  HB_SHAPER_DATA_GET (font) = (hb_coretext_shaper_font_data_t *) CFRetain (ct_font);
+  font->data.coretext.cmpexch (nullptr, (hb_coretext_font_data_t *) CFRetain (ct_font));
 
   return font;
 }
@@ -357,31 +392,8 @@
 CTFontRef
 hb_coretext_font_get_ct_font (hb_font_t *font)
 {
-  if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return nullptr;
-  return (CTFontRef) HB_SHAPER_DATA_GET (font);
-}
-
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_coretext_shaper_shape_plan_data_t {};
-
-hb_coretext_shaper_shape_plan_data_t *
-_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-                                             const hb_feature_t *user_features HB_UNUSED,
-                                             unsigned int        num_user_features HB_UNUSED,
-                                             const int          *coords HB_UNUSED,
-                                             unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED)
-{
+  const hb_coretext_font_data_t *data = hb_coretext_font_data_sync (font);
+  return data ? (CTFontRef) data : nullptr;
 }
 
 
@@ -432,183 +444,6 @@
 };
 
 
-/* The following enum members are added in OS X 10.8. */
-#define kAltHalfWidthTextSelector               6
-#define kAltProportionalTextSelector            5
-#define kAlternateHorizKanaOffSelector          1
-#define kAlternateHorizKanaOnSelector           0
-#define kAlternateKanaType                      34
-#define kAlternateVertKanaOffSelector           3
-#define kAlternateVertKanaOnSelector            2
-#define kCaseSensitiveLayoutOffSelector         1
-#define kCaseSensitiveLayoutOnSelector          0
-#define kCaseSensitiveLayoutType                33
-#define kCaseSensitiveSpacingOffSelector        3
-#define kCaseSensitiveSpacingOnSelector         2
-#define kContextualAlternatesOffSelector        1
-#define kContextualAlternatesOnSelector         0
-#define kContextualAlternatesType               36
-#define kContextualLigaturesOffSelector         19
-#define kContextualLigaturesOnSelector          18
-#define kContextualSwashAlternatesOffSelector   5
-#define kContextualSwashAlternatesOnSelector    4
-#define kDefaultLowerCaseSelector               0
-#define kDefaultUpperCaseSelector               0
-#define kHistoricalLigaturesOffSelector         21
-#define kHistoricalLigaturesOnSelector          20
-#define kHojoCharactersSelector                 12
-#define kJIS2004CharactersSelector              11
-#define kLowerCasePetiteCapsSelector            2
-#define kLowerCaseSmallCapsSelector             1
-#define kLowerCaseType                          37
-#define kMathematicalGreekOffSelector           11
-#define kMathematicalGreekOnSelector            10
-#define kNLCCharactersSelector                  13
-#define kQuarterWidthTextSelector               4
-#define kScientificInferiorsSelector            4
-#define kStylisticAltEightOffSelector           17
-#define kStylisticAltEightOnSelector            16
-#define kStylisticAltEighteenOffSelector        37
-#define kStylisticAltEighteenOnSelector         36
-#define kStylisticAltElevenOffSelector          23
-#define kStylisticAltElevenOnSelector           22
-#define kStylisticAltFifteenOffSelector         31
-#define kStylisticAltFifteenOnSelector          30
-#define kStylisticAltFiveOffSelector            11
-#define kStylisticAltFiveOnSelector             10
-#define kStylisticAltFourOffSelector            9
-#define kStylisticAltFourOnSelector             8
-#define kStylisticAltFourteenOffSelector        29
-#define kStylisticAltFourteenOnSelector         28
-#define kStylisticAltNineOffSelector            19
-#define kStylisticAltNineOnSelector             18
-#define kStylisticAltNineteenOffSelector        39
-#define kStylisticAltNineteenOnSelector         38
-#define kStylisticAltOneOffSelector             3
-#define kStylisticAltOneOnSelector              2
-#define kStylisticAltSevenOffSelector           15
-#define kStylisticAltSevenOnSelector            14
-#define kStylisticAltSeventeenOffSelector       35
-#define kStylisticAltSeventeenOnSelector        34
-#define kStylisticAltSixOffSelector             13
-#define kStylisticAltSixOnSelector              12
-#define kStylisticAltSixteenOffSelector         33
-#define kStylisticAltSixteenOnSelector          32
-#define kStylisticAltTenOffSelector             21
-#define kStylisticAltTenOnSelector              20
-#define kStylisticAltThirteenOffSelector        27
-#define kStylisticAltThirteenOnSelector         26
-#define kStylisticAltThreeOffSelector           7
-#define kStylisticAltThreeOnSelector            6
-#define kStylisticAltTwelveOffSelector          25
-#define kStylisticAltTwelveOnSelector           24
-#define kStylisticAltTwentyOffSelector          41
-#define kStylisticAltTwentyOnSelector           40
-#define kStylisticAltTwoOffSelector             5
-#define kStylisticAltTwoOnSelector              4
-#define kStylisticAlternativesType              35
-#define kSwashAlternatesOffSelector             3
-#define kSwashAlternatesOnSelector              2
-#define kThirdWidthTextSelector                 3
-#define kTraditionalNamesCharactersSelector     14
-#define kUpperCasePetiteCapsSelector            2
-#define kUpperCaseSmallCapsSelector             1
-#define kUpperCaseType                          38
-
-/* Table data courtesy of Apple. */
-static const struct feature_mapping_t {
-    FourCharCode otFeatureTag;
-    uint16_t aatFeatureType;
-    uint16_t selectorToEnable;
-    uint16_t selectorToDisable;
-} feature_mappings[] = {
-    { 'c2pc',   kUpperCaseType,             kUpperCasePetiteCapsSelector,           kDefaultUpperCaseSelector },
-    { 'c2sc',   kUpperCaseType,             kUpperCaseSmallCapsSelector,            kDefaultUpperCaseSelector },
-    { 'calt',   kContextualAlternatesType,  kContextualAlternatesOnSelector,        kContextualAlternatesOffSelector },
-    { 'case',   kCaseSensitiveLayoutType,   kCaseSensitiveLayoutOnSelector,         kCaseSensitiveLayoutOffSelector },
-    { 'clig',   kLigaturesType,             kContextualLigaturesOnSelector,         kContextualLigaturesOffSelector },
-    { 'cpsp',   kCaseSensitiveLayoutType,   kCaseSensitiveSpacingOnSelector,        kCaseSensitiveSpacingOffSelector },
-    { 'cswh',   kContextualAlternatesType,  kContextualSwashAlternatesOnSelector,   kContextualSwashAlternatesOffSelector },
-    { 'dlig',   kLigaturesType,             kRareLigaturesOnSelector,               kRareLigaturesOffSelector },
-    { 'expt',   kCharacterShapeType,        kExpertCharactersSelector,              16 },
-    { 'frac',   kFractionsType,             kDiagonalFractionsSelector,             kNoFractionsSelector },
-    { 'fwid',   kTextSpacingType,           kMonospacedTextSelector,                7 },
-    { 'halt',   kTextSpacingType,           kAltHalfWidthTextSelector,              7 },
-    { 'hist',   kLigaturesType,             kHistoricalLigaturesOnSelector,         kHistoricalLigaturesOffSelector },
-    { 'hkna',   kAlternateKanaType,         kAlternateHorizKanaOnSelector,          kAlternateHorizKanaOffSelector, },
-    { 'hlig',   kLigaturesType,             kHistoricalLigaturesOnSelector,         kHistoricalLigaturesOffSelector },
-    { 'hngl',   kTransliterationType,       kHanjaToHangulSelector,                 kNoTransliterationSelector },
-    { 'hojo',   kCharacterShapeType,        kHojoCharactersSelector,                16 },
-    { 'hwid',   kTextSpacingType,           kHalfWidthTextSelector,                 7 },
-    { 'ital',   kItalicCJKRomanType,        kCJKItalicRomanOnSelector,              kCJKItalicRomanOffSelector },
-    { 'jp04',   kCharacterShapeType,        kJIS2004CharactersSelector,             16 },
-    { 'jp78',   kCharacterShapeType,        kJIS1978CharactersSelector,             16 },
-    { 'jp83',   kCharacterShapeType,        kJIS1983CharactersSelector,             16 },
-    { 'jp90',   kCharacterShapeType,        kJIS1990CharactersSelector,             16 },
-    { 'liga',   kLigaturesType,             kCommonLigaturesOnSelector,             kCommonLigaturesOffSelector },
-    { 'lnum',   kNumberCaseType,            kUpperCaseNumbersSelector,              2 },
-    { 'mgrk',   kMathematicalExtrasType,    kMathematicalGreekOnSelector,           kMathematicalGreekOffSelector },
-    { 'nlck',   kCharacterShapeType,        kNLCCharactersSelector,                 16 },
-    { 'onum',   kNumberCaseType,            kLowerCaseNumbersSelector,              2 },
-    { 'ordn',   kVerticalPositionType,      kOrdinalsSelector,                      kNormalPositionSelector },
-    { 'palt',   kTextSpacingType,           kAltProportionalTextSelector,           7 },
-    { 'pcap',   kLowerCaseType,             kLowerCasePetiteCapsSelector,           kDefaultLowerCaseSelector },
-    { 'pkna',   kTextSpacingType,           kProportionalTextSelector,              7 },
-    { 'pnum',   kNumberSpacingType,         kProportionalNumbersSelector,           4 },
-    { 'pwid',   kTextSpacingType,           kProportionalTextSelector,              7 },
-    { 'qwid',   kTextSpacingType,           kQuarterWidthTextSelector,              7 },
-    { 'ruby',   kRubyKanaType,              kRubyKanaOnSelector,                    kRubyKanaOffSelector },
-    { 'sinf',   kVerticalPositionType,      kScientificInferiorsSelector,           kNormalPositionSelector },
-    { 'smcp',   kLowerCaseType,             kLowerCaseSmallCapsSelector,            kDefaultLowerCaseSelector },
-    { 'smpl',   kCharacterShapeType,        kSimplifiedCharactersSelector,          16 },
-    { 'ss01',   kStylisticAlternativesType, kStylisticAltOneOnSelector,             kStylisticAltOneOffSelector },
-    { 'ss02',   kStylisticAlternativesType, kStylisticAltTwoOnSelector,             kStylisticAltTwoOffSelector },
-    { 'ss03',   kStylisticAlternativesType, kStylisticAltThreeOnSelector,           kStylisticAltThreeOffSelector },
-    { 'ss04',   kStylisticAlternativesType, kStylisticAltFourOnSelector,            kStylisticAltFourOffSelector },
-    { 'ss05',   kStylisticAlternativesType, kStylisticAltFiveOnSelector,            kStylisticAltFiveOffSelector },
-    { 'ss06',   kStylisticAlternativesType, kStylisticAltSixOnSelector,             kStylisticAltSixOffSelector },
-    { 'ss07',   kStylisticAlternativesType, kStylisticAltSevenOnSelector,           kStylisticAltSevenOffSelector },
-    { 'ss08',   kStylisticAlternativesType, kStylisticAltEightOnSelector,           kStylisticAltEightOffSelector },
-    { 'ss09',   kStylisticAlternativesType, kStylisticAltNineOnSelector,            kStylisticAltNineOffSelector },
-    { 'ss10',   kStylisticAlternativesType, kStylisticAltTenOnSelector,             kStylisticAltTenOffSelector },
-    { 'ss11',   kStylisticAlternativesType, kStylisticAltElevenOnSelector,          kStylisticAltElevenOffSelector },
-    { 'ss12',   kStylisticAlternativesType, kStylisticAltTwelveOnSelector,          kStylisticAltTwelveOffSelector },
-    { 'ss13',   kStylisticAlternativesType, kStylisticAltThirteenOnSelector,        kStylisticAltThirteenOffSelector },
-    { 'ss14',   kStylisticAlternativesType, kStylisticAltFourteenOnSelector,        kStylisticAltFourteenOffSelector },
-    { 'ss15',   kStylisticAlternativesType, kStylisticAltFifteenOnSelector,         kStylisticAltFifteenOffSelector },
-    { 'ss16',   kStylisticAlternativesType, kStylisticAltSixteenOnSelector,         kStylisticAltSixteenOffSelector },
-    { 'ss17',   kStylisticAlternativesType, kStylisticAltSeventeenOnSelector,       kStylisticAltSeventeenOffSelector },
-    { 'ss18',   kStylisticAlternativesType, kStylisticAltEighteenOnSelector,        kStylisticAltEighteenOffSelector },
-    { 'ss19',   kStylisticAlternativesType, kStylisticAltNineteenOnSelector,        kStylisticAltNineteenOffSelector },
-    { 'ss20',   kStylisticAlternativesType, kStylisticAltTwentyOnSelector,          kStylisticAltTwentyOffSelector },
-    { 'subs',   kVerticalPositionType,      kInferiorsSelector,                     kNormalPositionSelector },
-    { 'sups',   kVerticalPositionType,      kSuperiorsSelector,                     kNormalPositionSelector },
-    { 'swsh',   kContextualAlternatesType,  kSwashAlternatesOnSelector,             kSwashAlternatesOffSelector },
-    { 'titl',   kStyleOptionsType,          kTitlingCapsSelector,                   kNoStyleOptionsSelector },
-    { 'tnam',   kCharacterShapeType,        kTraditionalNamesCharactersSelector,    16 },
-    { 'tnum',   kNumberSpacingType,         kMonospacedNumbersSelector,             4 },
-    { 'trad',   kCharacterShapeType,        kTraditionalCharactersSelector,         16 },
-    { 'twid',   kTextSpacingType,           kThirdWidthTextSelector,                7 },
-    { 'unic',   kLetterCaseType,            14,                                     15 },
-    { 'valt',   kTextSpacingType,           kAltProportionalTextSelector,           7 },
-    { 'vert',   kVerticalSubstitutionType,  kSubstituteVerticalFormsOnSelector,     kSubstituteVerticalFormsOffSelector },
-    { 'vhal',   kTextSpacingType,           kAltHalfWidthTextSelector,              7 },
-    { 'vkna',   kAlternateKanaType,         kAlternateVertKanaOnSelector,           kAlternateVertKanaOffSelector },
-    { 'vpal',   kTextSpacingType,           kAltProportionalTextSelector,           7 },
-    { 'vrt2',   kVerticalSubstitutionType,  kSubstituteVerticalFormsOnSelector,     kSubstituteVerticalFormsOffSelector },
-    { 'zero',   kTypographicExtrasType,     kSlashedZeroOnSelector,                 kSlashedZeroOffSelector },
-};
-
-static int
-_hb_feature_mapping_cmp (const void *key_, const void *entry_)
-{
-  unsigned int key = * (unsigned int *) key_;
-  const feature_mapping_t * entry = (const feature_mapping_t *) entry_;
-  return key < entry->otFeatureTag ? -1 :
-         key > entry->otFeatureTag ? 1 :
-         0;
-}
-
 hb_bool_t
 _hb_coretext_shape (hb_shape_plan_t    *shape_plan,
                     hb_font_t          *font,
@@ -617,15 +452,15 @@
                     unsigned int        num_features)
 {
   hb_face_t *face = font->face;
-  CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
-  CTFontRef ct_font = (CTFontRef) HB_SHAPER_DATA_GET (font);
+  CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
+  CTFontRef ct_font = (CTFontRef) hb_coretext_font_data_sync (font);
 
   CGFloat ct_font_size = CTFontGetSize (ct_font);
   CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
   CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size;
 
   /* Attach marks to their bases, to match the 'ot' shaper.
-   * Adapted from hb-ot-shape:hb_form_clusters().
+   * Adapted from a very old version of hb-ot-shape:hb_form_clusters().
    * Note that this only makes us be closer to the 'ot' shaper,
    * but by no means the same.  For example, if there's
    * B1 M1 B2 M2, and B1-B2 form a ligature, M2's cluster will
@@ -641,8 +476,8 @@
         buffer->merge_clusters (i - 1, i + 1);
   }
 
-  hb_auto_t<hb_vector_t<feature_record_t> > feature_records;
-  hb_auto_t<hb_vector_t<range_record_t> > range_records;
+  hb_vector_t<feature_record_t> feature_records;
+  hb_vector_t<range_record_t> range_records;
 
   /*
    * Set up features.
@@ -651,14 +486,10 @@
   if (num_features)
   {
     /* Sort features by start/end events. */
-    hb_auto_t<hb_vector_t<feature_event_t> > feature_events;
+    hb_vector_t<feature_event_t> feature_events;
     for (unsigned int i = 0; i < num_features; i++)
     {
-      const feature_mapping_t * mapping = (const feature_mapping_t *) bsearch (&features[i].tag,
-                                                                               feature_mappings,
-                                                                               ARRAY_LENGTH (feature_mappings),
-                                                                               sizeof (feature_mappings[0]),
-                                                                               _hb_feature_mapping_cmp);
+      const hb_aat_feature_mapping_t * mapping = hb_aat_layout_find_feature_mapping (features[i].tag);
       if (!mapping)
         continue;
 
@@ -694,9 +525,9 @@
     }
 
     /* Scan events and save features for each range. */
-    hb_auto_t<hb_vector_t<active_feature_t> > active_features;
+    hb_vector_t<active_feature_t> active_features;
     unsigned int last_index = 0;
-    for (unsigned int i = 0; i < feature_events.len; i++)
+    for (unsigned int i = 0; i < feature_events.length; i++)
     {
       feature_event_t *event = &feature_events[i];
 
@@ -705,13 +536,13 @@
         /* Save a snapshot of active features and the range. */
         range_record_t *range = range_records.push ();
 
-        if (active_features.len)
+        if (active_features.length)
         {
           CFMutableArrayRef features_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
 
           /* TODO sort and resolve conflicting features? */
           /* active_features.qsort (); */
-          for (unsigned int j = 0; j < active_features.len; j++)
+          for (unsigned int j = 0; j < active_features.length; j++)
           {
             CFStringRef keys[] = {
               kCTFontFeatureTypeIdentifierKey,
@@ -767,7 +598,7 @@
       } else {
         active_feature_t *feature = active_features.find (&event->feature);
         if (feature)
-          active_features.remove (feature - active_features.arrayZ);
+          active_features.remove (feature - active_features.arrayZ ());
       }
     }
   }
@@ -824,7 +655,7 @@
   CFStringRef string_ref = nullptr;
   CTLineRef line = nullptr;
 
-  if (0)
+  if (false)
   {
 resize_and_retry:
     DEBUG_MSG (CORETEXT, buffer, "Buffer resize");
@@ -899,7 +730,7 @@
       CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
                                       kCTFontAttributeName, ct_font);
 
-      if (num_features && range_records.len)
+      if (num_features && range_records.length)
       {
         unsigned int start = 0;
         range_record_t *last_range = &range_records[0];
@@ -1048,7 +879,7 @@
          * Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
          */
         bool matched = false;
-        for (unsigned int i = 0; i < range_records.len; i++)
+        for (unsigned int i = 0; i < range_records.length; i++)
           if (range_records[i].font && CFEqual (run_ct_font, range_records[i].font))
           {
             matched = true;
@@ -1235,7 +1066,7 @@
      *
      * https://crbug.com/419769
      */
-    if (0)
+    if (false)
     {
       /* Make sure all runs had the expected direction. */
       bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
@@ -1311,7 +1142,7 @@
   if (line)
     CFRelease (line);
 
-  for (unsigned int i = 0; i < range_records.len; i++)
+  for (unsigned int i = 0; i < range_records.length; i++)
     if (range_records[i].font)
       CFRelease (range_records[i].font);
 
@@ -1323,36 +1154,21 @@
  * AAT shaper
  */
 
-HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, face)
-HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font)
-
 /*
  * shaper face data
  */
 
-struct hb_coretext_aat_shaper_face_data_t {};
+struct hb_coretext_aat_face_data_t {};
 
-hb_coretext_aat_shaper_face_data_t *
+hb_coretext_aat_face_data_t *
 _hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
 {
-  static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX};
-
-  for (unsigned int i = 0; i < ARRAY_LENGTH (tags); i++)
-  {
-    hb_blob_t *blob = face->reference_table (tags[i]);
-    if (hb_blob_get_length (blob))
-    {
-      hb_blob_destroy (blob);
-      return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
-    }
-    hb_blob_destroy (blob);
-  }
-
-  return nullptr;
+  return hb_aat_layout_has_substitution (face) || hb_aat_layout_has_positioning (face) ?
+         (hb_coretext_aat_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
 }
 
 void
-_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *data HB_UNUSED)
+_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_face_data_t *data HB_UNUSED)
 {
 }
 
@@ -1361,38 +1177,16 @@
  * shaper font data
  */
 
-struct hb_coretext_aat_shaper_font_data_t {};
+struct hb_coretext_aat_font_data_t {};
 
-hb_coretext_aat_shaper_font_data_t *
+hb_coretext_aat_font_data_t *
 _hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
 {
-  return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
+  return font->data.coretext ? (hb_coretext_aat_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
 }
 
 void
-_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *data HB_UNUSED)
-{
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_coretext_aat_shaper_shape_plan_data_t {};
-
-hb_coretext_aat_shaper_shape_plan_data_t *
-_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-                                             const hb_feature_t *user_features HB_UNUSED,
-                                             unsigned int        num_user_features HB_UNUSED,
-                                             const int          *coords HB_UNUSED,
-                                             unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shaper_shape_plan_data_t *data HB_UNUSED)
+_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_font_data_t *data HB_UNUSED)
 {
 }
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-debug.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-debug.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,13 +27,60 @@
 #ifndef HB_DEBUG_HH
 #define HB_DEBUG_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
+#include "hb-atomic.hh"
+#include "hb-dsalgs.hh"
 
 
 #ifndef HB_DEBUG
 #define HB_DEBUG 0
 #endif
 
+
+/*
+ * Global runtime options.
+ */
+
+struct hb_options_t
+{
+  bool unused : 1; /* In-case sign bit is here. */
+  bool initialized : 1;
+  bool uniscribe_bug_compatible : 1;
+  bool aat : 1;
+};
+
+union hb_options_union_t {
+  int i;
+  hb_options_t opts;
+};
+static_assert ((sizeof (hb_atomic_int_t) >= sizeof (hb_options_union_t)), "");
+
+HB_INTERNAL void
+_hb_options_init ();
+
+extern HB_INTERNAL hb_atomic_int_t _hb_options;
+
+static inline hb_options_t
+hb_options ()
+{
+  /* Make a local copy, so we can access bitfield threadsafely. */
+  hb_options_union_t u;
+  u.i = _hb_options.get_relaxed ();
+
+  if (unlikely (!u.i))
+  {
+    _hb_options_init ();
+    u.i = _hb_options.get_relaxed ();
+  }
+
+  return u.opts;
+}
+
+
+/*
+ * Debug output (needs enabling at compile time.)
+ */
+
 static inline bool
 _hb_debug (unsigned int level,
            unsigned int max_level)
@@ -126,7 +173,7 @@
 
   fprintf (stderr, "\n");
 }
-template <> inline void
+template <> inline void HB_PRINTF_FUNC(7, 0)
 _hb_debug_msg_va<0> (const char *what HB_UNUSED,
                      const void *obj HB_UNUSED,
                      const char *func HB_UNUSED,
@@ -145,7 +192,7 @@
                int level_dir,
                const char *message,
                ...) HB_PRINTF_FUNC(7, 8);
-template <int max_level> static inline void
+template <int max_level> static inline void HB_PRINTF_FUNC(7, 8)
 _hb_debug_msg (const char *what,
                const void *obj,
                const char *func,
@@ -169,7 +216,7 @@
                   int level_dir HB_UNUSED,
                   const char *message HB_UNUSED,
                   ...) HB_PRINTF_FUNC(7, 8);
-template <> inline void
+template <> inline void HB_PRINTF_FUNC(7, 8)
 _hb_debug_msg<0> (const char *what HB_UNUSED,
                   const void *obj HB_UNUSED,
                   const char *func HB_UNUSED,
@@ -237,7 +284,7 @@
     _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
     va_end (ap);
   }
-  inline ~hb_auto_trace_t (void)
+  ~hb_auto_trace_t ()
   {
     _hb_warn_no_return<ret_t> (returned);
     if (!returned) {
@@ -246,14 +293,16 @@
     if (plevel) --*plevel;
   }
 
-  inline ret_t ret (ret_t v, unsigned int line = 0)
+  ret_t ret (ret_t v,
+             const char *func = "",
+             unsigned int line = 0)
   {
     if (unlikely (returned)) {
       fprintf (stderr, "OUCH, double calls to return_trace().  This is a bug, please report.\n");
       return v;
     }
 
-    _hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1,
+    _hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1,
                               "return %s (line %d)",
                               hb_printer_t<ret_t>().print (v), line);
     if (plevel) --*plevel;
@@ -278,17 +327,21 @@
                                    const char *message,
                                    ...) HB_PRINTF_FUNC(6, 7) {}
 
-  inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
+  ret_t ret (ret_t v,
+             const char *func HB_UNUSED = nullptr,
+             unsigned int line HB_UNUSED = 0) { return v; }
 };
 
 /* For disabled tracing; optimize out everything.
  * https://github.com/harfbuzz/harfbuzz/pull/605 */
 template <typename ret_t>
 struct hb_no_trace_t {
-  inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
+  ret_t ret (ret_t v,
+             const char *func HB_UNUSED = "",
+             unsigned int line HB_UNUSED = 0) { return v; }
 };
 
-#define return_trace(RET) return trace.ret (RET, __LINE__)
+#define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__)
 
 
 /*
@@ -348,30 +401,6 @@
 #define TRACE_APPLY(this) hb_no_trace_t<bool> trace
 #endif
 
-#ifndef HB_DEBUG_CLOSURE
-#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
-#endif
-#if HB_DEBUG_CLOSURE
-#define TRACE_CLOSURE(this) \
-        hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
-        (&c->debug_depth, c->get_name (), this, HB_FUNC, \
-         " ")
-#else
-#define TRACE_CLOSURE(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
-#endif
-
-#ifndef HB_DEBUG_COLLECT_GLYPHS
-#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
-#endif
-#if HB_DEBUG_COLLECT_GLYPHS
-#define TRACE_COLLECT_GLYPHS(this) \
-        hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \
-        (&c->debug_depth, c->get_name (), this, HB_FUNC, \
-         " ")
-#else
-#define TRACE_COLLECT_GLYPHS(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
-#endif
-
 #ifndef HB_DEBUG_SANITIZE
 #define HB_DEBUG_SANITIZE (HB_DEBUG+0)
 #endif
@@ -423,8 +452,6 @@
 #ifndef HB_DEBUG_DISPATCH
 #define HB_DEBUG_DISPATCH ( \
         HB_DEBUG_APPLY + \
-        HB_DEBUG_CLOSURE + \
-        HB_DEBUG_COLLECT_GLYPHS + \
         HB_DEBUG_SANITIZE + \
         HB_DEBUG_SERIALIZE + \
   HB_DEBUG_SUBSET + \
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-deprecated.h	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-deprecated.h	Fri Mar 01 16:59:19 2019 -0800
@@ -36,10 +36,23 @@
 #include "hb-font.h"
 #include "hb-set.h"
 
+
+/**
+ * SECTION:hb-deprecated
+ * @title: hb-deprecated
+ * @short_description: Deprecated API
+ * @include: hb.h
+ *
+ * These API have been deprecated in favor of newer API, or because they
+ * were deemed unnecessary.
+ **/
+
+
 HB_BEGIN_DECLS
 
 #ifndef HB_DISABLE_DEPRECATED
 
+
 #define HB_SCRIPT_CANADIAN_ABORIGINAL           HB_SCRIPT_CANADIAN_SYLLABICS
 
 #define HB_BUFFER_FLAGS_DEFAULT                 HB_BUFFER_FLAG_DEFAULT
@@ -50,13 +63,161 @@
                                                hb_codepoint_t *glyph,
                                                void *user_data);
 
-HB_EXTERN void
+HB_EXTERN HB_DEPRECATED_FOR(hb_font_funcs_set_nominal_glyph_func or hb_font_funcs_set_variation_glyph_func) void
 hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
                               hb_font_get_glyph_func_t func,
                               void *user_data, hb_destroy_func_t destroy);
 
+HB_EXTERN HB_DEPRECATED void
+hb_set_invert (hb_set_t *set);
+
+/**
+ * hb_unicode_eastasian_width_func_t:
+ *
+ * Deprecated: 2.0.0
+ */
+typedef unsigned int                    (*hb_unicode_eastasian_width_func_t)    (hb_unicode_funcs_t *ufuncs,
+                                                                                 hb_codepoint_t      unicode,
+                                                                                 void               *user_data);
+
+/**
+ * hb_unicode_funcs_set_eastasian_width_func:
+ * @ufuncs: a Unicode function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
+HB_EXTERN HB_DEPRECATED void
+hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
+                                           hb_unicode_eastasian_width_func_t func,
+                                           void *user_data, hb_destroy_func_t destroy);
+
+/**
+ * hb_unicode_eastasian_width:
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
+HB_EXTERN HB_DEPRECATED unsigned int
+hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
+                            hb_codepoint_t unicode);
+
+
+/**
+ * hb_unicode_decompose_compatibility_func_t:
+ * @ufuncs: a Unicode function structure
+ * @u: codepoint to decompose
+ * @decomposed: address of codepoint array (of length %HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into
+ * @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func()
+ *
+ * Fully decompose @u to its Unicode compatibility decomposition. The codepoints of the decomposition will be written to @decomposed.
+ * The complete length of the decomposition will be returned.
+ *
+ * If @u has no compatibility decomposition, zero should be returned.
+ *
+ * The Unicode standard guarantees that a buffer of length %HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any
+ * compatibility decomposition plus an terminating value of 0.  Consequently, @decompose must be allocated by the caller to be at least this length.  Implementations
+ * of this function type must ensure that they do not write past the provided array.
+ *
+ * Return value: number of codepoints in the full compatibility decomposition of @u, or 0 if no decomposition available.
+ *
+ * Deprecated: 2.0.0
+ */
+typedef unsigned int                    (*hb_unicode_decompose_compatibility_func_t)    (hb_unicode_funcs_t *ufuncs,
+                                                                                         hb_codepoint_t      u,
+                                                                                         hb_codepoint_t     *decomposed,
+                                                                                         void               *user_data);
+
+/**
+ * HB_UNICODE_MAX_DECOMPOSITION_LEN:
+ *
+ * See Unicode 6.1 for details on the maximum decomposition length.
+ *
+ * Deprecated: 2.0.0
+ */
+#define HB_UNICODE_MAX_DECOMPOSITION_LEN (18+1) /* codepoints */
+
+/**
+ * hb_unicode_funcs_set_decompose_compatibility_func:
+ * @ufuncs: a Unicode function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
+HB_EXTERN HB_DEPRECATED void
+hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs,
+                                                   hb_unicode_decompose_compatibility_func_t func,
+                                                   void *user_data, hb_destroy_func_t destroy);
+
+HB_EXTERN HB_DEPRECATED unsigned int
+hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
+                                    hb_codepoint_t      u,
+                                    hb_codepoint_t     *decomposed);
+
+
+typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
+                                                           hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+                                                           void *user_data);
+typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
+typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
+
+/**
+ * hb_font_funcs_set_glyph_h_kerning_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
 HB_EXTERN void
-hb_set_invert (hb_set_t *set);
+hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
+                                        hb_font_get_glyph_h_kerning_func_t func,
+                                        void *user_data, hb_destroy_func_t destroy);
+
+/**
+ * hb_font_funcs_set_glyph_v_kerning_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
+HB_EXTERN void
+hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs,
+                                        hb_font_get_glyph_v_kerning_func_t func,
+                                        void *user_data, hb_destroy_func_t destroy);
+
+HB_EXTERN hb_position_t
+hb_font_get_glyph_h_kerning (hb_font_t *font,
+                             hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
+HB_EXTERN hb_position_t
+hb_font_get_glyph_v_kerning (hb_font_t *font,
+                             hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
+
+HB_EXTERN void
+hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
+                                         hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+                                         hb_direction_t direction,
+                                         hb_position_t *x, hb_position_t *y);
+
 
 #endif
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-dsalgs.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-dsalgs.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,8 +27,338 @@
 #ifndef HB_DSALGS_HH
 #define HB_DSALGS_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
+#include "hb-null.hh"
+
+
+/* Void! For when we need a expression-type of void. */
+typedef const struct _hb_void_t *hb_void_t;
+#define HB_VOID ((const _hb_void_t *) nullptr)
+
+
+/*
+ * Bithacks.
+ */
+
+/* Return the number of 1 bits in v. */
+template <typename T>
+static inline HB_CONST_FUNC unsigned int
+hb_popcount (T v)
+{
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+  if (sizeof (T) <= sizeof (unsigned int))
+    return __builtin_popcount (v);
+
+  if (sizeof (T) <= sizeof (unsigned long))
+    return __builtin_popcountl (v);
+
+  if (sizeof (T) <= sizeof (unsigned long long))
+    return __builtin_popcountll (v);
+#endif
+
+  if (sizeof (T) <= 4)
+  {
+    /* "HACKMEM 169" */
+    uint32_t y;
+    y = (v >> 1) &033333333333;
+    y = v - y - ((y >>1) & 033333333333);
+    return (((y + (y >> 3)) & 030707070707) % 077);
+  }
+
+  if (sizeof (T) == 8)
+  {
+    unsigned int shift = 32;
+    return hb_popcount<uint32_t> ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift));
+  }
+
+  if (sizeof (T) == 16)
+  {
+    unsigned int shift = 64;
+    return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
+  }
+
+  assert (0);
+  return 0; /* Shut up stupid compiler. */
+}
+
+/* Returns the number of bits needed to store number */
+template <typename T>
+static inline HB_CONST_FUNC unsigned int
+hb_bit_storage (T v)
+{
+  if (unlikely (!v)) return 0;
+
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+  if (sizeof (T) <= sizeof (unsigned int))
+    return sizeof (unsigned int) * 8 - __builtin_clz (v);
+
+  if (sizeof (T) <= sizeof (unsigned long))
+    return sizeof (unsigned long) * 8 - __builtin_clzl (v);
+
+  if (sizeof (T) <= sizeof (unsigned long long))
+    return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
+#endif
+
+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
+  if (sizeof (T) <= sizeof (unsigned int))
+  {
+    unsigned long where;
+    _BitScanReverse (&where, v);
+    return 1 + where;
+  }
+# if defined(_WIN64)
+  if (sizeof (T) <= 8)
+  {
+    unsigned long where;
+    _BitScanReverse64 (&where, v);
+    return 1 + where;
+  }
+# endif
+#endif
+
+  if (sizeof (T) <= 4)
+  {
+    /* "bithacks" */
+    const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
+    const unsigned int S[] = {1, 2, 4, 8, 16};
+    unsigned int r = 0;
+    for (int i = 4; i >= 0; i--)
+      if (v & b[i])
+      {
+        v >>= S[i];
+        r |= S[i];
+      }
+    return r + 1;
+  }
+  if (sizeof (T) <= 8)
+  {
+    /* "bithacks" */
+    const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
+    const unsigned int S[] = {1, 2, 4, 8, 16, 32};
+    unsigned int r = 0;
+    for (int i = 5; i >= 0; i--)
+      if (v & b[i])
+      {
+        v >>= S[i];
+        r |= S[i];
+      }
+    return r + 1;
+  }
+  if (sizeof (T) == 16)
+  {
+    unsigned int shift = 64;
+    return (v >> shift) ? hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
+                          hb_bit_storage<uint64_t> ((uint64_t) v);
+  }
+
+  assert (0);
+  return 0; /* Shut up stupid compiler. */
+}
+
+/* Returns the number of zero bits in the least significant side of v */
+template <typename T>
+static inline HB_CONST_FUNC unsigned int
+hb_ctz (T v)
+{
+  if (unlikely (!v)) return 0;
+
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+  if (sizeof (T) <= sizeof (unsigned int))
+    return __builtin_ctz (v);
+
+  if (sizeof (T) <= sizeof (unsigned long))
+    return __builtin_ctzl (v);
+
+  if (sizeof (T) <= sizeof (unsigned long long))
+    return __builtin_ctzll (v);
+#endif
+
+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
+  if (sizeof (T) <= sizeof (unsigned int))
+  {
+    unsigned long where;
+    _BitScanForward (&where, v);
+    return where;
+  }
+# if defined(_WIN64)
+  if (sizeof (T) <= 8)
+  {
+    unsigned long where;
+    _BitScanForward64 (&where, v);
+    return where;
+  }
+# endif
+#endif
 
+  if (sizeof (T) <= 4)
+  {
+    /* "bithacks" */
+    unsigned int c = 32;
+    v &= - (int32_t) v;
+    if (v) c--;
+    if (v & 0x0000FFFF) c -= 16;
+    if (v & 0x00FF00FF) c -= 8;
+    if (v & 0x0F0F0F0F) c -= 4;
+    if (v & 0x33333333) c -= 2;
+    if (v & 0x55555555) c -= 1;
+    return c;
+  }
+  if (sizeof (T) <= 8)
+  {
+    /* "bithacks" */
+    unsigned int c = 64;
+    v &= - (int64_t) (v);
+    if (v) c--;
+    if (v & 0x00000000FFFFFFFFULL) c -= 32;
+    if (v & 0x0000FFFF0000FFFFULL) c -= 16;
+    if (v & 0x00FF00FF00FF00FFULL) c -= 8;
+    if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
+    if (v & 0x3333333333333333ULL) c -= 2;
+    if (v & 0x5555555555555555ULL) c -= 1;
+    return c;
+  }
+  if (sizeof (T) == 16)
+  {
+    unsigned int shift = 64;
+    return (uint64_t) v ? hb_bit_storage<uint64_t> ((uint64_t) v) :
+                          hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift;
+  }
+
+  assert (0);
+  return 0; /* Shut up stupid compiler. */
+}
+
+
+/*
+ * Tiny stuff.
+ */
+
+template <typename T>
+static inline T* hb_addressof (T& arg)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+  /* https://en.cppreference.com/w/cpp/memory/addressof */
+  return reinterpret_cast<T*>(
+           &const_cast<char&>(
+              reinterpret_cast<const volatile char&>(arg)));
+#pragma GCC diagnostic pop
+}
+
+/* ASCII tag/character handling */
+static inline bool ISALPHA (unsigned char c)
+{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
+static inline bool ISALNUM (unsigned char c)
+{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
+static inline bool ISSPACE (unsigned char c)
+{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
+static inline unsigned char TOUPPER (unsigned char c)
+{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
+static inline unsigned char TOLOWER (unsigned char c)
+{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
+
+#undef MIN
+template <typename Type>
+static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
+
+#undef MAX
+template <typename Type>
+static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
+
+static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
+{ return (a + (b - 1)) / b; }
+
+
+#undef  ARRAY_LENGTH
+template <typename Type, unsigned int n>
+static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
+/* A const version, but does not detect erratically being called on pointers. */
+#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
+
+
+static inline int
+hb_memcmp (const void *a, const void *b, unsigned int len)
+{
+  /* It's illegal to pass NULL to memcmp(), even if len is zero.
+   * So, wrap it.
+   * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
+  if (!len) return 0;
+  return memcmp (a, b, len);
+}
+
+static inline bool
+hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
+{
+  return (size > 0) && (count >= ((unsigned int) -1) / size);
+}
+
+static inline unsigned int
+hb_ceil_to_4 (unsigned int v)
+{
+  return ((v - 1) | 3) + 1;
+}
+
+template <typename T> struct hb_is_signed;
+/* https://github.com/harfbuzz/harfbuzz/issues/1535 */
+template <> struct hb_is_signed<int8_t> { enum { value = true }; };
+template <> struct hb_is_signed<int16_t> { enum { value = true }; };
+template <> struct hb_is_signed<int32_t> { enum { value = true }; };
+template <> struct hb_is_signed<int64_t> { enum { value = true }; };
+template <> struct hb_is_signed<uint8_t> { enum { value = false }; };
+template <> struct hb_is_signed<uint16_t> { enum { value = false }; };
+template <> struct hb_is_signed<uint32_t> { enum { value = false }; };
+template <> struct hb_is_signed<uint64_t> { enum { value = false }; };
+
+template <typename T> static inline bool
+hb_in_range (T u, T lo, T hi)
+{
+  /* The sizeof() is here to force template instantiation.
+   * I'm sure there are better ways to do this but can't think of
+   * one right now.  Declaring a variable won't work as HB_UNUSED
+   * is unusable on some platforms and unused types are less likely
+   * to generate a warning than unused variables. */
+  static_assert (!hb_is_signed<T>::value, "");
+
+  /* The casts below are important as if T is smaller than int,
+   * the subtract results will become a signed int! */
+  return (T)(u - lo) <= (T)(hi - lo);
+}
+template <typename T> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
+{
+  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
+}
+template <typename T> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
+{
+  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
+}
+
+
+/*
+ * Sort and search.
+ */
+
+static inline void *
+hb_bsearch (const void *key, const void *base,
+            size_t nmemb, size_t size,
+            int (*compar)(const void *_key, const void *_item))
+{
+  int min = 0, max = (int) nmemb - 1;
+  while (min <= max)
+  {
+    int mid = (min + max) / 2;
+    const void *p = (const void *) (((const char *) base) + (mid * size));
+    int c = compar (key, p);
+    if (c < 0)
+      max = mid - 1;
+    else if (c > 0)
+      min = mid + 1;
+    else
+      return (void *) p;
+  }
+  return nullptr;
+}
 
 static inline void *
 hb_bsearch_r (const void *key, const void *base,
@@ -39,7 +369,7 @@
   int min = 0, max = (int) nmemb - 1;
   while (min <= max)
   {
-    int mid = (min + max) / 2;
+    int mid = ((unsigned int) min + (unsigned int) max) / 2;
     const void *p = (const void *) (((const char *) base) + (mid * size));
     int c = compar (key, p, arg);
     if (c < 0)
@@ -53,8 +383,12 @@
 }
 
 
-
-/* From https://github.com/noporpoise/sort_r */
+/* From https://github.com/noporpoise/sort_r
+ * With following modifications:
+ *
+ * 10 November 2018:
+ * https://github.com/noporpoise/sort_r/issues/7
+ */
 
 /* Isaac Turner 29 April 2014 Public Domain */
 
@@ -110,7 +444,7 @@
 
     /* Use median of first, middle and last items as pivot */
     char *x, *y, *xend, ch;
-    char *pl, *pr;
+    char *pl, *pm, *pr;
     char *last = b+w*(nel-1), *tmp;
     char *l[3];
     l[0] = b;
@@ -132,13 +466,15 @@
     pr = last;
 
     while(pl < pr) {
-      for(; pl < pr; pl += w) {
+      pm = pl+((pr-pl+1)>>1);
+      for(; pl < pm; pl += w) {
         if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
           pr -= w; /* pivot now at pl */
           break;
         }
       }
-      for(; pl < pr; pr -= w) {
+      pm = pl+((pr-pl)>>1);
+      for(; pm < pr; pr -= w) {
         if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
           pl += w; /* pivot now at pr */
           break;
@@ -158,4 +494,139 @@
     sort_r_simple(base, nel, width, compar, arg);
 }
 
+
+template <typename T, typename T2> static inline void
+hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
+{
+  for (unsigned int i = 1; i < len; i++)
+  {
+    unsigned int j = i;
+    while (j && compar (&array[j - 1], &array[i]) > 0)
+      j--;
+    if (i == j)
+      continue;
+    /* Move item i to occupy place for item j, shift what's in between. */
+    {
+      T t = array[i];
+      memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
+      array[j] = t;
+    }
+    if (array2)
+    {
+      T2 t = array2[i];
+      memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
+      array2[j] = t;
+    }
+  }
+}
+
+template <typename T> static inline void
+hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
+{
+  hb_stable_sort (array, len, compar, (int *) nullptr);
+}
+
+static inline hb_bool_t
+hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
+{
+  /* Pain because we don't know whether s is nul-terminated. */
+  char buf[64];
+  len = MIN (ARRAY_LENGTH (buf) - 1, len);
+  strncpy (buf, s, len);
+  buf[len] = '\0';
+
+  char *end;
+  errno = 0;
+  unsigned long v = strtoul (buf, &end, base);
+  if (errno) return false;
+  if (*end) return false;
+  *out = v;
+  return true;
+}
+
+
+struct HbOpOr
+{
+  static constexpr bool passthru_left = true;
+  static constexpr bool passthru_right = true;
+  template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
+};
+struct HbOpAnd
+{
+  static constexpr bool passthru_left = false;
+  static constexpr bool passthru_right = false;
+  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
+};
+struct HbOpMinus
+{
+  static constexpr bool passthru_left = true;
+  static constexpr bool passthru_right = false;
+  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
+};
+struct HbOpXor
+{
+  static constexpr bool passthru_left = true;
+  static constexpr bool passthru_right = true;
+  template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
+};
+
+
+/* Compiler-assisted vectorization. */
+
+/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
+ * using vectorized operations if HB_VECTOR_SIZE is set to **bit** numbers (eg 128).
+ * Define that to 0 to disable. */
+template <typename elt_t, unsigned int byte_size>
+struct hb_vector_size_t
+{
+  elt_t& operator [] (unsigned int i) { return u.v[i]; }
+  const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
+
+  void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
+
+  template <class Op>
+  hb_vector_size_t process (const hb_vector_size_t &o) const
+  {
+    hb_vector_size_t r;
+#if HB_VECTOR_SIZE
+    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
+      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
+        Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]);
+    else
+#endif
+      for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
+        Op::process (r.u.v[i], u.v[i], o.u.v[i]);
+    return r;
+  }
+  hb_vector_size_t operator | (const hb_vector_size_t &o) const
+  { return process<HbOpOr> (o); }
+  hb_vector_size_t operator & (const hb_vector_size_t &o) const
+  { return process<HbOpAnd> (o); }
+  hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
+  { return process<HbOpXor> (o); }
+  hb_vector_size_t operator ~ () const
+  {
+    hb_vector_size_t r;
+#if HB_VECTOR_SIZE && 0
+    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
+      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
+        r.u.vec[i] = ~u.vec[i];
+    else
+#endif
+    for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
+      r.u.v[i] = ~u.v[i];
+    return r;
+  }
+
+  private:
+  static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
+  union {
+    elt_t v[byte_size / sizeof (elt_t)];
+#if HB_VECTOR_SIZE
+    hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)];
+#endif
+  } u;
+};
+
+
 #endif /* HB_DSALGS_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  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_FACE_PRIVATE_HH
-#define HB_FACE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-object-private.hh"
-#include "hb-shaper-private.hh"
-#include "hb-shape-plan-private.hh"
-
-
-/*
- * hb_face_t
- */
-
-struct hb_face_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t immutable;
-
-  hb_reference_table_func_t  reference_table_func;
-  void                      *user_data;
-  hb_destroy_func_t          destroy;
-
-  unsigned int index;                   /* Face index in a collection, zero-based. */
-  mutable unsigned int upem;            /* Units-per-EM. */
-  mutable unsigned int num_glyphs;      /* Number of glyphs. */
-
-  struct hb_shaper_data_t shaper_data;  /* Various shaper data. */
-
-  /* Various non-shaping data. */
-  /* ... */
-
-  /* Cache */
-  struct plan_node_t {
-    hb_shape_plan_t *shape_plan;
-    plan_node_t *next;
-  } *shape_plans;
-
-
-  inline hb_blob_t *reference_table (hb_tag_t tag) const
-  {
-    hb_blob_t *blob;
-
-    if (unlikely (!reference_table_func))
-      return hb_blob_get_empty ();
-
-    blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data);
-    if (unlikely (!blob))
-      return hb_blob_get_empty ();
-
-    return blob;
-  }
-
-  inline HB_PURE_FUNC unsigned int get_upem (void) const
-  {
-    if (unlikely (!upem))
-      load_upem ();
-    return upem;
-  }
-
-  inline unsigned int get_num_glyphs (void) const
-  {
-    if (unlikely (num_glyphs == (unsigned int) -1))
-      load_num_glyphs ();
-    return num_glyphs;
-  }
-
-  private:
-  HB_INTERNAL void load_upem (void) const;
-  HB_INTERNAL void load_num_glyphs (void) const;
-};
-
-extern HB_INTERNAL const hb_face_t _hb_face_nil;
-
-#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-
-
-#endif /* HB_FACE_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -26,23 +26,35 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-face-private.hh"
-#include "hb-blob-private.hh"
-#include "hb-open-file-private.hh"
-#include "hb-ot-head-table.hh"
-#include "hb-ot-maxp-table.hh"
-
+#include "hb-face.hh"
+#include "hb-blob.hh"
+#include "hb-open-file.hh"
+#include "hb-ot-face.hh"
+#include "hb-ot-cmap-table.hh"
 
 
 /**
- * hb_face_count: Get number of faces on the blob
- * @blob:
+ * SECTION:hb-face
+ * @title: hb-face
+ * @short_description: Font face objects
+ * @include: hb.h
  *
- *
+ * Font face is objects represent a single face in a font family.
+ * More exactly, a font face represents a single face in a binary font file.
+ * Font faces are typically built from a binary blob and a face index.
+ * Font faces are used to create fonts.
+ **/
+
+
+/**
+ * hb_face_count:
+ * @blob: a blob.
  *
- * Return value: Number of faces on the blob
+ * Get number of faces in a blob.
+ *
+ * Return value: Number of faces in @blob
  *
  * Since: 1.7.7
  **/
@@ -52,36 +64,33 @@
   if (unlikely (!blob))
     return 0;
 
-  hb_blob_t *sanitized = OT::Sanitizer<OT::OpenTypeFontFile> ().sanitize (blob);
+  /* TODO We shouldn't be sanitizing blob.  Port to run sanitizer and return if not sane. */
+  /* Make API signature const after. */
+  hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
   const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
+  unsigned int ret = ot.get_face_count ();
+  hb_blob_destroy (sanitized);
 
-  return ot.get_face_count ();
+  return ret;
 }
 
 /*
  * hb_face_t
  */
 
-const hb_face_t _hb_face_nil = {
+DEFINE_NULL_INSTANCE (hb_face_t) =
+{
   HB_OBJECT_HEADER_STATIC,
 
-  true, /* immutable */
-
   nullptr, /* reference_table_func */
   nullptr, /* user_data */
   nullptr, /* destroy */
 
   0,    /* index */
-  1000, /* upem */
-  0,    /* num_glyphs */
+  HB_ATOMIC_INT_INIT (1000), /* upem */
+  HB_ATOMIC_INT_INIT (0),    /* num_glyphs */
 
-  {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-  },
-
-  nullptr, /* shape_plans */
+  /* Zero for the rest is fine. */
 };
 
 
@@ -114,8 +123,10 @@
   face->user_data = user_data;
   face->destroy = destroy;
 
-  face->upem = 0;
-  face->num_glyphs = (unsigned int) -1;
+  face->num_glyphs.set_relaxed (-1);
+
+  face->data.init0 (face);
+  face->table.init0 (face);
 
   return face;
 }
@@ -159,11 +170,12 @@
     return hb_blob_reference (data->blob);
 
   const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
-  const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
+  unsigned int base_offset;
+  const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index, &base_offset);
 
   const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
 
-  hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
+  hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, base_offset + table.offset, table.length);
 
   return blob;
 }
@@ -188,7 +200,7 @@
   if (unlikely (!blob))
     blob = hb_blob_get_empty ();
 
-  hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>().sanitize (hb_blob_reference (blob)), index);
+  hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob)), index);
 
   if (unlikely (!closure))
     return hb_face_get_empty ();
@@ -212,9 +224,9 @@
  * Since: 0.9.2
  **/
 hb_face_t *
-hb_face_get_empty (void)
+hb_face_get_empty ()
 {
-  return const_cast<hb_face_t *> (&_hb_face_nil);
+  return const_cast<hb_face_t *> (&Null(hb_face_t));
 }
 
 
@@ -255,9 +267,8 @@
     node = next;
   }
 
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
+  face->data.fini ();
+  face->table.fini ();
 
   if (face->destroy)
     face->destroy (face->user_data);
@@ -301,7 +312,7 @@
  * Since: 0.9.2
  **/
 void *
-hb_face_get_user_data (hb_face_t          *face,
+hb_face_get_user_data (const hb_face_t    *face,
                        hb_user_data_key_t *key)
 {
   return hb_object_get_user_data (face, key);
@@ -318,10 +329,10 @@
 void
 hb_face_make_immutable (hb_face_t *face)
 {
-  if (unlikely (hb_object_is_inert (face)))
+  if (hb_object_is_immutable (face))
     return;
 
-  face->immutable = true;
+  hb_object_make_immutable (face);
 }
 
 /**
@@ -335,9 +346,9 @@
  * Since: 0.9.2
  **/
 hb_bool_t
-hb_face_is_immutable (hb_face_t *face)
+hb_face_is_immutable (const hb_face_t *face)
 {
-  return face->immutable;
+  return hb_object_is_immutable (face);
 }
 
 
@@ -353,8 +364,8 @@
  * Since: 0.9.2
  **/
 hb_blob_t *
-hb_face_reference_table (hb_face_t *face,
-                         hb_tag_t   tag)
+hb_face_reference_table (const hb_face_t *face,
+                         hb_tag_t tag)
 {
   return face->reference_table (tag);
 }
@@ -388,7 +399,7 @@
 hb_face_set_index (hb_face_t    *face,
                    unsigned int  index)
 {
-  if (face->immutable)
+  if (hb_object_is_immutable (face))
     return;
 
   face->index = index;
@@ -405,7 +416,7 @@
  * Since: 0.9.2
  **/
 unsigned int
-hb_face_get_index (hb_face_t    *face)
+hb_face_get_index (const hb_face_t *face)
 {
   return face->index;
 }
@@ -423,10 +434,10 @@
 hb_face_set_upem (hb_face_t    *face,
                   unsigned int  upem)
 {
-  if (face->immutable)
+  if (hb_object_is_immutable (face))
     return;
 
-  face->upem = upem;
+  face->upem.set_relaxed (upem);
 }
 
 /**
@@ -440,20 +451,11 @@
  * Since: 0.9.2
  **/
 unsigned int
-hb_face_get_upem (hb_face_t *face)
+hb_face_get_upem (const hb_face_t *face)
 {
   return face->get_upem ();
 }
 
-void
-hb_face_t::load_upem (void) const
-{
-  hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (reference_table (HB_OT_TAG_head));
-  const OT::head *head_table = head_blob->as<OT::head> ();
-  upem = head_table->get_upem ();
-  hb_blob_destroy (head_blob);
-}
-
 /**
  * hb_face_set_glyph_count:
  * @face: a face.
@@ -467,10 +469,10 @@
 hb_face_set_glyph_count (hb_face_t    *face,
                          unsigned int  glyph_count)
 {
-  if (face->immutable)
+  if (hb_object_is_immutable (face))
     return;
 
-  face->num_glyphs = glyph_count;
+  face->num_glyphs.set_relaxed (glyph_count);
 }
 
 /**
@@ -484,23 +486,17 @@
  * Since: 0.9.7
  **/
 unsigned int
-hb_face_get_glyph_count (hb_face_t *face)
+hb_face_get_glyph_count (const hb_face_t *face)
 {
   return face->get_num_glyphs ();
 }
 
-void
-hb_face_t::load_num_glyphs (void) const
-{
-  hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (reference_table (HB_OT_TAG_maxp));
-  const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
-  num_glyphs = maxp_table->get_num_glyphs ();
-  hb_blob_destroy (maxp_blob);
-}
-
 /**
  * hb_face_get_table_tags:
  * @face: a face.
+ * @start_offset: index of first tag to return.
+ * @table_count: input length of @table_tags array, output number of items written.
+ * @table_tags: array to write tags into.
  *
  * Retrieves table tags for a face, if possible.
  *
@@ -509,7 +505,7 @@
  * Since: 1.6.0
  **/
 unsigned int
-hb_face_get_table_tags (hb_face_t    *face,
+hb_face_get_table_tags (const hb_face_t *face,
                         unsigned int  start_offset,
                         unsigned int *table_count, /* IN/OUT */
                         hb_tag_t     *table_tags /* OUT */)
@@ -528,3 +524,200 @@
 
   return ot_face.get_table_tags (start_offset, table_count, table_tags);
 }
+
+
+/*
+ * Character set.
+ */
+
+
+/**
+ * hb_face_collect_unicodes:
+ * @face: font face.
+ * @out: set to add Unicode characters covered by @face to.
+ *
+ * Since: 1.9.0
+ */
+void
+hb_face_collect_unicodes (hb_face_t *face,
+                          hb_set_t  *out)
+{
+  face->table.cmap->collect_unicodes (out);
+}
+
+/**
+ * hb_face_collect_variation_selectors:
+ * @face: font face.
+ * @out: set to add Variation Selector characters covered by @face to.
+ *
+ *
+ *
+ * Since: 1.9.0
+ */
+void
+hb_face_collect_variation_selectors (hb_face_t *face,
+                                     hb_set_t  *out)
+{
+  face->table.cmap->collect_variation_selectors (out);
+}
+
+/**
+ * hb_face_collect_variation_unicodes:
+ * @face: font face.
+ * @out: set to add Unicode characters for @variation_selector covered by @face to.
+ *
+ *
+ *
+ * Since: 1.9.0
+ */
+void
+hb_face_collect_variation_unicodes (hb_face_t *face,
+                                    hb_codepoint_t variation_selector,
+                                    hb_set_t  *out)
+{
+  face->table.cmap->collect_variation_unicodes (variation_selector, out);
+}
+
+
+
+/*
+ * face-builder: A face that has add_table().
+ */
+
+struct hb_face_builder_data_t
+{
+  struct table_entry_t
+  {
+    int cmp (hb_tag_t t) const
+    {
+      if (t < tag) return -1;
+      if (t > tag) return -1;
+      return 0;
+    }
+
+    hb_tag_t   tag;
+    hb_blob_t *blob;
+  };
+
+  hb_vector_t<table_entry_t> tables;
+};
+
+static hb_face_builder_data_t *
+_hb_face_builder_data_create ()
+{
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) calloc (1, sizeof (hb_face_builder_data_t));
+  if (unlikely (!data))
+    return nullptr;
+
+  data->tables.init ();
+
+  return data;
+}
+
+static void
+_hb_face_builder_data_destroy (void *user_data)
+{
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
+
+  for (unsigned int i = 0; i < data->tables.length; i++)
+    hb_blob_destroy (data->tables[i].blob);
+
+  data->tables.fini ();
+
+  free (data);
+}
+
+static hb_blob_t *
+_hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
+{
+
+  unsigned int table_count = data->tables.length;
+  unsigned int face_length = table_count * 16 + 12;
+
+  for (unsigned int i = 0; i < table_count; i++)
+    face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables[i].blob));
+
+  char *buf = (char *) malloc (face_length);
+  if (unlikely (!buf))
+    return nullptr;
+
+  hb_serialize_context_t c (buf, face_length);
+  c.propagate_error (data->tables);
+  OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
+
+  bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
+  hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
+
+  bool ret = f->serialize_single (&c, sfnt_tag, data->tables.as_array ());
+
+  c.end_serialize ();
+
+  if (unlikely (!ret))
+  {
+    free (buf);
+    return nullptr;
+  }
+
+  return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free);
+}
+
+static hb_blob_t *
+_hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
+{
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
+
+  if (!tag)
+    return _hb_face_builder_data_reference_blob (data);
+
+  hb_face_builder_data_t::table_entry_t *entry = data->tables.lsearch (tag);
+  if (entry)
+    return hb_blob_reference (entry->blob);
+
+  return nullptr;
+}
+
+
+/**
+ * hb_face_builder_create:
+ *
+ * Creates a #hb_face_t that can be used with hb_face_builder_add_table().
+ * After tables are added to the face, it can be compiled to a binary
+ * font file by calling hb_face_reference_blob().
+ *
+ * Return value: (transfer full): New face.
+ *
+ * Since: 1.9.0
+ **/
+hb_face_t *
+hb_face_builder_create ()
+{
+  hb_face_builder_data_t *data = _hb_face_builder_data_create ();
+  if (unlikely (!data)) return hb_face_get_empty ();
+
+  return hb_face_create_for_tables (_hb_face_builder_reference_table,
+                                    data,
+                                    _hb_face_builder_data_destroy);
+}
+
+/**
+ * hb_face_builder_add_table:
+ *
+ * Add table for @tag with data provided by @blob to the face.  @face must
+ * be created using hb_face_builder_create().
+ *
+ * Since: 1.9.0
+ **/
+hb_bool_t
+hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
+{
+  if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
+    return false;
+
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
+  hb_face_builder_data_t::table_entry_t *entry = data->tables.push ();
+
+  entry->tag = tag;
+  entry->blob = hb_blob_reference (blob);
+
+  return true;
+}
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.h	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.h	Fri Mar 01 16:59:19 2019 -0800
@@ -33,6 +33,7 @@
 
 #include "hb-common.h"
 #include "hb-blob.h"
+#include "hb-set.h"
 
 HB_BEGIN_DECLS
 
@@ -76,19 +77,19 @@
                        hb_bool_t           replace);
 
 HB_EXTERN void *
-hb_face_get_user_data (hb_face_t          *face,
+hb_face_get_user_data (const hb_face_t    *face,
                        hb_user_data_key_t *key);
 
 HB_EXTERN void
 hb_face_make_immutable (hb_face_t *face);
 
 HB_EXTERN hb_bool_t
-hb_face_is_immutable (hb_face_t *face);
+hb_face_is_immutable (const hb_face_t *face);
 
 
 HB_EXTERN hb_blob_t *
-hb_face_reference_table (hb_face_t *face,
-                         hb_tag_t   tag);
+hb_face_reference_table (const hb_face_t *face,
+                         hb_tag_t tag);
 
 HB_EXTERN hb_blob_t *
 hb_face_reference_blob (hb_face_t *face);
@@ -98,28 +99,60 @@
                    unsigned int  index);
 
 HB_EXTERN unsigned int
-hb_face_get_index (hb_face_t    *face);
+hb_face_get_index (const hb_face_t *face);
 
 HB_EXTERN void
 hb_face_set_upem (hb_face_t    *face,
                   unsigned int  upem);
 
 HB_EXTERN unsigned int
-hb_face_get_upem (hb_face_t *face);
+hb_face_get_upem (const hb_face_t *face);
 
 HB_EXTERN void
 hb_face_set_glyph_count (hb_face_t    *face,
                          unsigned int  glyph_count);
 
 HB_EXTERN unsigned int
-hb_face_get_glyph_count (hb_face_t *face);
+hb_face_get_glyph_count (const hb_face_t *face);
 
 HB_EXTERN unsigned int
-hb_face_get_table_tags (hb_face_t    *face,
+hb_face_get_table_tags (const hb_face_t *face,
                         unsigned int  start_offset,
                         unsigned int *table_count, /* IN/OUT */
                         hb_tag_t     *table_tags /* OUT */);
 
+
+/*
+ * Character set.
+ */
+
+HB_EXTERN void
+hb_face_collect_unicodes (hb_face_t *face,
+                          hb_set_t  *out);
+
+HB_EXTERN void
+hb_face_collect_variation_selectors (hb_face_t *face,
+                                     hb_set_t  *out);
+
+HB_EXTERN void
+hb_face_collect_variation_unicodes (hb_face_t *face,
+                                    hb_codepoint_t variation_selector,
+                                    hb_set_t  *out);
+
+
+/*
+ * Builder face.
+ */
+
+HB_EXTERN hb_face_t *
+hb_face_builder_create (void);
+
+HB_EXTERN hb_bool_t
+hb_face_builder_add_table (hb_face_t *face,
+                           hb_tag_t   tag,
+                           hb_blob_t *blob);
+
+
 HB_END_DECLS
 
 #endif /* HB_FACE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,109 @@
+/*
+ * Copyright © 2009  Red Hat, Inc.
+ * Copyright © 2011  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_FACE_HH
+#define HB_FACE_HH
+
+#include "hb.hh"
+
+#include "hb-shaper.hh"
+#include "hb-shape-plan.hh"
+#include "hb-ot-face.hh"
+
+
+/*
+ * hb_face_t
+ */
+
+#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, face);
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+
+struct hb_face_t
+{
+  hb_object_header_t header;
+
+  hb_reference_table_func_t  reference_table_func;
+  void                      *user_data;
+  hb_destroy_func_t          destroy;
+
+  unsigned int index;                   /* Face index in a collection, zero-based. */
+  mutable hb_atomic_int_t upem;         /* Units-per-EM. */
+  mutable hb_atomic_int_t num_glyphs;   /* Number of glyphs. */
+
+  hb_shaper_object_dataset_t<hb_face_t> data;/* Various shaper data. */
+  hb_ot_face_t table;                   /* All the face's tables. */
+
+  /* Cache */
+  struct plan_node_t
+  {
+    hb_shape_plan_t *shape_plan;
+    plan_node_t *next;
+  };
+  hb_atomic_ptr_t<plan_node_t> shape_plans;
+
+  hb_blob_t *reference_table (hb_tag_t tag) const
+  {
+    hb_blob_t *blob;
+
+    if (unlikely (!reference_table_func))
+      return hb_blob_get_empty ();
+
+    blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data);
+    if (unlikely (!blob))
+      return hb_blob_get_empty ();
+
+    return blob;
+  }
+
+  HB_PURE_FUNC unsigned int get_upem () const
+  {
+    unsigned int ret = upem.get_relaxed ();
+    if (unlikely (!ret))
+    {
+      return load_upem ();
+    }
+    return ret;
+  }
+
+  unsigned int get_num_glyphs () const
+  {
+    unsigned int ret = num_glyphs.get_relaxed ();
+    if (unlikely (ret == (unsigned int) -1))
+      return load_num_glyphs ();
+    return ret;
+  }
+
+  private:
+  HB_INTERNAL unsigned int load_upem () const;
+  HB_INTERNAL unsigned int load_num_glyphs () const;
+};
+DECLARE_NULL_INSTANCE (hb_face_t);
+
+
+#endif /* HB_FACE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-fallback-shape.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-fallback-shape.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,28 +24,23 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#define HB_SHAPER fallback
-#include "hb-shaper-impl-private.hh"
-
-
-HB_SHAPER_DATA_ENSURE_DEFINE(fallback, face)
-HB_SHAPER_DATA_ENSURE_DEFINE(fallback, font)
+#include "hb-shaper-impl.hh"
 
 
 /*
  * shaper face data
  */
 
-struct hb_fallback_shaper_face_data_t {};
+struct hb_fallback_face_data_t {};
 
-hb_fallback_shaper_face_data_t *
+hb_fallback_face_data_t *
 _hb_fallback_shaper_face_data_create (hb_face_t *face HB_UNUSED)
 {
-  return (hb_fallback_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+  return (hb_fallback_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
-_hb_fallback_shaper_face_data_destroy (hb_fallback_shaper_face_data_t *data HB_UNUSED)
+_hb_fallback_shaper_face_data_destroy (hb_fallback_face_data_t *data HB_UNUSED)
 {
 }
 
@@ -54,38 +49,16 @@
  * shaper font data
  */
 
-struct hb_fallback_shaper_font_data_t {};
+struct hb_fallback_font_data_t {};
 
-hb_fallback_shaper_font_data_t *
+hb_fallback_font_data_t *
 _hb_fallback_shaper_font_data_create (hb_font_t *font HB_UNUSED)
 {
-  return (hb_fallback_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+  return (hb_fallback_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
-_hb_fallback_shaper_font_data_destroy (hb_fallback_shaper_font_data_t *data HB_UNUSED)
-{
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_fallback_shaper_shape_plan_data_t {};
-
-hb_fallback_shaper_shape_plan_data_t *
-_hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-                                            const hb_feature_t *user_features HB_UNUSED,
-                                            unsigned int        num_user_features HB_UNUSED,
-                                            const int          *coords HB_UNUSED,
-                                            unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_fallback_shaper_shape_plan_data_destroy (hb_fallback_shaper_shape_plan_data_t *data HB_UNUSED)
+_hb_fallback_shaper_font_data_destroy (hb_fallback_font_data_t *data HB_UNUSED)
 {
 }
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,565 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  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_FONT_PRIVATE_HH
-#define HB_FONT_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-object-private.hh"
-#include "hb-face-private.hh"
-#include "hb-shaper-private.hh"
-
-
-
-/*
- * hb_font_funcs_t
- */
-
-#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
-  HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
-  HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
-  HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
-  HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_name) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
-  /* ^--- Add new callbacks here */
-
-struct hb_font_funcs_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t immutable;
-
-  struct {
-#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
-    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-  } user_data;
-
-  struct {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
-    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-  } destroy;
-
-  /* Don't access these directly.  Call font->get_*() instead. */
-  union get_t {
-    struct get_funcs_t {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
-      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-    } f;
-    void (*array[0
-#define HB_FONT_FUNC_IMPLEMENT(name) +1
-      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-                ]) (void);
-  } get;
-};
-
-
-
-/*
- * hb_font_t
- */
-
-struct hb_font_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t immutable;
-
-  hb_font_t *parent;
-  hb_face_t *face;
-
-  int x_scale;
-  int y_scale;
-
-  unsigned int x_ppem;
-  unsigned int y_ppem;
-
-  float ptem;
-
-  /* Font variation coordinates. */
-  unsigned int num_coords;
-  int *coords;
-
-  hb_font_funcs_t   *klass;
-  void              *user_data;
-  hb_destroy_func_t  destroy;
-
-  struct hb_shaper_data_t shaper_data;
-
-
-  /* Convert from font-space to user-space */
-  inline int dir_scale (hb_direction_t direction)
-  { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
-  inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
-  inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
-  inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
-  inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
-  inline float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
-  inline float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
-  inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
-  { return em_scale (v, dir_scale (direction)); }
-
-  /* Convert from parent-font user-space to our user-space */
-  inline hb_position_t parent_scale_x_distance (hb_position_t v) {
-    if (unlikely (parent && parent->x_scale != x_scale))
-      return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
-    return v;
-  }
-  inline hb_position_t parent_scale_y_distance (hb_position_t v) {
-    if (unlikely (parent && parent->y_scale != y_scale))
-      return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
-    return v;
-  }
-  inline hb_position_t parent_scale_x_position (hb_position_t v) {
-    return parent_scale_x_distance (v);
-  }
-  inline hb_position_t parent_scale_y_position (hb_position_t v) {
-    return parent_scale_y_distance (v);
-  }
-
-  inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
-    *x = parent_scale_x_distance (*x);
-    *y = parent_scale_y_distance (*y);
-  }
-  inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
-    *x = parent_scale_x_position (*x);
-    *y = parent_scale_y_position (*y);
-  }
-
-
-  /* Public getters */
-
-  HB_INTERNAL bool has_func (unsigned int i);
-
-  /* has_* ... */
-#define HB_FONT_FUNC_IMPLEMENT(name) \
-  bool \
-  has_##name##_func (void) \
-  { \
-    hb_font_funcs_t *funcs = this->klass; \
-    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
-    return has_func (i); \
-  }
-  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-
-  inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
-  {
-    memset (extents, 0, sizeof (*extents));
-    return klass->get.f.font_h_extents (this, user_data,
-                                        extents,
-                                        klass->user_data.font_h_extents);
-  }
-  inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
-  {
-    memset (extents, 0, sizeof (*extents));
-    return klass->get.f.font_v_extents (this, user_data,
-                                        extents,
-                                        klass->user_data.font_v_extents);
-  }
-
-  inline bool has_glyph (hb_codepoint_t unicode)
-  {
-    hb_codepoint_t glyph;
-    return get_nominal_glyph (unicode, &glyph);
-  }
-
-  inline hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
-                                      hb_codepoint_t *glyph)
-  {
-    *glyph = 0;
-    return klass->get.f.nominal_glyph (this, user_data,
-                                       unicode, glyph,
-                                       klass->user_data.nominal_glyph);
-  }
-
-  inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-                                        hb_codepoint_t *glyph)
-  {
-    *glyph = 0;
-    return klass->get.f.variation_glyph (this, user_data,
-                                         unicode, variation_selector, glyph,
-                                         klass->user_data.variation_glyph);
-  }
-
-  inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
-  {
-    return klass->get.f.glyph_h_advance (this, user_data,
-                                         glyph,
-                                         klass->user_data.glyph_h_advance);
-  }
-
-  inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
-  {
-    return klass->get.f.glyph_v_advance (this, user_data,
-                                         glyph,
-                                         klass->user_data.glyph_v_advance);
-  }
-
-  inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
-                                       hb_position_t *x, hb_position_t *y)
-  {
-    *x = *y = 0;
-    return klass->get.f.glyph_h_origin (this, user_data,
-                                        glyph, x, y,
-                                        klass->user_data.glyph_h_origin);
-  }
-
-  inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
-                                       hb_position_t *x, hb_position_t *y)
-  {
-    *x = *y = 0;
-    return klass->get.f.glyph_v_origin (this, user_data,
-                                        glyph, x, y,
-                                        klass->user_data.glyph_v_origin);
-  }
-
-  inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
-  {
-    return klass->get.f.glyph_h_kerning (this, user_data,
-                                         left_glyph, right_glyph,
-                                         klass->user_data.glyph_h_kerning);
-  }
-
-  inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
-  {
-    return klass->get.f.glyph_v_kerning (this, user_data,
-                                         top_glyph, bottom_glyph,
-                                         klass->user_data.glyph_v_kerning);
-  }
-
-  inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
-                                      hb_glyph_extents_t *extents)
-  {
-    memset (extents, 0, sizeof (*extents));
-    return klass->get.f.glyph_extents (this, user_data,
-                                       glyph,
-                                       extents,
-                                       klass->user_data.glyph_extents);
-  }
-
-  inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
-                                            hb_position_t *x, hb_position_t *y)
-  {
-    *x = *y = 0;
-    return klass->get.f.glyph_contour_point (this, user_data,
-                                             glyph, point_index,
-                                             x, y,
-                                             klass->user_data.glyph_contour_point);
-  }
-
-  inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
-                                   char *name, unsigned int size)
-  {
-    if (size) *name = '\0';
-    return klass->get.f.glyph_name (this, user_data,
-                                    glyph,
-                                    name, size,
-                                    klass->user_data.glyph_name);
-  }
-
-  inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
-                                        hb_codepoint_t *glyph)
-  {
-    *glyph = 0;
-    if (len == -1) len = strlen (name);
-    return klass->get.f.glyph_from_name (this, user_data,
-                                         name, len,
-                                         glyph,
-                                         klass->user_data.glyph_from_name);
-  }
-
-
-  /* A bit higher-level, and with fallback */
-
-  inline void get_h_extents_with_fallback (hb_font_extents_t *extents)
-  {
-    if (!get_font_h_extents (extents))
-    {
-      extents->ascender = y_scale * .8;
-      extents->descender = extents->ascender - y_scale;
-      extents->line_gap = 0;
-    }
-  }
-  inline void get_v_extents_with_fallback (hb_font_extents_t *extents)
-  {
-    if (!get_font_v_extents (extents))
-    {
-      extents->ascender = x_scale / 2;
-      extents->descender = extents->ascender - x_scale;
-      extents->line_gap = 0;
-    }
-  }
-
-  inline void get_extents_for_direction (hb_direction_t direction,
-                                         hb_font_extents_t *extents)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
-      get_h_extents_with_fallback (extents);
-    else
-      get_v_extents_with_fallback (extents);
-  }
-
-  inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
-                                               hb_direction_t direction,
-                                               hb_position_t *x, hb_position_t *y)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
-      *x = get_glyph_h_advance (glyph);
-      *y = 0;
-    } else {
-      *x = 0;
-      *y = get_glyph_v_advance (glyph);
-    }
-  }
-
-  inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
-                                             hb_position_t *x, hb_position_t *y)
-  {
-    *x = get_glyph_h_advance (glyph) / 2;
-
-    /* TODO cache this somehow?! */
-    hb_font_extents_t extents;
-    get_h_extents_with_fallback (&extents);
-    *y = extents.ascender;
-  }
-
-  inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
-                                                hb_position_t *x, hb_position_t *y)
-  {
-    if (!get_glyph_h_origin (glyph, x, y) &&
-         get_glyph_v_origin (glyph, x, y))
-    {
-      hb_position_t dx, dy;
-      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
-      *x -= dx; *y -= dy;
-    }
-  }
-  inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
-                                                hb_position_t *x, hb_position_t *y)
-  {
-    if (!get_glyph_v_origin (glyph, x, y) &&
-         get_glyph_h_origin (glyph, x, y))
-    {
-      hb_position_t dx, dy;
-      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
-      *x += dx; *y += dy;
-    }
-  }
-
-  inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
-                                              hb_direction_t direction,
-                                              hb_position_t *x, hb_position_t *y)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
-      get_glyph_h_origin_with_fallback (glyph, x, y);
-    else
-      get_glyph_v_origin_with_fallback (glyph, x, y);
-  }
-
-  inline void add_glyph_h_origin (hb_codepoint_t glyph,
-                                  hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x += origin_x;
-    *y += origin_y;
-  }
-  inline void add_glyph_v_origin (hb_codepoint_t glyph,
-                                  hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x += origin_x;
-    *y += origin_y;
-  }
-  inline void add_glyph_origin_for_direction (hb_codepoint_t glyph,
-                                              hb_direction_t direction,
-                                              hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
-
-    *x += origin_x;
-    *y += origin_y;
-  }
-
-  inline void subtract_glyph_h_origin (hb_codepoint_t glyph,
-                                       hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x -= origin_x;
-    *y -= origin_y;
-  }
-  inline void subtract_glyph_v_origin (hb_codepoint_t glyph,
-                                       hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x -= origin_x;
-    *y -= origin_y;
-  }
-  inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
-                                                   hb_direction_t direction,
-                                                   hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
-
-    *x -= origin_x;
-    *y -= origin_y;
-  }
-
-  inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-                                               hb_direction_t direction,
-                                               hb_position_t *x, hb_position_t *y)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
-      *x = get_glyph_h_kerning (first_glyph, second_glyph);
-      *y = 0;
-    } else {
-      *x = 0;
-      *y = get_glyph_v_kerning (first_glyph, second_glyph);
-    }
-  }
-
-  inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
-                                                 hb_direction_t direction,
-                                                 hb_glyph_extents_t *extents)
-  {
-    hb_bool_t ret = get_glyph_extents (glyph, extents);
-
-    if (ret)
-      subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
-
-    return ret;
-  }
-
-  inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
-                                                       hb_direction_t direction,
-                                                       hb_position_t *x, hb_position_t *y)
-  {
-    hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
-
-    if (ret)
-      subtract_glyph_origin_for_direction (glyph, direction, x, y);
-
-    return ret;
-  }
-
-  /* Generates gidDDD if glyph has no name. */
-  inline void
-  glyph_to_string (hb_codepoint_t glyph,
-                   char *s, unsigned int size)
-  {
-    if (get_glyph_name (glyph, s, size)) return;
-
-    if (size && snprintf (s, size, "gid%u", glyph) < 0)
-      *s = '\0';
-  }
-
-  /* Parses gidDDD and uniUUUU strings automatically. */
-  inline hb_bool_t
-  glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
-                     hb_codepoint_t *glyph)
-  {
-    if (get_glyph_from_name (s, len, glyph)) return true;
-
-    if (len == -1) len = strlen (s);
-
-    /* Straight glyph index. */
-    if (hb_codepoint_parse (s, len, 10, glyph))
-      return true;
-
-    if (len > 3)
-    {
-      /* gidDDD syntax for glyph indices. */
-      if (0 == strncmp (s, "gid", 3) &&
-          hb_codepoint_parse (s + 3, len - 3, 10, glyph))
-        return true;
-
-      /* uniUUUU and other Unicode character indices. */
-      hb_codepoint_t unichar;
-      if (0 == strncmp (s, "uni", 3) &&
-          hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
-          get_nominal_glyph (unichar, glyph))
-        return true;
-    }
-
-    return false;
-  }
-
-  inline hb_position_t em_scale (int16_t v, int scale)
-  {
-    int upem = face->get_upem ();
-    int64_t scaled = v * (int64_t) scale;
-    scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
-    return (hb_position_t) (scaled / upem);
-  }
-  inline hb_position_t em_scalef (float v, int scale)
-  {
-    return (hb_position_t) round (v * scale / face->get_upem ());
-  }
-  inline float em_fscale (int16_t v, int scale)
-  {
-    return (float) v * scale / face->get_upem ();
-  }
-};
-
-#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-
-
-#endif /* HB_FONT_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -26,9 +26,25 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
+
+#include "hb-font.hh"
+#include "hb-machinery.hh"
+
+#include "hb-ot.h"
+
 
-#include "hb-font-private.hh"
+/**
+ * SECTION:hb-font
+ * @title: hb-font
+ * @short_description: Font objects
+ * @include: hb.h
+ *
+ * Font objects represent a font face at a certain size and other
+ * parameters (pixels per EM, points per EM, variation settings.)
+ * Fonts are created from font faces, and are used as input to
+ * hb_shape() among other things.
+ **/
 
 
 /*
@@ -38,23 +54,23 @@
 static hb_bool_t
 hb_font_get_font_h_extents_nil (hb_font_t *font HB_UNUSED,
                                 void *font_data HB_UNUSED,
-                                hb_font_extents_t *metrics,
+                                hb_font_extents_t *extents,
                                 void *user_data HB_UNUSED)
 {
-  memset (metrics, 0, sizeof (*metrics));
+  memset (extents, 0, sizeof (*extents));
   return false;
 }
 static hb_bool_t
-hb_font_get_font_h_extents_parent (hb_font_t *font,
-                                   void *font_data HB_UNUSED,
-                                   hb_font_extents_t *metrics,
-                                   void *user_data HB_UNUSED)
+hb_font_get_font_h_extents_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    hb_font_extents_t *extents,
+                                    void *user_data HB_UNUSED)
 {
-  hb_bool_t ret = font->parent->get_font_h_extents (metrics);
+  hb_bool_t ret = font->parent->get_font_h_extents (extents);
   if (ret) {
-    metrics->ascender = font->parent_scale_y_distance (metrics->ascender);
-    metrics->descender = font->parent_scale_y_distance (metrics->descender);
-    metrics->line_gap = font->parent_scale_y_distance (metrics->line_gap);
+    extents->ascender = font->parent_scale_y_distance (extents->ascender);
+    extents->descender = font->parent_scale_y_distance (extents->descender);
+    extents->line_gap = font->parent_scale_y_distance (extents->line_gap);
   }
   return ret;
 }
@@ -62,23 +78,23 @@
 static hb_bool_t
 hb_font_get_font_v_extents_nil (hb_font_t *font HB_UNUSED,
                                 void *font_data HB_UNUSED,
-                                hb_font_extents_t *metrics,
+                                hb_font_extents_t *extents,
                                 void *user_data HB_UNUSED)
 {
-  memset (metrics, 0, sizeof (*metrics));
+  memset (extents, 0, sizeof (*extents));
   return false;
 }
 static hb_bool_t
-hb_font_get_font_v_extents_parent (hb_font_t *font,
-                                   void *font_data HB_UNUSED,
-                                   hb_font_extents_t *metrics,
-                                   void *user_data HB_UNUSED)
+hb_font_get_font_v_extents_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    hb_font_extents_t *extents,
+                                    void *user_data HB_UNUSED)
 {
-  hb_bool_t ret = font->parent->get_font_v_extents (metrics);
+  hb_bool_t ret = font->parent->get_font_v_extents (extents);
   if (ret) {
-    metrics->ascender = font->parent_scale_x_distance (metrics->ascender);
-    metrics->descender = font->parent_scale_x_distance (metrics->descender);
-    metrics->line_gap = font->parent_scale_x_distance (metrics->line_gap);
+    extents->ascender = font->parent_scale_x_distance (extents->ascender);
+    extents->descender = font->parent_scale_x_distance (extents->descender);
+    extents->line_gap = font->parent_scale_x_distance (extents->line_gap);
   }
   return ret;
 }
@@ -86,7 +102,7 @@
 static hb_bool_t
 hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED,
                                void *font_data HB_UNUSED,
-                               hb_codepoint_t unicode,
+                               hb_codepoint_t unicode HB_UNUSED,
                                hb_codepoint_t *glyph,
                                void *user_data HB_UNUSED)
 {
@@ -94,20 +110,53 @@
   return false;
 }
 static hb_bool_t
-hb_font_get_nominal_glyph_parent (hb_font_t *font,
-                                  void *font_data HB_UNUSED,
-                                  hb_codepoint_t unicode,
-                                  hb_codepoint_t *glyph,
-                                  void *user_data HB_UNUSED)
+hb_font_get_nominal_glyph_default (hb_font_t *font,
+                                   void *font_data HB_UNUSED,
+                                   hb_codepoint_t unicode,
+                                   hb_codepoint_t *glyph,
+                                   void *user_data HB_UNUSED)
 {
+  if (font->has_nominal_glyphs_func_set ())
+  {
+    return font->get_nominal_glyphs (1, &unicode, 0, glyph, 0);
+  }
   return font->parent->get_nominal_glyph (unicode, glyph);
 }
 
+#define hb_font_get_nominal_glyphs_nil hb_font_get_nominal_glyphs_default
+static unsigned int
+hb_font_get_nominal_glyphs_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    unsigned int count,
+                                    const hb_codepoint_t *first_unicode,
+                                    unsigned int unicode_stride,
+                                    hb_codepoint_t *first_glyph,
+                                    unsigned int glyph_stride,
+                                    void *user_data HB_UNUSED)
+{
+  if (font->has_nominal_glyph_func_set ())
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (!font->get_nominal_glyph (*first_unicode, first_glyph))
+        return i;
+
+      first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
+      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+    }
+    return count;
+  }
+
+  return font->parent->get_nominal_glyphs (count,
+                                           first_unicode, unicode_stride,
+                                           first_glyph, glyph_stride);
+}
+
 static hb_bool_t
 hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED,
                                  void *font_data HB_UNUSED,
-                                 hb_codepoint_t unicode,
-                                 hb_codepoint_t variation_selector,
+                                 hb_codepoint_t unicode HB_UNUSED,
+                                 hb_codepoint_t variation_selector HB_UNUSED,
                                  hb_codepoint_t *glyph,
                                  void *user_data HB_UNUSED)
 {
@@ -115,12 +164,12 @@
   return false;
 }
 static hb_bool_t
-hb_font_get_variation_glyph_parent (hb_font_t *font,
-                                    void *font_data HB_UNUSED,
-                                    hb_codepoint_t unicode,
-                                    hb_codepoint_t variation_selector,
-                                    hb_codepoint_t *glyph,
-                                    void *user_data HB_UNUSED)
+hb_font_get_variation_glyph_default (hb_font_t *font,
+                                     void *font_data HB_UNUSED,
+                                     hb_codepoint_t unicode,
+                                     hb_codepoint_t variation_selector,
+                                     hb_codepoint_t *glyph,
+                                     void *user_data HB_UNUSED)
 {
   return font->parent->get_variation_glyph (unicode, variation_selector, glyph);
 }
@@ -129,42 +178,118 @@
 static hb_position_t
 hb_font_get_glyph_h_advance_nil (hb_font_t *font,
                                  void *font_data HB_UNUSED,
-                                 hb_codepoint_t glyph,
+                                 hb_codepoint_t glyph HB_UNUSED,
                                  void *user_data HB_UNUSED)
 {
   return font->x_scale;
 }
 static hb_position_t
-hb_font_get_glyph_h_advance_parent (hb_font_t *font,
-                                    void *font_data HB_UNUSED,
-                                    hb_codepoint_t glyph,
-                                    void *user_data HB_UNUSED)
+hb_font_get_glyph_h_advance_default (hb_font_t *font,
+                                     void *font_data HB_UNUSED,
+                                     hb_codepoint_t glyph,
+                                     void *user_data HB_UNUSED)
 {
+  if (font->has_glyph_h_advances_func_set ())
+  {
+    hb_position_t ret;
+    font->get_glyph_h_advances (1, &glyph, 0, &ret, 0);
+    return ret;
+  }
   return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
 }
 
 static hb_position_t
 hb_font_get_glyph_v_advance_nil (hb_font_t *font,
                                  void *font_data HB_UNUSED,
-                                 hb_codepoint_t glyph,
+                                 hb_codepoint_t glyph HB_UNUSED,
                                  void *user_data HB_UNUSED)
 {
   /* TODO use font_extents.ascender+descender */
   return font->y_scale;
 }
 static hb_position_t
-hb_font_get_glyph_v_advance_parent (hb_font_t *font,
-                                    void *font_data HB_UNUSED,
-                                    hb_codepoint_t glyph,
-                                    void *user_data HB_UNUSED)
+hb_font_get_glyph_v_advance_default (hb_font_t *font,
+                                     void *font_data HB_UNUSED,
+                                     hb_codepoint_t glyph,
+                                     void *user_data HB_UNUSED)
+{
+  if (font->has_glyph_v_advances_func_set ())
+  {
+    hb_position_t ret;
+    font->get_glyph_v_advances (1, &glyph, 0, &ret, 0);
+    return ret;
+  }
+  return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
+}
+
+#define hb_font_get_glyph_h_advances_nil hb_font_get_glyph_h_advances_default
+static void
+hb_font_get_glyph_h_advances_default (hb_font_t* font,
+                                      void* font_data HB_UNUSED,
+                                      unsigned int count,
+                                      const hb_codepoint_t *first_glyph,
+                                      unsigned int glyph_stride,
+                                      hb_position_t *first_advance,
+                                      unsigned int advance_stride,
+                                      void *user_data HB_UNUSED)
 {
-  return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
+  if (font->has_glyph_h_advance_func_set ())
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      *first_advance = font->get_glyph_h_advance (*first_glyph);
+      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+    }
+    return;
+  }
+
+  font->parent->get_glyph_h_advances (count,
+                                      first_glyph, glyph_stride,
+                                      first_advance, advance_stride);
+  for (unsigned int i = 0; i < count; i++)
+  {
+    *first_advance = font->parent_scale_x_distance (*first_advance);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
+}
+
+#define hb_font_get_glyph_v_advances_nil hb_font_get_glyph_v_advances_default
+static void
+hb_font_get_glyph_v_advances_default (hb_font_t* font,
+                                      void* font_data HB_UNUSED,
+                                      unsigned int count,
+                                      const hb_codepoint_t *first_glyph,
+                                      unsigned int glyph_stride,
+                                      hb_position_t *first_advance,
+                                      unsigned int advance_stride,
+                                      void *user_data HB_UNUSED)
+{
+  if (font->has_glyph_v_advance_func_set ())
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      *first_advance = font->get_glyph_v_advance (*first_glyph);
+      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+    }
+    return;
+  }
+
+  font->parent->get_glyph_v_advances (count,
+                                      first_glyph, glyph_stride,
+                                      first_advance, advance_stride);
+  for (unsigned int i = 0; i < count; i++)
+  {
+    *first_advance = font->parent_scale_y_distance (*first_advance);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
 }
 
 static hb_bool_t
 hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
                                 void *font_data HB_UNUSED,
-                                hb_codepoint_t glyph,
+                                hb_codepoint_t glyph HB_UNUSED,
                                 hb_position_t *x,
                                 hb_position_t *y,
                                 void *user_data HB_UNUSED)
@@ -173,12 +298,12 @@
   return true;
 }
 static hb_bool_t
-hb_font_get_glyph_h_origin_parent (hb_font_t *font,
-                                   void *font_data HB_UNUSED,
-                                   hb_codepoint_t glyph,
-                                   hb_position_t *x,
-                                   hb_position_t *y,
-                                   void *user_data HB_UNUSED)
+hb_font_get_glyph_h_origin_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    hb_codepoint_t glyph,
+                                    hb_position_t *x,
+                                    hb_position_t *y,
+                                    void *user_data HB_UNUSED)
 {
   hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
   if (ret)
@@ -189,7 +314,7 @@
 static hb_bool_t
 hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
                                 void *font_data HB_UNUSED,
-                                hb_codepoint_t glyph,
+                                hb_codepoint_t glyph HB_UNUSED,
                                 hb_position_t *x,
                                 hb_position_t *y,
                                 void *user_data HB_UNUSED)
@@ -198,12 +323,12 @@
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_v_origin_parent (hb_font_t *font,
-                                   void *font_data HB_UNUSED,
-                                   hb_codepoint_t glyph,
-                                   hb_position_t *x,
-                                   hb_position_t *y,
-                                   void *user_data HB_UNUSED)
+hb_font_get_glyph_v_origin_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    hb_codepoint_t glyph,
+                                    hb_position_t *x,
+                                    hb_position_t *y,
+                                    void *user_data HB_UNUSED)
 {
   hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
   if (ret)
@@ -214,18 +339,18 @@
 static hb_position_t
 hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
                                  void *font_data HB_UNUSED,
-                                 hb_codepoint_t left_glyph,
-                                 hb_codepoint_t right_glyph,
+                                 hb_codepoint_t left_glyph HB_UNUSED,
+                                 hb_codepoint_t right_glyph HB_UNUSED,
                                  void *user_data HB_UNUSED)
 {
   return 0;
 }
 static hb_position_t
-hb_font_get_glyph_h_kerning_parent (hb_font_t *font,
-                                    void *font_data HB_UNUSED,
-                                    hb_codepoint_t left_glyph,
-                                    hb_codepoint_t right_glyph,
-                                    void *user_data HB_UNUSED)
+hb_font_get_glyph_h_kerning_default (hb_font_t *font,
+                                     void *font_data HB_UNUSED,
+                                     hb_codepoint_t left_glyph,
+                                     hb_codepoint_t right_glyph,
+                                     void *user_data HB_UNUSED)
 {
   return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
 }
@@ -233,18 +358,18 @@
 static hb_position_t
 hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
                                  void *font_data HB_UNUSED,
-                                 hb_codepoint_t top_glyph,
-                                 hb_codepoint_t bottom_glyph,
+                                 hb_codepoint_t top_glyph HB_UNUSED,
+                                 hb_codepoint_t bottom_glyph HB_UNUSED,
                                  void *user_data HB_UNUSED)
 {
   return 0;
 }
 static hb_position_t
-hb_font_get_glyph_v_kerning_parent (hb_font_t *font,
-                                    void *font_data HB_UNUSED,
-                                    hb_codepoint_t top_glyph,
-                                    hb_codepoint_t bottom_glyph,
-                                    void *user_data HB_UNUSED)
+hb_font_get_glyph_v_kerning_default (hb_font_t *font,
+                                     void *font_data HB_UNUSED,
+                                     hb_codepoint_t top_glyph,
+                                     hb_codepoint_t bottom_glyph,
+                                     void *user_data HB_UNUSED)
 {
   return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
 }
@@ -252,7 +377,7 @@
 static hb_bool_t
 hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
                                void *font_data HB_UNUSED,
-                               hb_codepoint_t glyph,
+                               hb_codepoint_t glyph HB_UNUSED,
                                hb_glyph_extents_t *extents,
                                void *user_data HB_UNUSED)
 {
@@ -260,11 +385,11 @@
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_extents_parent (hb_font_t *font,
-                                  void *font_data HB_UNUSED,
-                                  hb_codepoint_t glyph,
-                                  hb_glyph_extents_t *extents,
-                                  void *user_data HB_UNUSED)
+hb_font_get_glyph_extents_default (hb_font_t *font,
+                                   void *font_data HB_UNUSED,
+                                   hb_codepoint_t glyph,
+                                   hb_glyph_extents_t *extents,
+                                   void *user_data HB_UNUSED)
 {
   hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
   if (ret) {
@@ -277,8 +402,8 @@
 static hb_bool_t
 hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
                                      void *font_data HB_UNUSED,
-                                     hb_codepoint_t glyph,
-                                     unsigned int point_index,
+                                     hb_codepoint_t glyph HB_UNUSED,
+                                     unsigned int point_index HB_UNUSED,
                                      hb_position_t *x,
                                      hb_position_t *y,
                                      void *user_data HB_UNUSED)
@@ -287,13 +412,13 @@
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_contour_point_parent (hb_font_t *font,
-                                        void *font_data HB_UNUSED,
-                                        hb_codepoint_t glyph,
-                                        unsigned int point_index,
-                                        hb_position_t *x,
-                                        hb_position_t *y,
-                                        void *user_data HB_UNUSED)
+hb_font_get_glyph_contour_point_default (hb_font_t *font,
+                                         void *font_data HB_UNUSED,
+                                         hb_codepoint_t glyph,
+                                         unsigned int point_index,
+                                         hb_position_t *x,
+                                         hb_position_t *y,
+                                         void *user_data HB_UNUSED)
 {
   hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
   if (ret)
@@ -304,7 +429,7 @@
 static hb_bool_t
 hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED,
                             void *font_data HB_UNUSED,
-                            hb_codepoint_t glyph,
+                            hb_codepoint_t glyph HB_UNUSED,
                             char *name, unsigned int size,
                             void *user_data HB_UNUSED)
 {
@@ -312,11 +437,11 @@
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_name_parent (hb_font_t *font,
-                               void *font_data HB_UNUSED,
-                               hb_codepoint_t glyph,
-                               char *name, unsigned int size,
-                               void *user_data HB_UNUSED)
+hb_font_get_glyph_name_default (hb_font_t *font,
+                                void *font_data HB_UNUSED,
+                                hb_codepoint_t glyph,
+                                char *name, unsigned int size,
+                                void *user_data HB_UNUSED)
 {
   return font->parent->get_glyph_name (glyph, name, size);
 }
@@ -324,7 +449,8 @@
 static hb_bool_t
 hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED,
                                  void *font_data HB_UNUSED,
-                                 const char *name, int len, /* -1 means nul-terminated */
+                                 const char *name HB_UNUSED,
+                                 int len HB_UNUSED, /* -1 means nul-terminated */
                                  hb_codepoint_t *glyph,
                                  void *user_data HB_UNUSED)
 {
@@ -332,20 +458,19 @@
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_from_name_parent (hb_font_t *font,
-                                    void *font_data HB_UNUSED,
-                                    const char *name, int len, /* -1 means nul-terminated */
-                                    hb_codepoint_t *glyph,
-                                    void *user_data HB_UNUSED)
+hb_font_get_glyph_from_name_default (hb_font_t *font,
+                                     void *font_data HB_UNUSED,
+                                     const char *name, int len, /* -1 means nul-terminated */
+                                     hb_codepoint_t *glyph,
+                                     void *user_data HB_UNUSED)
 {
   return font->parent->get_glyph_from_name (name, len, glyph);
 }
 
-static const hb_font_funcs_t _hb_font_funcs_nil = {
+DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
+{
   HB_OBJECT_HEADER_STATIC,
 
-  true, /* immutable */
-
   {
 #define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
@@ -364,11 +489,10 @@
     }
   }
 };
-static const hb_font_funcs_t _hb_font_funcs_parent = {
+
+static const hb_font_funcs_t _hb_font_funcs_default = {
   HB_OBJECT_HEADER_STATIC,
 
-  true, /* immutable */
-
   {
 #define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
@@ -381,7 +505,7 @@
   },
   {
     {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent,
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_default,
       HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 #undef HB_FONT_FUNC_IMPLEMENT
     }
@@ -399,14 +523,14 @@
  * Since: 0.9.2
  **/
 hb_font_funcs_t *
-hb_font_funcs_create (void)
+hb_font_funcs_create ()
 {
   hb_font_funcs_t *ffuncs;
 
   if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
     return hb_font_funcs_get_empty ();
 
-  ffuncs->get = _hb_font_funcs_parent.get;
+  ffuncs->get = _hb_font_funcs_default.get;
 
   return ffuncs;
 }
@@ -421,9 +545,9 @@
  * Since: 0.9.2
  **/
 hb_font_funcs_t *
-hb_font_funcs_get_empty (void)
+hb_font_funcs_get_empty ()
 {
-  return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_parent);
+  return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_default);
 }
 
 /**
@@ -517,10 +641,10 @@
 void
 hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
 {
-  if (unlikely (hb_object_is_inert (ffuncs)))
+  if (hb_object_is_immutable (ffuncs))
     return;
 
-  ffuncs->immutable = true;
+  hb_object_make_immutable (ffuncs);
 }
 
 /**
@@ -536,7 +660,7 @@
 hb_bool_t
 hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
 {
-  return ffuncs->immutable;
+  return hb_object_is_immutable (ffuncs);
 }
 
 
@@ -548,7 +672,7 @@
                                  void                        *user_data, \
                                  hb_destroy_func_t            destroy)   \
 {                                                                        \
-  if (ffuncs->immutable) {                                               \
+  if (hb_object_is_immutable (ffuncs)) {                                 \
     if (destroy)                                                         \
       destroy (user_data);                                               \
     return;                                                              \
@@ -562,9 +686,9 @@
     ffuncs->user_data.name = user_data;                                  \
     ffuncs->destroy.name = destroy;                                      \
   } else {                                                               \
-    ffuncs->get.f.name = hb_font_get_##name##_parent;                    \
-    ffuncs->user_data.name = nullptr;                                       \
-    ffuncs->destroy.name = nullptr;                                         \
+    ffuncs->get.f.name = hb_font_get_##name##_default;                   \
+    ffuncs->user_data.name = nullptr;                                    \
+    ffuncs->destroy.name = nullptr;                                      \
   }                                                                      \
 }
 
@@ -572,11 +696,16 @@
 #undef HB_FONT_FUNC_IMPLEMENT
 
 bool
+hb_font_t::has_func_set (unsigned int i)
+{
+  return this->klass->get.array[i] != _hb_font_funcs_default.get.array[i];
+}
+
+bool
 hb_font_t::has_func (unsigned int i)
 {
-  if (parent && parent != hb_font_get_empty () && parent->has_func (i))
-    return true;
-  return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i];
+  return has_func_set (i) ||
+         (parent && parent != &_hb_Null_hb_font_t && parent->has_func (i));
 }
 
 /* Public getters */
@@ -718,6 +847,43 @@
 }
 
 /**
+ * hb_font_get_glyph_h_advances:
+ * @font: a font.
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+void
+hb_font_get_glyph_h_advances (hb_font_t* font,
+                              unsigned int count,
+                              const hb_codepoint_t *first_glyph,
+                              unsigned glyph_stride,
+                              hb_position_t *first_advance,
+                              unsigned advance_stride)
+{
+  font->get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+}
+/**
+ * hb_font_get_glyph_v_advances:
+ * @font: a font.
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+void
+hb_font_get_glyph_v_advances (hb_font_t* font,
+                              unsigned int count,
+                              const hb_codepoint_t *first_glyph,
+                              unsigned glyph_stride,
+                              hb_position_t *first_advance,
+                              unsigned advance_stride)
+{
+  font->get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+}
+
+/**
  * hb_font_get_glyph_h_origin:
  * @font: a font.
  * @glyph:
@@ -770,6 +936,7 @@
  * Return value:
  *
  * Since: 0.9.2
+ * Deprecated: 2.0.0
  **/
 hb_position_t
 hb_font_get_glyph_h_kerning (hb_font_t *font,
@@ -789,6 +956,7 @@
  * Return value:
  *
  * Since: 0.9.2
+ * Deprecated: 2.0.0
  **/
 hb_position_t
 hb_font_get_glyph_v_kerning (hb_font_t *font,
@@ -888,7 +1056,7 @@
  * hb_font_get_extents_for_direction:
  * @font: a font.
  * @direction:
- * @extents:
+ * @extents: (out):
  *
  *
  *
@@ -921,6 +1089,26 @@
 {
   return font->get_glyph_advance_for_direction (glyph, direction, x, y);
 }
+/**
+ * hb_font_get_glyph_advances_for_direction:
+ * @font: a font.
+ * @direction:
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+HB_EXTERN void
+hb_font_get_glyph_advances_for_direction (hb_font_t* font,
+                                          hb_direction_t direction,
+                                          unsigned int count,
+                                          const hb_codepoint_t *first_glyph,
+                                          unsigned glyph_stride,
+                                          hb_position_t *first_advance,
+                                          unsigned advance_stride)
+{
+  font->get_glyph_advances_for_direction (direction, count, first_glyph, glyph_stride, first_advance, advance_stride);
+}
 
 /**
  * hb_font_get_glyph_origin_for_direction:
@@ -997,6 +1185,7 @@
  *
  *
  * Since: 0.9.2
+ * Deprecated: 2.0.0
  **/
 void
 hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
@@ -1100,6 +1289,49 @@
  * hb_font_t
  */
 
+DEFINE_NULL_INSTANCE (hb_font_t) =
+{
+  HB_OBJECT_HEADER_STATIC,
+
+  nullptr, /* parent */
+  const_cast<hb_face_t *> (&_hb_Null_hb_face_t),
+
+  1000, /* x_scale */
+  1000, /* y_scale */
+
+  0, /* x_ppem */
+  0, /* y_ppem */
+  0, /* ptem */
+
+  0, /* num_coords */
+  nullptr, /* coords */
+
+  const_cast<hb_font_funcs_t *> (&_hb_Null_hb_font_funcs_t),
+
+  /* Zero for the rest is fine. */
+};
+
+
+static hb_font_t *
+_hb_font_create (hb_face_t *face)
+{
+  hb_font_t *font;
+
+  if (unlikely (!face))
+    face = hb_face_get_empty ();
+  if (!(font = hb_object_create<hb_font_t> ()))
+    return hb_font_get_empty ();
+
+  hb_face_make_immutable (face);
+  font->parent = hb_font_get_empty ();
+  font->face = hb_face_reference (face);
+  font->klass = hb_font_funcs_get_empty ();
+  font->data.init0 (font);
+  font->x_scale = font->y_scale = hb_face_get_upem (face);
+
+  return font;
+}
+
 /**
  * hb_font_create: (Xconstructor)
  * @face: a face.
@@ -1113,19 +1345,10 @@
 hb_font_t *
 hb_font_create (hb_face_t *face)
 {
-  hb_font_t *font;
-
-  if (unlikely (!face))
-    face = hb_face_get_empty ();
-  if (!(font = hb_object_create<hb_font_t> ()))
-    return hb_font_get_empty ();
+  hb_font_t *font = _hb_font_create (face);
 
-  hb_face_make_immutable (face);
-  font->parent = hb_font_get_empty ();
-  font->face = hb_face_reference (face);
-  font->klass = hb_font_funcs_get_empty ();
-
-  font->x_scale = font->y_scale = hb_face_get_upem (face);
+  /* Install our in-house, very lightweight, funcs. */
+  hb_ot_font_set_funcs (font);
 
   return font;
 }
@@ -1146,9 +1369,9 @@
   if (unlikely (!parent))
     parent = hb_font_get_empty ();
 
-  hb_font_t *font = hb_font_create (parent->face);
+  hb_font_t *font = _hb_font_create (parent->face);
 
-  if (unlikely (hb_object_is_inert (font)))
+  if (unlikely (hb_object_is_immutable (font)))
     return font;
 
   font->parent = hb_font_reference (parent);
@@ -1185,38 +1408,9 @@
  * Since: 0.9.2
  **/
 hb_font_t *
-hb_font_get_empty (void)
+hb_font_get_empty ()
 {
-  static const hb_font_t _hb_font_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* immutable */
-
-    nullptr, /* parent */
-    const_cast<hb_face_t *> (&_hb_face_nil),
-
-    1000, /* x_scale */
-    1000, /* y_scale */
-
-    0, /* x_ppem */
-    0, /* y_ppem */
-    0, /* ptem */
-
-    0, /* num_coords */
-    nullptr, /* coords */
-
-    const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
-    nullptr, /* user_data */
-    nullptr, /* destroy */
-
-    {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-    }
-  };
-
-  return const_cast<hb_font_t *> (&_hb_font_nil);
+  return const_cast<hb_font_t *> (&Null(hb_font_t));
 }
 
 /**
@@ -1248,9 +1442,7 @@
 {
   if (!hb_object_destroy (font)) return;
 
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, font);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
+  font->data.fini ();
 
   if (font->destroy)
     font->destroy (font->user_data);
@@ -1317,13 +1509,13 @@
 void
 hb_font_make_immutable (hb_font_t *font)
 {
-  if (unlikely (hb_object_is_inert (font)))
+  if (hb_object_is_immutable (font))
     return;
 
   if (font->parent)
     hb_font_make_immutable (font->parent);
 
-  font->immutable = true;
+  hb_object_make_immutable (font);
 }
 
 /**
@@ -1339,7 +1531,7 @@
 hb_bool_t
 hb_font_is_immutable (hb_font_t *font)
 {
-  return font->immutable;
+  return hb_object_is_immutable (font);
 }
 
 /**
@@ -1355,7 +1547,7 @@
 hb_font_set_parent (hb_font_t *font,
                     hb_font_t *parent)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   if (!parent)
@@ -1397,7 +1589,7 @@
 hb_font_set_face (hb_font_t *font,
                   hb_face_t *face)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   if (unlikely (!face))
@@ -1444,7 +1636,8 @@
                    void              *font_data,
                    hb_destroy_func_t  destroy)
 {
-  if (font->immutable) {
+  if (hb_object_is_immutable (font))
+  {
     if (destroy)
       destroy (font_data);
     return;
@@ -1479,7 +1672,8 @@
                         hb_destroy_func_t  destroy)
 {
   /* Destroy user_data? */
-  if (font->immutable) {
+  if (hb_object_is_immutable (font))
+  {
     if (destroy)
       destroy (font_data);
     return;
@@ -1508,7 +1702,7 @@
                    int x_scale,
                    int y_scale)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   font->x_scale = x_scale;
@@ -1549,7 +1743,7 @@
                   unsigned int x_ppem,
                   unsigned int y_ppem)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   font->x_ppem = x_ppem;
@@ -1578,16 +1772,18 @@
 /**
  * hb_font_set_ptem:
  * @font: a font.
- * @ptem:
+ * @ptem: font size in points.
  *
- * Sets "point size" of the font.
+ * Sets "point size" of the font.  Set to 0 to unset.
+ *
+ * There are 72 points in an inch.
  *
  * Since: 1.6.0
  **/
 void
 hb_font_set_ptem (hb_font_t *font, float ptem)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   font->ptem = ptem;
@@ -1634,7 +1830,7 @@
                         const hb_variation_t *variations,
                         unsigned int variations_length)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   if (!variations_length)
@@ -1665,7 +1861,7 @@
                                const float *coords,
                                unsigned int coords_length)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
@@ -1686,7 +1882,7 @@
                                    const int *coords, /* 2.14 normalized */
                                    unsigned int coords_length)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr;
@@ -1718,8 +1914,6 @@
 }
 
 
-#ifndef HB_DISABLE_DEPRECATED
-
 /*
  * Deprecated get_glyph_func():
  */
@@ -1806,9 +2000,9 @@
 /**
  * hb_font_funcs_set_glyph_func:
  * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
+ * @func: (closure user_data) (destroy destroy) (scope notified): callback function.
+ * @user_data: data to pass to @func.
+ * @destroy: function to call when @user_data is not needed anymore.
  *
  * Deprecated.  Use hb_font_funcs_set_nominal_glyph_func() and
  * hb_font_funcs_set_variation_glyph_func() instead.
@@ -1842,5 +2036,3 @@
                                           trampoline,
                                           trampoline_destroy);
 }
-
-#endif /* HB_DISABLE_DEPRECATED */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.h	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.h	Fri Mar 01 16:59:19 2019 -0800
@@ -110,7 +110,7 @@
 /* func types */
 
 typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data,
-                                                       hb_font_extents_t *metrics,
+                                                       hb_font_extents_t *extents,
                                                        void *user_data);
 typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t;
 typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t;
@@ -125,6 +125,14 @@
                                                          hb_codepoint_t *glyph,
                                                          void *user_data);
 
+typedef unsigned int (*hb_font_get_nominal_glyphs_func_t) (hb_font_t *font, void *font_data,
+                                                           unsigned int count,
+                                                           const hb_codepoint_t *first_unicode,
+                                                           unsigned int unicode_stride,
+                                                           hb_codepoint_t *first_glyph,
+                                                           unsigned int glyph_stride,
+                                                           void *user_data);
+
 
 typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data,
                                                            hb_codepoint_t glyph,
@@ -132,6 +140,16 @@
 typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_h_advance_func_t;
 typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t;
 
+typedef void (*hb_font_get_glyph_advances_func_t) (hb_font_t* font, void* font_data,
+                                                   unsigned int count,
+                                                   const hb_codepoint_t *first_glyph,
+                                                   unsigned glyph_stride,
+                                                   hb_position_t *first_advance,
+                                                   unsigned advance_stride,
+                                                   void *user_data);
+typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_h_advances_func_t;
+typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t;
+
 typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
                                                       hb_codepoint_t glyph,
                                                       hb_position_t *x, hb_position_t *y,
@@ -139,12 +157,6 @@
 typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t;
 typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t;
 
-typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
-                                                           hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-                                                           void *user_data);
-typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
-typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
-
 
 typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
                                                        hb_codepoint_t glyph,
@@ -217,6 +229,22 @@
                                       void *user_data, hb_destroy_func_t destroy);
 
 /**
+ * hb_font_funcs_set_nominal_glyphs_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 2.0.0
+ **/
+HB_EXTERN void
+hb_font_funcs_set_nominal_glyphs_func (hb_font_funcs_t *ffuncs,
+                                       hb_font_get_nominal_glyphs_func_t func,
+                                       void *user_data, hb_destroy_func_t destroy);
+
+/**
  * hb_font_funcs_set_variation_glyph_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
@@ -265,6 +293,38 @@
                                         void *user_data, hb_destroy_func_t destroy);
 
 /**
+ * hb_font_funcs_set_glyph_h_advances_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+HB_EXTERN void
+hb_font_funcs_set_glyph_h_advances_func (hb_font_funcs_t *ffuncs,
+                                        hb_font_get_glyph_h_advances_func_t func,
+                                        void *user_data, hb_destroy_func_t destroy);
+
+/**
+ * hb_font_funcs_set_glyph_v_advances_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+HB_EXTERN void
+hb_font_funcs_set_glyph_v_advances_func (hb_font_funcs_t *ffuncs,
+                                        hb_font_get_glyph_v_advances_func_t func,
+                                        void *user_data, hb_destroy_func_t destroy);
+
+/**
  * hb_font_funcs_set_glyph_h_origin_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
@@ -297,38 +357,6 @@
                                        void *user_data, hb_destroy_func_t destroy);
 
 /**
- * hb_font_funcs_set_glyph_h_kerning_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- *
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
-                                        hb_font_get_glyph_h_kerning_func_t func,
-                                        void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_glyph_v_kerning_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- *
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs,
-                                        hb_font_get_glyph_v_kerning_func_t func,
-                                        void *user_data, hb_destroy_func_t destroy);
-
-/**
  * hb_font_funcs_set_glyph_extents_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
@@ -417,6 +445,21 @@
 hb_font_get_glyph_v_advance (hb_font_t *font,
                              hb_codepoint_t glyph);
 
+HB_EXTERN void
+hb_font_get_glyph_h_advances (hb_font_t* font,
+                              unsigned int count,
+                              const hb_codepoint_t *first_glyph,
+                              unsigned glyph_stride,
+                              hb_position_t *first_advance,
+                              unsigned advance_stride);
+HB_EXTERN void
+hb_font_get_glyph_v_advances (hb_font_t* font,
+                              unsigned int count,
+                              const hb_codepoint_t *first_glyph,
+                              unsigned glyph_stride,
+                              hb_position_t *first_advance,
+                              unsigned advance_stride);
+
 HB_EXTERN hb_bool_t
 hb_font_get_glyph_h_origin (hb_font_t *font,
                             hb_codepoint_t glyph,
@@ -426,13 +469,6 @@
                             hb_codepoint_t glyph,
                             hb_position_t *x, hb_position_t *y);
 
-HB_EXTERN hb_position_t
-hb_font_get_glyph_h_kerning (hb_font_t *font,
-                             hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
-HB_EXTERN hb_position_t
-hb_font_get_glyph_v_kerning (hb_font_t *font,
-                             hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
-
 HB_EXTERN hb_bool_t
 hb_font_get_glyph_extents (hb_font_t *font,
                            hb_codepoint_t glyph,
@@ -472,6 +508,14 @@
                                          hb_direction_t direction,
                                          hb_position_t *x, hb_position_t *y);
 HB_EXTERN void
+hb_font_get_glyph_advances_for_direction (hb_font_t* font,
+                                          hb_direction_t direction,
+                                          unsigned int count,
+                                          const hb_codepoint_t *first_glyph,
+                                          unsigned glyph_stride,
+                                          hb_position_t *first_advance,
+                                          unsigned advance_stride);
+HB_EXTERN void
 hb_font_get_glyph_origin_for_direction (hb_font_t *font,
                                         hb_codepoint_t glyph,
                                         hb_direction_t direction,
@@ -487,12 +531,6 @@
                                              hb_direction_t direction,
                                              hb_position_t *x, hb_position_t *y);
 
-HB_EXTERN void
-hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
-                                         hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-                                         hb_direction_t direction,
-                                         hb_position_t *x, hb_position_t *y);
-
 HB_EXTERN hb_bool_t
 hb_font_get_glyph_extents_for_origin (hb_font_t *font,
                                       hb_codepoint_t glyph,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,617 @@
+/*
+ * Copyright © 2009  Red Hat, Inc.
+ * Copyright © 2011  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_FONT_HH
+#define HB_FONT_HH
+
+#include "hb.hh"
+
+#include "hb-face.hh"
+#include "hb-shaper.hh"
+
+
+/*
+ * hb_font_funcs_t
+ */
+
+#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
+  HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
+  HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
+  HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
+  HB_FONT_FUNC_IMPLEMENT (nominal_glyphs) \
+  HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_h_advances) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_name) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
+  /* ^--- Add new callbacks here */
+
+struct hb_font_funcs_t
+{
+  hb_object_header_t header;
+
+  struct {
+#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
+    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+  } user_data;
+
+  struct {
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
+    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+  } destroy;
+
+  /* Don't access these directly.  Call font->get_*() instead. */
+  union get_t {
+    struct get_funcs_t {
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
+      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+    } f;
+    void (*array[0
+#define HB_FONT_FUNC_IMPLEMENT(name) +1
+      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+                ]) ();
+  } get;
+};
+DECLARE_NULL_INSTANCE (hb_font_funcs_t);
+
+
+/*
+ * hb_font_t
+ */
+
+#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, font);
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+
+struct hb_font_t
+{
+  hb_object_header_t header;
+
+  hb_font_t *parent;
+  hb_face_t *face;
+
+  int x_scale;
+  int y_scale;
+
+  unsigned int x_ppem;
+  unsigned int y_ppem;
+
+  float ptem;
+
+  /* Font variation coordinates. */
+  unsigned int num_coords;
+  int *coords;
+
+  hb_font_funcs_t   *klass;
+  void              *user_data;
+  hb_destroy_func_t  destroy;
+
+  hb_shaper_object_dataset_t<hb_font_t> data; /* Various shaper data. */
+
+
+  /* Convert from font-space to user-space */
+  int dir_scale (hb_direction_t direction)
+  { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
+  hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
+  hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
+  hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
+  hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
+  float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
+  float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
+  hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
+  { return em_scale (v, dir_scale (direction)); }
+
+  /* Convert from parent-font user-space to our user-space */
+  hb_position_t parent_scale_x_distance (hb_position_t v)
+  {
+    if (unlikely (parent && parent->x_scale != x_scale))
+      return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
+    return v;
+  }
+  hb_position_t parent_scale_y_distance (hb_position_t v)
+  {
+    if (unlikely (parent && parent->y_scale != y_scale))
+      return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
+    return v;
+  }
+  hb_position_t parent_scale_x_position (hb_position_t v)
+  { return parent_scale_x_distance (v); }
+  hb_position_t parent_scale_y_position (hb_position_t v)
+  { return parent_scale_y_distance (v); }
+
+  void parent_scale_distance (hb_position_t *x, hb_position_t *y)
+  {
+    *x = parent_scale_x_distance (*x);
+    *y = parent_scale_y_distance (*y);
+  }
+  void parent_scale_position (hb_position_t *x, hb_position_t *y)
+  {
+    *x = parent_scale_x_position (*x);
+    *y = parent_scale_y_position (*y);
+  }
+
+
+  /* Public getters */
+
+  HB_INTERNAL bool has_func (unsigned int i);
+  HB_INTERNAL bool has_func_set (unsigned int i);
+
+  /* has_* ... */
+#define HB_FONT_FUNC_IMPLEMENT(name) \
+  bool \
+  has_##name##_func () \
+  { \
+    hb_font_funcs_t *funcs = this->klass; \
+    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
+    return has_func (i); \
+  } \
+  bool \
+  has_##name##_func_set () \
+  { \
+    hb_font_funcs_t *funcs = this->klass; \
+    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
+    return has_func_set (i); \
+  }
+  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+
+  hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
+  {
+    memset (extents, 0, sizeof (*extents));
+    return klass->get.f.font_h_extents (this, user_data,
+                                        extents,
+                                        klass->user_data.font_h_extents);
+  }
+  hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
+  {
+    memset (extents, 0, sizeof (*extents));
+    return klass->get.f.font_v_extents (this, user_data,
+                                        extents,
+                                        klass->user_data.font_v_extents);
+  }
+
+  bool has_glyph (hb_codepoint_t unicode)
+  {
+    hb_codepoint_t glyph;
+    return get_nominal_glyph (unicode, &glyph);
+  }
+
+  hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
+                                      hb_codepoint_t *glyph)
+  {
+    *glyph = 0;
+    return klass->get.f.nominal_glyph (this, user_data,
+                                       unicode, glyph,
+                                       klass->user_data.nominal_glyph);
+  }
+  unsigned int get_nominal_glyphs (unsigned int count,
+                                   const hb_codepoint_t *first_unicode,
+                                   unsigned int unicode_stride,
+                                   hb_codepoint_t *first_glyph,
+                                   unsigned int glyph_stride)
+  {
+    return klass->get.f.nominal_glyphs (this, user_data,
+                                        count,
+                                        first_unicode, unicode_stride,
+                                        first_glyph, glyph_stride,
+                                        klass->user_data.nominal_glyphs);
+  }
+
+  hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+                                 hb_codepoint_t *glyph)
+  {
+    *glyph = 0;
+    return klass->get.f.variation_glyph (this, user_data,
+                                         unicode, variation_selector, glyph,
+                                         klass->user_data.variation_glyph);
+  }
+
+  hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
+  {
+    return klass->get.f.glyph_h_advance (this, user_data,
+                                         glyph,
+                                         klass->user_data.glyph_h_advance);
+  }
+
+  hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
+  {
+    return klass->get.f.glyph_v_advance (this, user_data,
+                                         glyph,
+                                         klass->user_data.glyph_v_advance);
+  }
+
+  void get_glyph_h_advances (unsigned int count,
+                             const hb_codepoint_t *first_glyph,
+                             unsigned int glyph_stride,
+                             hb_position_t *first_advance,
+                             unsigned int advance_stride)
+  {
+    return klass->get.f.glyph_h_advances (this, user_data,
+                                          count,
+                                          first_glyph, glyph_stride,
+                                          first_advance, advance_stride,
+                                          klass->user_data.glyph_h_advances);
+  }
+
+  void get_glyph_v_advances (unsigned int count,
+                             const hb_codepoint_t *first_glyph,
+                             unsigned int glyph_stride,
+                             hb_position_t *first_advance,
+                             unsigned int advance_stride)
+  {
+    return klass->get.f.glyph_v_advances (this, user_data,
+                                          count,
+                                          first_glyph, glyph_stride,
+                                          first_advance, advance_stride,
+                                          klass->user_data.glyph_v_advances);
+  }
+
+  hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
+                                       hb_position_t *x, hb_position_t *y)
+  {
+    *x = *y = 0;
+    return klass->get.f.glyph_h_origin (this, user_data,
+                                        glyph, x, y,
+                                        klass->user_data.glyph_h_origin);
+  }
+
+  hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
+                                hb_position_t *x, hb_position_t *y)
+  {
+    *x = *y = 0;
+    return klass->get.f.glyph_v_origin (this, user_data,
+                                        glyph, x, y,
+                                        klass->user_data.glyph_v_origin);
+  }
+
+  hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
+                                     hb_codepoint_t right_glyph)
+  {
+    return klass->get.f.glyph_h_kerning (this, user_data,
+                                         left_glyph, right_glyph,
+                                         klass->user_data.glyph_h_kerning);
+  }
+
+  hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph,
+                                     hb_codepoint_t bottom_glyph)
+  {
+    return klass->get.f.glyph_v_kerning (this, user_data,
+                                         top_glyph, bottom_glyph,
+                                         klass->user_data.glyph_v_kerning);
+  }
+
+  hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
+                                      hb_glyph_extents_t *extents)
+  {
+    memset (extents, 0, sizeof (*extents));
+    return klass->get.f.glyph_extents (this, user_data,
+                                       glyph,
+                                       extents,
+                                       klass->user_data.glyph_extents);
+  }
+
+  hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
+                                            hb_position_t *x, hb_position_t *y)
+  {
+    *x = *y = 0;
+    return klass->get.f.glyph_contour_point (this, user_data,
+                                             glyph, point_index,
+                                             x, y,
+                                             klass->user_data.glyph_contour_point);
+  }
+
+  hb_bool_t get_glyph_name (hb_codepoint_t glyph,
+                            char *name, unsigned int size)
+  {
+    if (size) *name = '\0';
+    return klass->get.f.glyph_name (this, user_data,
+                                    glyph,
+                                    name, size,
+                                    klass->user_data.glyph_name);
+  }
+
+  hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
+                                 hb_codepoint_t *glyph)
+  {
+    *glyph = 0;
+    if (len == -1) len = strlen (name);
+    return klass->get.f.glyph_from_name (this, user_data,
+                                         name, len,
+                                         glyph,
+                                         klass->user_data.glyph_from_name);
+  }
+
+
+  /* A bit higher-level, and with fallback */
+
+  void get_h_extents_with_fallback (hb_font_extents_t *extents)
+  {
+    if (!get_font_h_extents (extents))
+    {
+      extents->ascender = y_scale * .8;
+      extents->descender = extents->ascender - y_scale;
+      extents->line_gap = 0;
+    }
+  }
+  void get_v_extents_with_fallback (hb_font_extents_t *extents)
+  {
+    if (!get_font_v_extents (extents))
+    {
+      extents->ascender = x_scale / 2;
+      extents->descender = extents->ascender - x_scale;
+      extents->line_gap = 0;
+    }
+  }
+
+  void get_extents_for_direction (hb_direction_t direction,
+                                  hb_font_extents_t *extents)
+  {
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+      get_h_extents_with_fallback (extents);
+    else
+      get_v_extents_with_fallback (extents);
+  }
+
+  void get_glyph_advance_for_direction (hb_codepoint_t glyph,
+                                        hb_direction_t direction,
+                                        hb_position_t *x, hb_position_t *y)
+  {
+    *x = *y = 0;
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+      *x = get_glyph_h_advance (glyph);
+    else
+      *y = get_glyph_v_advance (glyph);
+  }
+  void get_glyph_advances_for_direction (hb_direction_t direction,
+                                         unsigned int count,
+                                         const hb_codepoint_t *first_glyph,
+                                         unsigned glyph_stride,
+                                         hb_position_t *first_advance,
+                                         unsigned advance_stride)
+  {
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+      get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+    else
+      get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+  }
+
+  void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
+                                      hb_position_t *x, hb_position_t *y)
+  {
+    *x = get_glyph_h_advance (glyph) / 2;
+
+    /* TODO cache this somehow?! */
+    hb_font_extents_t extents;
+    get_h_extents_with_fallback (&extents);
+    *y = extents.ascender;
+  }
+
+  void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
+                                         hb_position_t *x, hb_position_t *y)
+  {
+    if (!get_glyph_h_origin (glyph, x, y) &&
+         get_glyph_v_origin (glyph, x, y))
+    {
+      hb_position_t dx, dy;
+      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
+      *x -= dx; *y -= dy;
+    }
+  }
+  void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
+                                         hb_position_t *x, hb_position_t *y)
+  {
+    if (!get_glyph_v_origin (glyph, x, y) &&
+         get_glyph_h_origin (glyph, x, y))
+    {
+      hb_position_t dx, dy;
+      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
+      *x += dx; *y += dy;
+    }
+  }
+
+  void get_glyph_origin_for_direction (hb_codepoint_t glyph,
+                                       hb_direction_t direction,
+                                       hb_position_t *x, hb_position_t *y)
+  {
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+      get_glyph_h_origin_with_fallback (glyph, x, y);
+    else
+      get_glyph_v_origin_with_fallback (glyph, x, y);
+  }
+
+  void add_glyph_h_origin (hb_codepoint_t glyph,
+                           hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
+
+    *x += origin_x;
+    *y += origin_y;
+  }
+  void add_glyph_v_origin (hb_codepoint_t glyph,
+                           hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
+
+    *x += origin_x;
+    *y += origin_y;
+  }
+  void add_glyph_origin_for_direction (hb_codepoint_t glyph,
+                                       hb_direction_t direction,
+                                       hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
+
+    *x += origin_x;
+    *y += origin_y;
+  }
+
+  void subtract_glyph_h_origin (hb_codepoint_t glyph,
+                                hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
+
+    *x -= origin_x;
+    *y -= origin_y;
+  }
+  void subtract_glyph_v_origin (hb_codepoint_t glyph,
+                                hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
+
+    *x -= origin_x;
+    *y -= origin_y;
+  }
+  void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
+                                            hb_direction_t direction,
+                                            hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
+
+    *x -= origin_x;
+    *y -= origin_y;
+  }
+
+  void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+                                        hb_direction_t direction,
+                                        hb_position_t *x, hb_position_t *y)
+  {
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
+      *y = 0;
+      *x = get_glyph_h_kerning (first_glyph, second_glyph);
+    } else {
+      *x = 0;
+      *y = get_glyph_v_kerning (first_glyph, second_glyph);
+    }
+  }
+
+  hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
+                                          hb_direction_t direction,
+                                          hb_glyph_extents_t *extents)
+  {
+    hb_bool_t ret = get_glyph_extents (glyph, extents);
+
+    if (ret)
+      subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
+
+    return ret;
+  }
+
+  hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
+                                                hb_direction_t direction,
+                                                hb_position_t *x, hb_position_t *y)
+  {
+    hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
+
+    if (ret)
+      subtract_glyph_origin_for_direction (glyph, direction, x, y);
+
+    return ret;
+  }
+
+  /* Generates gidDDD if glyph has no name. */
+  void
+  glyph_to_string (hb_codepoint_t glyph,
+                   char *s, unsigned int size)
+  {
+    if (get_glyph_name (glyph, s, size)) return;
+
+    if (size && snprintf (s, size, "gid%u", glyph) < 0)
+      *s = '\0';
+  }
+
+  /* Parses gidDDD and uniUUUU strings automatically. */
+  hb_bool_t
+  glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
+                     hb_codepoint_t *glyph)
+  {
+    if (get_glyph_from_name (s, len, glyph)) return true;
+
+    if (len == -1) len = strlen (s);
+
+    /* Straight glyph index. */
+    if (hb_codepoint_parse (s, len, 10, glyph))
+      return true;
+
+    if (len > 3)
+    {
+      /* gidDDD syntax for glyph indices. */
+      if (0 == strncmp (s, "gid", 3) &&
+          hb_codepoint_parse (s + 3, len - 3, 10, glyph))
+        return true;
+
+      /* uniUUUU and other Unicode character indices. */
+      hb_codepoint_t unichar;
+      if (0 == strncmp (s, "uni", 3) &&
+          hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
+          get_nominal_glyph (unichar, glyph))
+        return true;
+    }
+
+    return false;
+  }
+
+  hb_position_t em_scale (int16_t v, int scale)
+  {
+    int upem = face->get_upem ();
+    int64_t scaled = v * (int64_t) scale;
+    scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
+    return (hb_position_t) (scaled / upem);
+  }
+  hb_position_t em_scalef (float v, int scale)
+  { return (hb_position_t) round (v * scale / face->get_upem ()); }
+  float em_fscale (int16_t v, int scale)
+  { return (float) v * scale / face->get_upem (); }
+};
+DECLARE_NULL_INSTANCE (hb_font_t);
+
+
+#endif /* HB_FONT_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ft.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ft.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -27,47 +27,58 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-#include "hb-debug.hh"
+#include "hb.hh"
 
 #include "hb-ft.h"
 
-#include "hb-font-private.hh"
+#include "hb-font.hh"
+#include "hb-machinery.hh"
+#include "hb-cache.hh"
 
 #include FT_ADVANCES_H
 #include FT_MULTIPLE_MASTERS_H
 #include FT_TRUETYPE_TABLES_H
 
 
+/**
+ * SECTION:hb-ft
+ * @title: hb-ft
+ * @short_description: FreeType integration
+ * @include: hb-ft.h
+ *
+ * Functions for using HarfBuzz with the FreeType library to provide face and
+ * font data.
+ **/
+
+
 /* TODO:
  *
  * In general, this file does a fine job of what it's supposed to do.
  * There are, however, things that need more work:
  *
- *   - I remember seeing FT_Get_Advance() without the NO_HINTING flag to be buggy.
- *     Have not investigated.
- *
  *   - FreeType works in 26.6 mode.  Clients can decide to use that mode, and everything
  *     would work fine.  However, we also abuse this API for performing in font-space,
  *     but don't pass the correct flags to FreeType.  We just abuse the no-hinting mode
  *     for that, such that no rounding etc happens.  As such, we don't set ppem, and
  *     pass NO_HINTING as load_flags.  Would be much better to use NO_SCALE, and scale
- *     ourselves, like we do in uniscribe, etc.
+ *     ourselves.
  *
  *   - We don't handle / allow for emboldening / obliqueing.
  *
  *   - In the future, we should add constructors to create fonts in font space?
- *
- *   - FT_Load_Glyph() is extremely costly.  Do something about it?
  */
 
 
 struct hb_ft_font_t
 {
+  mutable hb_mutex_t lock;
   FT_Face ft_face;
   int load_flags;
   bool symbol; /* Whether selected cmap is symbol cmap. */
   bool unref; /* Whether to destroy ft_face when done. */
+
+  mutable hb_atomic_int_t cached_x_scale;
+  mutable hb_advance_cache_t advance_cache;
 };
 
 static hb_ft_font_t *
@@ -78,12 +89,16 @@
   if (unlikely (!ft_font))
     return nullptr;
 
+  ft_font->lock.init ();
   ft_font->ft_face = ft_face;
   ft_font->symbol = symbol;
   ft_font->unref = unref;
 
   ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
 
+  ft_font->cached_x_scale.set (0);
+  ft_font->advance_cache.init ();
+
   return ft_font;
 }
 
@@ -98,9 +113,13 @@
 {
   hb_ft_font_t *ft_font = (hb_ft_font_t *) data;
 
+  ft_font->advance_cache.fini ();
+
   if (ft_font->unref)
     _hb_ft_face_destroy (ft_font->ft_face);
 
+  ft_font->lock.fini ();
+
   free (ft_font);
 }
 
@@ -116,7 +135,7 @@
 void
 hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
@@ -168,6 +187,7 @@
                          void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode);
 
   if (unlikely (!g))
@@ -191,6 +211,32 @@
   return true;
 }
 
+static unsigned int
+hb_ft_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
+                          void *font_data,
+                          unsigned int count,
+                          const hb_codepoint_t *first_unicode,
+                          unsigned int unicode_stride,
+                          hb_codepoint_t *first_glyph,
+                          unsigned int glyph_stride,
+                          void *user_data HB_UNUSED)
+{
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
+  unsigned int done;
+  for (done = 0;
+       done < count && (*first_glyph = FT_Get_Char_Index (ft_font->ft_face, *first_unicode));
+       done++)
+  {
+    first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
+    first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+  }
+  /* We don't need to do ft_font->symbol dance here, since HB calls the singular
+   * nominal_glyph() for what we don't handle here. */
+  return done;
+}
+
+
 static hb_bool_t
 hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
                            void *font_data,
@@ -200,6 +246,7 @@
                            void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
 
   if (unlikely (!g))
@@ -209,22 +256,45 @@
   return true;
 }
 
-static hb_position_t
-hb_ft_get_glyph_h_advance (hb_font_t *font,
-                           void *font_data,
-                           hb_codepoint_t glyph,
-                           void *user_data HB_UNUSED)
+static void
+hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
+                            unsigned count,
+                            const hb_codepoint_t *first_glyph,
+                            unsigned glyph_stride,
+                            hb_position_t *first_advance,
+                            unsigned advance_stride,
+                            void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  FT_Fixed v;
+  hb_lock_t lock (ft_font->lock);
+  FT_Face ft_face = ft_font->ft_face;
+  int load_flags = ft_font->load_flags;
+  int mult = font->x_scale < 0 ? -1 : +1;
 
-  if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags, &v)))
-    return 0;
+  if (font->x_scale != ft_font->cached_x_scale.get ())
+  {
+    ft_font->advance_cache.clear ();
+    ft_font->cached_x_scale.set (font->x_scale);
+  }
 
-  if (font->x_scale < 0)
-    v = -v;
+  for (unsigned int i = 0; i < count; i++)
+  {
+    FT_Fixed v = 0;
+    hb_codepoint_t glyph = *first_glyph;
 
-  return (v + (1<<9)) >> 10;
+    unsigned int cv;
+    if (ft_font->advance_cache.get (glyph, &cv))
+      v = cv;
+    else
+    {
+      FT_Get_Advance (ft_face, glyph, load_flags, &v);
+      ft_font->advance_cache.set (glyph, v);
+    }
+
+    *first_advance = (v * mult + (1<<9)) >> 10;
+    first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
 }
 
 static hb_position_t
@@ -234,6 +304,7 @@
                            void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Fixed v;
 
   if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
@@ -256,6 +327,7 @@
                           void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
 
   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
@@ -274,23 +346,6 @@
   return true;
 }
 
-static hb_position_t
-hb_ft_get_glyph_h_kerning (hb_font_t *font,
-                           void *font_data,
-                           hb_codepoint_t left_glyph,
-                           hb_codepoint_t right_glyph,
-                           void *user_data HB_UNUSED)
-{
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  FT_Vector kerningv;
-
-  FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED;
-  if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv))
-    return 0;
-
-  return kerningv.x;
-}
-
 static hb_bool_t
 hb_ft_get_glyph_extents (hb_font_t *font,
                          void *font_data,
@@ -299,6 +354,7 @@
                          void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
 
   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
@@ -331,6 +387,7 @@
                                void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
 
   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
@@ -356,8 +413,10 @@
                       void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
+  FT_Face ft_face = ft_font->ft_face;
 
-  hb_bool_t ret = !FT_Get_Glyph_Name (ft_font->ft_face, glyph, name, size);
+  hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size);
   if (ret && (size && !*name))
     ret = false;
 
@@ -372,6 +431,7 @@
                            void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
 
   if (len < 0)
@@ -404,10 +464,11 @@
                           void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
-  metrics->ascender = ft_face->size->metrics.ascender;
-  metrics->descender = ft_face->size->metrics.descender;
-  metrics->line_gap = ft_face->size->metrics.height - (ft_face->size->metrics.ascender - ft_face->size->metrics.descender);
+  metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale);
+  metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale);
+  metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender);
   if (font->y_scale < 0)
   {
     metrics->ascender = -metrics->ascender;
@@ -417,41 +478,25 @@
   return true;
 }
 
-static hb_font_funcs_t *static_ft_funcs = nullptr;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_ft_funcs (void)
-{
-retry:
-  hb_font_funcs_t *ft_funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
-  if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, ft_funcs, nullptr))
-    goto retry;
-
-  hb_font_funcs_destroy (ft_funcs);
-}
+#if HB_USE_ATEXIT
+static void free_static_ft_funcs ();
 #endif
 
-static void
-_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
+static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
 {
-retry:
-  hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
-
-  if (unlikely (!funcs))
+  static hb_font_funcs_t *create ()
   {
-    funcs = hb_font_funcs_create ();
+    hb_font_funcs_t *funcs = hb_font_funcs_create ();
 
     hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
     //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr);
+    hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ft_get_nominal_glyphs, nullptr, nullptr);
     hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, nullptr, nullptr);
+    hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr);
     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
     hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, nullptr, nullptr);
     hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr);
     hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr);
     hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
@@ -459,20 +504,35 @@
 
     hb_font_funcs_make_immutable (funcs);
 
-    if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, nullptr, funcs)) {
-      hb_font_funcs_destroy (funcs);
-      goto retry;
-    }
+#if HB_USE_ATEXIT
+    atexit (free_static_ft_funcs);
+#endif
+
+    return funcs;
+  }
+} static_ft_funcs;
 
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_ft_funcs); /* First person registers atexit() callback. */
+#if HB_USE_ATEXIT
+static
+void free_static_ft_funcs ()
+{
+  static_ft_funcs.free_instance ();
+}
 #endif
-  };
 
+static hb_font_funcs_t *
+_hb_ft_get_font_funcs ()
+{
+  return static_ft_funcs.get_unconst ();
+}
+
+static void
+_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
+{
   bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
 
   hb_font_set_funcs (font,
-                     funcs,
+                     _hb_ft_get_font_funcs (),
                      _hb_ft_font_create (ft_face, symbol, unref),
                      _hb_ft_font_destroy);
 }
@@ -497,7 +557,8 @@
     return nullptr;
 
   error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
-  if (error) {
+  if (error)
+  {
     free (buffer);
     return nullptr;
   }
@@ -683,47 +744,47 @@
   return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
 }
 
+#if HB_USE_ATEXIT
+static void free_static_ft_library ();
+#endif
 
-/* Thread-safe, lock-free, FT_Library */
+static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer (FT_Library),
+                                                             hb_ft_library_lazy_loader_t>
+{
+  static FT_Library create ()
+  {
+    FT_Library l;
+    if (FT_Init_FreeType (&l))
+      return nullptr;
 
-static FT_Library ft_library;
+#if HB_USE_ATEXIT
+    atexit (free_static_ft_library);
+#endif
 
-#ifdef HB_USE_ATEXIT
+    return l;
+  }
+  static void destroy (FT_Library l)
+  {
+    FT_Done_FreeType (l);
+  }
+  static FT_Library get_null ()
+  {
+    return nullptr;
+  }
+} static_ft_library;
+
+#if HB_USE_ATEXIT
 static
-void free_ft_library (void)
+void free_static_ft_library ()
 {
-retry:
-  FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library);
-  if (!hb_atomic_ptr_cmpexch (&ft_library, library, nullptr))
-    goto retry;
-
-  FT_Done_FreeType (library);
+  static_ft_library.free_instance ();
 }
 #endif
 
 static FT_Library
-get_ft_library (void)
+get_ft_library ()
 {
-retry:
-  FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library);
-
-  if (unlikely (!library))
-  {
-    /* Not found; allocate one. */
-    if (FT_Init_FreeType (&library))
-      return nullptr;
-
-    if (!hb_atomic_ptr_cmpexch (&ft_library, nullptr, library)) {
-      FT_Done_FreeType (library);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_ft_library); /* First person registers atexit() callback. */
-#endif
-  }
-
-  return library;
+  return static_ft_library.get_unconst ();
 }
 
 static void
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-iter.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,153 @@
+/*
+ * 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_ITER_HH
+#define HB_ITER_HH
+
+#include "hb.hh"
+#include "hb-null.hh"
+
+
+/* Unified iterator object.
+ *
+ * The goal of this template is to make the same iterator interface
+ * available to all types, and make it very easy and compact to use.
+ * hb_iter_tator objects are small, light-weight, objects that can be
+ * copied by value.  If the collection / object being iterated on
+ * is writable, then the iterator returns lvalues, otherwise it
+ * returns rvalues.
+ */
+
+/* Base class for all iterators. */
+template <typename Iter, typename Item = typename Iter::__item_type__>
+struct hb_iter_t
+{
+  typedef Iter iter_t;
+  typedef iter_t const_iter_t;
+  typedef Item item_t;
+  static constexpr unsigned item_size = hb_static_size (Item);
+
+  private:
+  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
+  const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
+        iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
+  public:
+
+  /* Operators. */
+  operator iter_t () { return iter(); }
+  explicit_operator bool () const { return more (); }
+  item_t& operator * () const { return item (); }
+  item_t& operator [] (signed i) const { return item_at ((unsigned) i); }
+  iter_t& operator += (unsigned count) { forward (count); return *thiz(); }
+  iter_t& operator ++ () { next (); return *thiz(); }
+  iter_t& operator -= (unsigned count) { rewind (count); return *thiz(); }
+  iter_t& operator -- () { prev (); return *thiz(); }
+  iter_t operator + (unsigned count) { iter_t c (*thiz()); c += count; return c; }
+  iter_t operator ++ (int) { iter_t c (*thiz()); ++*thiz(); return c; }
+  iter_t operator - (unsigned count) { iter_t c (*thiz()); c -= count; return c; }
+  iter_t operator -- (int) { iter_t c (*thiz()); --*thiz(); return c; }
+
+  /* Methods. */
+  iter_t iter () const { return *thiz(); }
+  const_iter_t const_iter () const { return iter (); }
+  item_t& item () const { return thiz()->__item__ (); }
+  item_t& item_at (unsigned i) const { return thiz()->__item_at__ (i); }
+  bool more () const { return thiz()->__more__ (); }
+  unsigned len () const { return thiz()->__len__ (); }
+  void next () { thiz()->__next__ (); }
+  void forward (unsigned n) { thiz()->__forward__ (n); }
+  void prev () { thiz()->__prev__ (); }
+  void rewind (unsigned n) { thiz()->__rewind__ (n); }
+  bool random_access () const { return thiz()->__random_access__ (); }
+
+  protected:
+  hb_iter_t () {}
+  hb_iter_t (const hb_iter_t &o HB_UNUSED) {}
+  void operator = (const hb_iter_t &o HB_UNUSED) {}
+};
+
+/* Base class for sorted iterators.  Does not enforce anything.
+ * Just for class taxonomy and requirements. */
+template <typename Iter, typename Item = typename Iter::__item_type__>
+struct hb_sorted_iter_t : hb_iter_t<Iter, Item>
+{
+  protected:
+  hb_sorted_iter_t () {}
+  hb_sorted_iter_t (const hb_sorted_iter_t &o) : hb_iter_t<Iter, Item> (o) {}
+  void operator = (const hb_sorted_iter_t &o HB_UNUSED) {}
+};
+
+/* Mixin to fill in what the subclass doesn't provide. */
+template <typename iter_t, typename item_t = typename iter_t::__item_type__>
+struct hb_iter_mixin_t
+{
+  private:
+  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
+  const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
+        iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
+  public:
+
+  /* Access: Implement __item__(), or __item_at__() if random-access. */
+  item_t& __item__ () const { return thiz()->item_at (0); }
+  item_t& __item_at__ (unsigned i) const { return *(thiz() + i); }
+
+  /* Termination: Implement __more__(), or __len__() if random-access. */
+  bool __more__ () const { return thiz()->__len__ (); }
+  unsigned __len__ () const
+  { iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; }; return l; }
+
+  /* Advancing: Implement __next__(), or __forward__() if random-access. */
+  void __next__ () { thiz()->forward (1); }
+  void __forward__ (unsigned n) { while (n--) thiz()->next (); }
+
+  /* Rewinding: Implement __prev__() or __rewind__() if bidirectional. */
+  void __prev__ () { thiz()->rewind (1); }
+  void __rewind__ (unsigned n) { while (n--) thiz()->prev (); }
+
+  /* Random access: Return true if item_at(), len(), forward() are fast. */
+  bool __random_access__ () const { return false; }
+};
+
+
+/* Functions operating on iterators or iteratables. */
+
+template <typename C, typename V> inline void
+hb_fill (const C& c, const V &v)
+{
+  for (typename C::iter_t i (c); i; i++)
+    hb_assign (*i, v);
+}
+
+template <typename S, typename D> inline bool
+hb_copy (hb_iter_t<D> &id, hb_iter_t<S> &is)
+{
+  for (; id && is; ++id, ++is)
+    *id = *is;
+  return !is;
+}
+
+
+#endif /* HB_ITER_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-kern.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,139 @@
+/*
+ * 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_KERN_HH
+#define HB_KERN_HH
+
+#include "hb-open-type.hh"
+#include "hb-aat-layout-common.hh"
+#include "hb-ot-layout-gpos-table.hh"
+
+
+namespace OT {
+
+
+template <typename Driver>
+struct hb_kern_machine_t
+{
+  hb_kern_machine_t (const Driver &driver_,
+                     bool crossStream_ = false) :
+                       driver (driver_),
+                       crossStream (crossStream_) {}
+
+  HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW
+  void kern (hb_font_t   *font,
+             hb_buffer_t *buffer,
+             hb_mask_t    kern_mask,
+             bool         scale = true) const
+  {
+    OT::hb_ot_apply_context_t c (1, font, buffer);
+    c.set_lookup_mask (kern_mask);
+    c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
+    OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
+    skippy_iter.init (&c);
+
+    bool horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction);
+    unsigned int count = buffer->len;
+    hb_glyph_info_t *info = buffer->info;
+    hb_glyph_position_t *pos = buffer->pos;
+    for (unsigned int idx = 0; idx < count;)
+    {
+      if (!(info[idx].mask & kern_mask))
+      {
+        idx++;
+        continue;
+      }
+
+      skippy_iter.reset (idx, 1);
+      if (!skippy_iter.next ())
+      {
+        idx++;
+        continue;
+      }
+
+      unsigned int i = idx;
+      unsigned int j = skippy_iter.idx;
+
+      hb_position_t kern = driver.get_kerning (info[i].codepoint,
+                                               info[j].codepoint);
+
+
+      if (likely (!kern))
+        goto skip;
+
+      if (horizontal)
+      {
+        if (scale)
+          kern = font->em_scale_x (kern);
+        if (crossStream)
+        {
+          pos[j].y_offset = kern;
+          buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+        }
+        else
+        {
+          hb_position_t kern1 = kern >> 1;
+          hb_position_t kern2 = kern - kern1;
+          pos[i].x_advance += kern1;
+          pos[j].x_advance += kern2;
+          pos[j].x_offset += kern2;
+        }
+      }
+      else
+      {
+        if (scale)
+          kern = font->em_scale_y (kern);
+        if (crossStream)
+        {
+          pos[j].x_offset = kern;
+          buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+        }
+        else
+        {
+          hb_position_t kern1 = kern >> 1;
+          hb_position_t kern2 = kern - kern1;
+          pos[i].y_advance += kern1;
+          pos[j].y_advance += kern2;
+          pos[j].y_offset += kern2;
+        }
+      }
+
+      buffer->unsafe_to_break (i, j + 1);
+
+    skip:
+      idx = skippy_iter.idx;
+    }
+  }
+
+  const Driver &driver;
+  bool crossStream;
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_KERN_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-machinery.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,931 @@
+/*
+ * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
+ * Copyright © 2012,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_MACHINERY_HH
+#define HB_MACHINERY_HH
+
+#include "hb.hh"
+#include "hb-blob.hh"
+
+#include "hb-array.hh"
+#include "hb-vector.hh"
+
+
+/*
+ * Casts
+ */
+
+/* Cast to struct T, reference to reference */
+template<typename Type, typename TObject>
+static inline const Type& CastR(const TObject &X)
+{ return reinterpret_cast<const Type&> (X); }
+template<typename Type, typename TObject>
+static inline Type& CastR(TObject &X)
+{ return reinterpret_cast<Type&> (X); }
+
+/* Cast to struct T, pointer to pointer */
+template<typename Type, typename TObject>
+static inline const Type* CastP(const TObject *X)
+{ return reinterpret_cast<const Type*> (X); }
+template<typename Type, typename TObject>
+static inline Type* CastP(TObject *X)
+{ return reinterpret_cast<Type*> (X); }
+
+/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
+ * location pointed to by P plus Ofs bytes. */
+template<typename Type>
+static inline const Type& StructAtOffset(const void *P, unsigned int offset)
+{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
+template<typename Type>
+static inline Type& StructAtOffset(void *P, unsigned int offset)
+{ return * reinterpret_cast<Type*> ((char *) P + offset); }
+template<typename Type>
+static inline const Type& StructAtOffsetUnaligned(const void *P, unsigned int offset)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+  return * reinterpret_cast<Type*> ((char *) P + offset);
+#pragma GCC diagnostic pop
+}
+template<typename Type>
+static inline Type& StructAtOffsetUnaligned(void *P, unsigned int offset)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+  return * reinterpret_cast<Type*> ((char *) P + offset);
+#pragma GCC diagnostic pop
+}
+
+/* StructAfter<T>(X) returns the struct T& that is placed after X.
+ * Works with X of variable size also.  X must implement get_size() */
+template<typename Type, typename TObject>
+static inline const Type& StructAfter(const TObject &X)
+{ return StructAtOffset<Type>(&X, X.get_size()); }
+template<typename Type, typename TObject>
+static inline Type& StructAfter(TObject &X)
+{ return StructAtOffset<Type>(&X, X.get_size()); }
+
+
+/*
+ * Size checking
+ */
+
+/* Check _assertion in a method environment */
+#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
+  void _instance_assertion_on_line_##_line () const \
+  { static_assert ((_assertion), ""); }
+# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
+# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
+
+/* Check that _code compiles in a method environment */
+#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
+  void _compiles_assertion_on_line_##_line () const \
+  { _code; }
+# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
+# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
+
+
+#define DEFINE_SIZE_STATIC(size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)) \
+  unsigned int get_size () const { return (size); } \
+  static constexpr unsigned null_size = (size); \
+  static constexpr unsigned min_size = (size); \
+  static constexpr unsigned static_size = (size)
+
+#define DEFINE_SIZE_UNION(size, _member) \
+  DEFINE_COMPILES_ASSERTION ((void) this->u._member.static_size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof(this->u._member) == (size)) \
+  static constexpr unsigned null_size = (size); \
+  static constexpr unsigned min_size = (size)
+
+#define DEFINE_SIZE_MIN(size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)) \
+  static constexpr unsigned null_size = (size); \
+  static constexpr unsigned min_size = (size)
+
+#define DEFINE_SIZE_UNBOUNDED(size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)) \
+  static constexpr unsigned min_size = (size)
+
+#define DEFINE_SIZE_ARRAY(size, array) \
+  DEFINE_COMPILES_ASSERTION ((void) (array)[0].static_size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + VAR * sizeof ((array)[0])) \
+  static constexpr unsigned null_size = (size); \
+  static constexpr unsigned min_size = (size)
+
+#define DEFINE_SIZE_ARRAY_SIZED(size, array) \
+  unsigned int get_size () const { return (size - (array).min_size + (array).get_size ()); } \
+  DEFINE_SIZE_ARRAY(size, array)
+
+
+/*
+ * Dispatch
+ */
+
+template <typename Context, typename Return, unsigned int MaxDebugDepth>
+struct hb_dispatch_context_t
+{
+  static constexpr unsigned max_debug_depth = MaxDebugDepth;
+  typedef Return return_t;
+  template <typename T, typename F>
+  bool may_dispatch (const T *obj HB_UNUSED, const F *format HB_UNUSED) { return true; }
+  static return_t no_dispatch_return_value () { return Context::default_return_value (); }
+  static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; }
+};
+
+
+/*
+ * Sanitize
+ *
+ *
+ * === Introduction ===
+ *
+ * The sanitize machinery is at the core of our zero-cost font loading.  We
+ * mmap() font file into memory and create a blob out of it.  Font subtables
+ * are returned as a readonly sub-blob of the main font blob.  These table
+ * blobs are then sanitized before use, to ensure invalid memory access does
+ * not happen.  The toplevel sanitize API use is like, eg. to load the 'head'
+ * table:
+ *
+ *   hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<OT::head> (face);
+ *
+ * The blob then can be converted to a head table struct with:
+ *
+ *   const head *head_table = head_blob->as<head> ();
+ *
+ * What the reference_table does is, to call hb_face_reference_table() to load
+ * the table blob, sanitize it and return either the sanitized blob, or empty
+ * blob if sanitization failed.  The blob->as() function returns the null
+ * object of its template type argument if the blob is empty.  Otherwise, it
+ * just casts the blob contents to the desired type.
+ *
+ * Sanitizing a blob of data with a type T works as follows (with minor
+ * simplification):
+ *
+ *   - Cast blob content to T*, call sanitize() method of it,
+ *   - If sanitize succeeded, return blob.
+ *   - Otherwise, if blob is not writable, try making it writable,
+ *     or copy if cannot be made writable in-place,
+ *   - Call sanitize() again.  Return blob if sanitize succeeded.
+ *   - Return empty blob otherwise.
+ *
+ *
+ * === The sanitize() contract ===
+ *
+ * The sanitize() method of each object type shall return true if it's safe to
+ * call other methods of the object, and false otherwise.
+ *
+ * Note that what sanitize() checks for might align with what the specification
+ * describes as valid table data, but does not have to be.  In particular, we
+ * do NOT want to be pedantic and concern ourselves with validity checks that
+ * are irrelevant to our use of the table.  On the contrary, we want to be
+ * lenient with error handling and accept invalid data to the extent that it
+ * does not impose extra burden on us.
+ *
+ * Based on the sanitize contract, one can see that what we check for depends
+ * on how we use the data in other table methods.  Ie. if other table methods
+ * assume that offsets do NOT point out of the table data block, then that's
+ * something sanitize() must check for (GSUB/GPOS/GDEF/etc work this way).  On
+ * the other hand, if other methods do such checks themselves, then sanitize()
+ * does not have to bother with them (glyf/local work this way).  The choice
+ * depends on the table structure and sanitize() performance.  For example, to
+ * check glyf/loca offsets in sanitize() would cost O(num-glyphs).  We try hard
+ * to avoid such costs during font loading.  By postponing such checks to the
+ * actual glyph loading, we reduce the sanitize cost to O(1) and total runtime
+ * cost to O(used-glyphs).  As such, this is preferred.
+ *
+ * The same argument can be made re GSUB/GPOS/GDEF, but there, the table
+ * structure is so complicated that by checking all offsets at sanitize() time,
+ * we make the code much simpler in other methods, as offsets and referenced
+ * objects do not need to be validated at each use site.
+ */
+
+/* This limits sanitizing time on really broken fonts. */
+#ifndef HB_SANITIZE_MAX_EDITS
+#define HB_SANITIZE_MAX_EDITS 32
+#endif
+#ifndef HB_SANITIZE_MAX_OPS_FACTOR
+#define HB_SANITIZE_MAX_OPS_FACTOR 8
+#endif
+#ifndef HB_SANITIZE_MAX_OPS_MIN
+#define HB_SANITIZE_MAX_OPS_MIN 16384
+#endif
+#ifndef HB_SANITIZE_MAX_OPS_MAX
+#define HB_SANITIZE_MAX_OPS_MAX 0x3FFFFFFF
+#endif
+
+struct hb_sanitize_context_t :
+       hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
+{
+  hb_sanitize_context_t () :
+        debug_depth (0),
+        start (nullptr), end (nullptr),
+        max_ops (0),
+        writable (false), edit_count (0),
+        blob (nullptr),
+        num_glyphs (65536),
+        num_glyphs_set (false) {}
+
+  const char *get_name () { return "SANITIZE"; }
+  template <typename T, typename F>
+  bool may_dispatch (const T *obj HB_UNUSED, const F *format)
+  { return format->sanitize (this); }
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.sanitize (this); }
+  static return_t default_return_value () { return true; }
+  static return_t no_dispatch_return_value () { return false; }
+  bool stop_sublookup_iteration (const return_t r) const { return !r; }
+
+  void init (hb_blob_t *b)
+  {
+    this->blob = hb_blob_reference (b);
+    this->writable = false;
+  }
+
+  void set_num_glyphs (unsigned int num_glyphs_)
+  {
+    num_glyphs = num_glyphs_;
+    num_glyphs_set = true;
+  }
+  unsigned int get_num_glyphs () { return num_glyphs; }
+
+  void set_max_ops (int max_ops_) { max_ops = max_ops_; }
+
+  template <typename T>
+  void set_object (const T *obj)
+  {
+    reset_object ();
+
+    if (!obj) return;
+
+    const char *obj_start = (const char *) obj;
+    if (unlikely (obj_start < this->start || this->end <= obj_start))
+      this->start = this->end = nullptr;
+    else
+    {
+      this->start = obj_start;
+      this->end   = obj_start + MIN<uintptr_t> (this->end - obj_start, obj->get_size ());
+    }
+  }
+
+  void reset_object ()
+  {
+    this->start = this->blob->data;
+    this->end = this->start + this->blob->length;
+    assert (this->start <= this->end); /* Must not overflow. */
+  }
+
+  void start_processing ()
+  {
+    reset_object ();
+    this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
+                         (unsigned) HB_SANITIZE_MAX_OPS_MIN);
+    this->edit_count = 0;
+    this->debug_depth = 0;
+
+    DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
+                     "start [%p..%p] (%lu bytes)",
+                     this->start, this->end,
+                     (unsigned long) (this->end - this->start));
+  }
+
+  void end_processing ()
+  {
+    DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
+                     "end [%p..%p] %u edit requests",
+                     this->start, this->end, this->edit_count);
+
+    hb_blob_destroy (this->blob);
+    this->blob = nullptr;
+    this->start = this->end = nullptr;
+  }
+
+  bool check_range (const void *base,
+                           unsigned int len) const
+  {
+    const char *p = (const char *) base;
+    bool ok = this->start <= p &&
+              p <= this->end &&
+              (unsigned int) (this->end - p) >= len &&
+              this->max_ops-- > 0;
+
+    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+       "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
+       p, p + len, len,
+       this->start, this->end,
+       ok ? "OK" : "OUT-OF-RANGE");
+
+    return likely (ok);
+  }
+
+  template <typename T>
+  bool check_range (const T *base,
+                           unsigned int a,
+                           unsigned int b) const
+  {
+    return !hb_unsigned_mul_overflows (a, b) &&
+           this->check_range (base, a * b);
+  }
+
+  template <typename T>
+  bool check_range (const T *base,
+                           unsigned int a,
+                           unsigned int b,
+                           unsigned int c) const
+  {
+    return !hb_unsigned_mul_overflows (a, b) &&
+           this->check_range (base, a * b, c);
+  }
+
+  template <typename T>
+  bool check_array (const T *base, unsigned int len) const
+  {
+    return this->check_range (base, len, hb_static_size (T));
+  }
+
+  template <typename T>
+  bool check_array (const T *base,
+                    unsigned int a,
+                    unsigned int b) const
+  {
+    return this->check_range (base, a, b, hb_static_size (T));
+  }
+
+  template <typename Type>
+  bool check_struct (const Type *obj) const
+  { return likely (this->check_range (obj, obj->min_size)); }
+
+  bool may_edit (const void *base, unsigned int len)
+  {
+    if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
+      return false;
+
+    const char *p = (const char *) base;
+    this->edit_count++;
+
+    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+       "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
+       this->edit_count,
+       p, p + len, len,
+       this->start, this->end,
+       this->writable ? "GRANTED" : "DENIED");
+
+    return this->writable;
+  }
+
+  template <typename Type, typename ValueType>
+  bool try_set (const Type *obj, const ValueType &v)
+  {
+    if (this->may_edit (obj, hb_static_size (Type)))
+    {
+      hb_assign (* const_cast<Type *> (obj), v);
+      return true;
+    }
+    return false;
+  }
+
+  template <typename Type>
+  hb_blob_t *sanitize_blob (hb_blob_t *blob)
+  {
+    bool sane;
+
+    init (blob);
+
+  retry:
+    DEBUG_MSG_FUNC (SANITIZE, start, "start");
+
+    start_processing ();
+
+    if (unlikely (!start))
+    {
+      end_processing ();
+      return blob;
+    }
+
+    Type *t = CastP<Type> (const_cast<char *> (start));
+
+    sane = t->sanitize (this);
+    if (sane)
+    {
+      if (edit_count)
+      {
+        DEBUG_MSG_FUNC (SANITIZE, start, "passed first round with %d edits; going for second round", edit_count);
+
+        /* sanitize again to ensure no toe-stepping */
+        edit_count = 0;
+        sane = t->sanitize (this);
+        if (edit_count) {
+          DEBUG_MSG_FUNC (SANITIZE, start, "requested %d edits in second round; FAILLING", edit_count);
+          sane = false;
+        }
+      }
+    }
+    else
+    {
+      if (edit_count && !writable) {
+        start = hb_blob_get_data_writable (blob, nullptr);
+        end = start + blob->length;
+
+        if (start)
+        {
+          writable = true;
+          /* ok, we made it writable by relocating.  try again */
+          DEBUG_MSG_FUNC (SANITIZE, start, "retry");
+          goto retry;
+        }
+      }
+    }
+
+    end_processing ();
+
+    DEBUG_MSG_FUNC (SANITIZE, start, sane ? "PASSED" : "FAILED");
+    if (sane)
+    {
+      hb_blob_make_immutable (blob);
+      return blob;
+    }
+    else
+    {
+      hb_blob_destroy (blob);
+      return hb_blob_get_empty ();
+    }
+  }
+
+  template <typename Type>
+  hb_blob_t *reference_table (const hb_face_t *face, hb_tag_t tableTag = Type::tableTag)
+  {
+    if (!num_glyphs_set)
+      set_num_glyphs (hb_face_get_glyph_count (face));
+    return sanitize_blob<Type> (hb_face_reference_table (face, tableTag));
+  }
+
+  mutable unsigned int debug_depth;
+  const char *start, *end;
+  mutable int max_ops;
+  private:
+  bool writable;
+  unsigned int edit_count;
+  hb_blob_t *blob;
+  unsigned int num_glyphs;
+  bool  num_glyphs_set;
+};
+
+struct hb_sanitize_with_object_t
+{
+  template <typename T>
+  hb_sanitize_with_object_t (hb_sanitize_context_t *c,
+                                    const T& obj) : c (c)
+  { c->set_object (obj); }
+  ~hb_sanitize_with_object_t ()
+  { c->reset_object (); }
+
+  private:
+  hb_sanitize_context_t *c;
+};
+
+
+/*
+ * Serialize
+ */
+
+struct hb_serialize_context_t
+{
+  hb_serialize_context_t (void *start_, unsigned int size)
+  {
+    this->start = (char *) start_;
+    this->end = this->start + size;
+    reset ();
+  }
+
+  bool in_error () const { return !this->successful; }
+
+  void reset ()
+  {
+    this->successful = true;
+    this->head = this->start;
+    this->debug_depth = 0;
+  }
+
+  bool propagate_error (bool e)
+  { return this->successful = this->successful && e; }
+  template <typename T> bool propagate_error (const T &obj)
+  { return this->successful = this->successful && !obj.in_error (); }
+  template <typename T> bool propagate_error (const T *obj)
+  { return this->successful = this->successful && !obj->in_error (); }
+  template <typename T1, typename T2> bool propagate_error (T1 &o1, T2 &o2)
+  { return propagate_error (o1) && propagate_error (o2); }
+  template <typename T1, typename T2> bool propagate_error (T1 *o1, T2 *o2)
+  { return propagate_error (o1) && propagate_error (o2); }
+  template <typename T1, typename T2, typename T3>
+  bool propagate_error (T1 &o1, T2 &o2, T3 &o3)
+  { return propagate_error (o1) && propagate_error (o2, o3); }
+  template <typename T1, typename T2, typename T3>
+  bool propagate_error (T1 *o1, T2 *o2, T3 *o3)
+  { return propagate_error (o1) && propagate_error (o2, o3); }
+
+  /* To be called around main operation. */
+  template <typename Type>
+  Type *start_serialize ()
+  {
+    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
+                     "start [%p..%p] (%lu bytes)",
+                     this->start, this->end,
+                     (unsigned long) (this->end - this->start));
+
+    return start_embed<Type> ();
+  }
+  void end_serialize ()
+  {
+    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
+                     "end [%p..%p] serialized %d bytes; %s",
+                     this->start, this->end,
+                     (int) (this->head - this->start),
+                     this->successful ? "successful" : "UNSUCCESSFUL");
+  }
+
+  unsigned int length () const { return this->head - this->start; }
+
+  void align (unsigned int alignment)
+  {
+    unsigned int l = length () % alignment;
+    if (l)
+      allocate_size<void> (alignment - l);
+  }
+
+  template <typename Type>
+  Type *start_embed (const Type *_ HB_UNUSED = nullptr) const
+  {
+    Type *ret = reinterpret_cast<Type *> (this->head);
+    return ret;
+  }
+
+  template <typename Type>
+  Type *allocate_size (unsigned int size)
+  {
+    if (unlikely (!this->successful || this->end - this->head < ptrdiff_t (size))) {
+      this->successful = false;
+      return nullptr;
+    }
+    memset (this->head, 0, size);
+    char *ret = this->head;
+    this->head += size;
+    return reinterpret_cast<Type *> (ret);
+  }
+
+  template <typename Type>
+  Type *allocate_min ()
+  {
+    return this->allocate_size<Type> (Type::min_size);
+  }
+
+  template <typename Type>
+  Type *embed (const Type &obj)
+  {
+    unsigned int size = obj.get_size ();
+    Type *ret = this->allocate_size<Type> (size);
+    if (unlikely (!ret)) return nullptr;
+    memcpy (ret, &obj, size);
+    return ret;
+  }
+  template <typename Type>
+  hb_serialize_context_t &operator << (const Type &obj) { embed (obj); return *this; }
+
+  template <typename Type>
+  Type *extend_size (Type &obj, unsigned int size)
+  {
+    assert (this->start <= (char *) &obj);
+    assert ((char *) &obj <= this->head);
+    assert ((char *) &obj + size >= this->head);
+    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
+    return reinterpret_cast<Type *> (&obj);
+  }
+
+  template <typename Type>
+  Type *extend_min (Type &obj) { return extend_size (obj, obj.min_size); }
+
+  template <typename Type>
+  Type *extend (Type &obj) { return extend_size (obj, obj.get_size ()); }
+
+  /* Output routines. */
+  template <typename Type>
+  Type *copy () const
+  {
+    assert (this->successful);
+    unsigned int len = this->head - this->start;
+    void *p = malloc (len);
+    if (p)
+      memcpy (p, this->start, len);
+    return reinterpret_cast<Type *> (p);
+  }
+  hb_bytes_t copy_bytes () const
+  {
+    assert (this->successful);
+    unsigned int len = this->head - this->start;
+    void *p = malloc (len);
+    if (p)
+      memcpy (p, this->start, len);
+    else
+      return hb_bytes_t ();
+    return hb_bytes_t ((char *) p, len);
+  }
+  hb_blob_t *copy_blob () const
+  {
+    assert (this->successful);
+    return hb_blob_create (this->start,
+                           this->head - this->start,
+                           HB_MEMORY_MODE_DUPLICATE,
+                           nullptr, nullptr);
+  }
+
+  public:
+  unsigned int debug_depth;
+  char *start, *end, *head;
+  bool successful;
+};
+
+
+
+/*
+ * Big-endian integers.
+ */
+
+template <typename Type, int Bytes> struct BEInt;
+
+template <typename Type>
+struct BEInt<Type, 1>
+{
+  public:
+  void set (Type V)      { v = V; }
+  operator Type () const { return v; }
+  private: uint8_t v;
+};
+template <typename Type>
+struct BEInt<Type, 2>
+{
+  public:
+  void set (Type V)
+  {
+    v[0] = (V >>  8) & 0xFF;
+    v[1] = (V      ) & 0xFF;
+  }
+  operator Type () const
+  {
+#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
+    defined(__BYTE_ORDER) && \
+    (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
+    /* Spoon-feed the compiler a big-endian integer with alignment 1.
+     * https://github.com/harfbuzz/harfbuzz/pull/1398 */
+    struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+    return __builtin_bswap16 (((packed_uint16_t *) this)->v);
+#else /* __BYTE_ORDER == __BIG_ENDIAN */
+    return ((packed_uint16_t *) this)->v;
+#endif
+#endif
+    return (v[0] <<  8)
+         + (v[1]      );
+  }
+  private: uint8_t v[2];
+};
+template <typename Type>
+struct BEInt<Type, 3>
+{
+  public:
+  void set (Type V)
+  {
+    v[0] = (V >> 16) & 0xFF;
+    v[1] = (V >>  8) & 0xFF;
+    v[2] = (V      ) & 0xFF;
+  }
+  operator Type () const
+  {
+    return (v[0] << 16)
+         + (v[1] <<  8)
+         + (v[2]      );
+  }
+  private: uint8_t v[3];
+};
+template <typename Type>
+struct BEInt<Type, 4>
+{
+  public:
+  typedef Type type;
+  void set (Type V)
+  {
+    v[0] = (V >> 24) & 0xFF;
+    v[1] = (V >> 16) & 0xFF;
+    v[2] = (V >>  8) & 0xFF;
+    v[3] = (V      ) & 0xFF;
+  }
+  operator Type () const
+  {
+    return (v[0] << 24)
+         + (v[1] << 16)
+         + (v[2] <<  8)
+         + (v[3]      );
+  }
+  private: uint8_t v[4];
+};
+
+
+/*
+ * Lazy loaders.
+ */
+
+template <typename Data, unsigned int WheresData>
+struct hb_data_wrapper_t
+{
+  static_assert (WheresData > 0, "");
+
+  Data * get_data () const
+  { return *(((Data **) (void *) this) - WheresData); }
+
+  bool is_inert () const { return !get_data (); }
+
+  template <typename Stored, typename Subclass>
+  Stored * call_create () const { return Subclass::create (get_data ()); }
+};
+template <>
+struct hb_data_wrapper_t<void, 0>
+{
+  bool is_inert () const { return false; }
+
+  template <typename Stored, typename Funcs>
+  Stored * call_create () const { return Funcs::create (); }
+};
+
+template <typename T1, typename T2> struct hb_non_void_t { typedef T1 value; };
+template <typename T2> struct hb_non_void_t<void, T2> { typedef T2 value; };
+
+template <typename Returned,
+          typename Subclass = void,
+          typename Data = void,
+          unsigned int WheresData = 0,
+          typename Stored = Returned>
+struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
+{
+  typedef typename hb_non_void_t<Subclass,
+                                 hb_lazy_loader_t<Returned,Subclass,Data,WheresData,Stored>
+                                >::value Funcs;
+
+  void init0 () {} /* Init, when memory is already set to 0. No-op for us. */
+  void init ()  { instance.set_relaxed (nullptr); }
+  void fini ()  { do_destroy (instance.get ()); }
+
+  void free_instance ()
+  {
+  retry:
+    Stored *p = instance.get ();
+    if (unlikely (p && !cmpexch (p, nullptr)))
+      goto retry;
+    do_destroy (p);
+  }
+
+  static void do_destroy (Stored *p)
+  {
+    if (p && p != const_cast<Stored *> (Funcs::get_null ()))
+      Funcs::destroy (p);
+  }
+
+  const Returned * operator -> () const { return get (); }
+  const Returned & operator * () const  { return *get (); }
+  explicit_operator bool () const
+  { return get_stored () != Funcs::get_null (); }
+  template <typename C> operator const C * () const { return get (); }
+
+  Stored * get_stored () const
+  {
+  retry:
+    Stored *p = this->instance.get ();
+    if (unlikely (!p))
+    {
+      if (unlikely (this->is_inert ()))
+        return const_cast<Stored *> (Funcs::get_null ());
+
+      p = this->template call_create<Stored, Funcs> ();
+      if (unlikely (!p))
+        p = const_cast<Stored *> (Funcs::get_null ());
+
+      if (unlikely (!cmpexch (nullptr, p)))
+      {
+        do_destroy (p);
+        goto retry;
+      }
+    }
+    return p;
+  }
+  Stored * get_stored_relaxed () const
+  {
+    return this->instance.get_relaxed ();
+  }
+
+  bool cmpexch (Stored *current, Stored *value) const
+  {
+    /* This *must* be called when there are no other threads accessing. */
+    return this->instance.cmpexch (current, value);
+  }
+
+  const Returned * get () const { return Funcs::convert (get_stored ()); }
+  const Returned * get_relaxed () const { return Funcs::convert (get_stored_relaxed ()); }
+  Returned * get_unconst () const { return const_cast<Returned *> (Funcs::convert (get_stored ())); }
+
+  /* To be possibly overloaded by subclasses. */
+  static Returned* convert (Stored *p) { return p; }
+
+  /* By default null/init/fini the object. */
+  static const Stored* get_null () { return &Null(Stored); }
+  static Stored *create (Data *data)
+  {
+    Stored *p = (Stored *) calloc (1, sizeof (Stored));
+    if (likely (p))
+      p->init (data);
+    return p;
+  }
+  static Stored *create ()
+  {
+    Stored *p = (Stored *) calloc (1, sizeof (Stored));
+    if (likely (p))
+      p->init ();
+    return p;
+  }
+  static void destroy (Stored *p)
+  {
+    p->fini ();
+    free (p);
+  }
+
+//  private:
+  /* Must only have one pointer. */
+  hb_atomic_ptr_t<Stored *> instance;
+};
+
+/* Specializations. */
+
+template <typename T, unsigned int WheresFace>
+struct hb_face_lazy_loader_t : hb_lazy_loader_t<T,
+                                                hb_face_lazy_loader_t<T, WheresFace>,
+                                                hb_face_t, WheresFace> {};
+
+template <typename T, unsigned int WheresFace>
+struct hb_table_lazy_loader_t : hb_lazy_loader_t<T,
+                                                 hb_table_lazy_loader_t<T, WheresFace>,
+                                                 hb_face_t, WheresFace,
+                                                 hb_blob_t>
+{
+  static hb_blob_t *create (hb_face_t *face)
+  { return hb_sanitize_context_t ().reference_table<T> (face); }
+  static void destroy (hb_blob_t *p) { hb_blob_destroy (p); }
+
+  static const hb_blob_t *get_null ()
+  { return hb_blob_get_empty (); }
+
+  static const T* convert (const hb_blob_t *blob)
+  { return blob->as<T> (); }
+
+  hb_blob_t* get_blob () const { return this->get_stored (); }
+};
+
+template <typename Subclass>
+struct hb_font_funcs_lazy_loader_t : hb_lazy_loader_t<hb_font_funcs_t, Subclass>
+{
+  static void destroy (hb_font_funcs_t *p)
+  { hb_font_funcs_destroy (p); }
+  static const hb_font_funcs_t *get_null ()
+  { return hb_font_funcs_get_empty (); }
+};
+template <typename Subclass>
+struct hb_unicode_funcs_lazy_loader_t : hb_lazy_loader_t<hb_unicode_funcs_t, Subclass>
+{
+  static void destroy (hb_unicode_funcs_t *p)
+  { hb_unicode_funcs_destroy (p); }
+  static const hb_unicode_funcs_t *get_null ()
+  { return hb_unicode_funcs_get_empty (); }
+};
+
+
+#endif /* HB_MACHINERY_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,255 +0,0 @@
-/*
- * 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_MAP_PRIVATE_HH
-#define HB_MAP_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-
-
-template <typename T>
-inline uint32_t Hash (const T &v)
-{
-  /* Knuth's multiplicative method: */
-  return (uint32_t) v * 2654435761u;
-}
-
-
-/*
- * hb_map_t
- */
-
-struct hb_map_t
-{
-  struct item_t
-  {
-    hb_codepoint_t key;
-    hb_codepoint_t value;
-
-    inline bool is_unused (void) const { return key == INVALID; }
-    inline bool is_tombstone (void) const { return key != INVALID && value == INVALID; }
-  };
-
-  hb_object_header_t header;
-  bool successful; /* Allocations successful */
-  unsigned int population; /* Not including tombstones. */
-  unsigned int occupancy; /* Including tombstones. */
-  unsigned int mask;
-  unsigned int prime;
-  item_t *items;
-
-  inline void init_shallow (void)
-  {
-    successful = true;
-    population = occupancy = 0;
-    mask = 0;
-    prime = 0;
-    items = nullptr;
-  }
-  inline void init (void)
-  {
-    hb_object_init (this);
-    init_shallow ();
-  }
-  inline void fini_shallow (void)
-  {
-    free (items);
-  }
-  inline void fini (void)
-  {
-    hb_object_fini (this);
-    fini_shallow ();
-  }
-
-  inline bool resize (void)
-  {
-    if (unlikely (!successful)) return false;
-
-    unsigned int power = _hb_bit_storage (population * 2 + 8);
-    unsigned int new_size = 1u << power;
-    item_t *new_items = (item_t *) malloc ((size_t) new_size * sizeof (item_t));
-    if (unlikely (!new_items))
-    {
-      successful = false;
-      return false;
-    }
-    memset (new_items, 0xFF, (size_t) new_size * sizeof (item_t));
-
-    unsigned int old_size = mask + 1;
-    item_t *old_items = items;
-
-    /* Switch to new, empty, array. */
-    population = occupancy = 0;
-    mask = new_size - 1;
-    prime = prime_for (power);
-    items = new_items;
-
-    /* Insert back old items. */
-    if (old_items)
-      for (unsigned int i = 0; i < old_size; i++)
-        if (old_items[i].key != INVALID && old_items[i].value != INVALID)
-          set (old_items[i].key, old_items[i].value);
-
-    free (old_items);
-
-    return true;
-  }
-
-  inline void set (hb_codepoint_t key, hb_codepoint_t value)
-  {
-    if (unlikely (!successful)) return;
-    if (unlikely (key == INVALID)) return;
-    if ((occupancy + occupancy / 2) >= mask && !resize ()) return;
-    unsigned int i = bucket_for (key);
-
-    if (value == INVALID && items[i].key != key)
-      return; /* Trying to delete non-existent key. */
-
-    if (!items[i].is_unused ())
-    {
-      occupancy--;
-      if (items[i].is_tombstone ())
-        population--;
-    }
-
-    items[i].key = key;
-    items[i].value = value;
-
-    occupancy++;
-    if (!items[i].is_tombstone ())
-      population++;
-
-  }
-  inline hb_codepoint_t get (hb_codepoint_t key) const
-  {
-    if (unlikely (!items)) return INVALID;
-    unsigned int i = bucket_for (key);
-    return items[i].key == key ? items[i].value : INVALID;
-  }
-
-  inline void del (hb_codepoint_t key)
-  {
-    set (key, INVALID);
-  }
-  inline bool has (hb_codepoint_t key) const
-  {
-    return get (key) != INVALID;
-  }
-
-  inline hb_codepoint_t operator [] (unsigned int key) const
-  { return get (key); }
-
-  static const hb_codepoint_t INVALID = HB_MAP_VALUE_INVALID;
-
-  inline void clear (void)
-  {
-    memset (items, 0xFF, ((size_t) mask + 1) * sizeof (item_t));
-    population = occupancy = 0;
-  }
-
-  inline bool is_empty (void) const
-  {
-    return population != 0;
-  }
-
-  inline unsigned int get_population () const
-  {
-    return population;
-  }
-
-  protected:
-
-  inline unsigned int bucket_for (hb_codepoint_t key) const
-  {
-    unsigned int i = Hash (key) % prime;
-    unsigned int step = 0;
-    unsigned int tombstone = INVALID;
-    while (!items[i].is_unused ())
-    {
-      if (items[i].key == key)
-        return i;
-      if (tombstone == INVALID && items[i].is_tombstone ())
-        tombstone = i;
-      i = (i + ++step) & mask;
-    }
-    return tombstone == INVALID ? i : tombstone;
-  }
-
-  static inline unsigned int prime_for (unsigned int shift)
-  {
-    /* Following comment and table copied from glib. */
-    /* Each table size has an associated prime modulo (the first prime
-     * lower than the table size) used to find the initial bucket. Probing
-     * then works modulo 2^n. The prime modulo is necessary to get a
-     * good distribution with poor hash functions.
-     */
-    /* Not declaring static to make all kinds of compilers happy... */
-    /*static*/ const unsigned int prime_mod [32] =
-    {
-      1,          /* For 1 << 0 */
-      2,
-      3,
-      7,
-      13,
-      31,
-      61,
-      127,
-      251,
-      509,
-      1021,
-      2039,
-      4093,
-      8191,
-      16381,
-      32749,
-      65521,      /* For 1 << 16 */
-      131071,
-      262139,
-      524287,
-      1048573,
-      2097143,
-      4194301,
-      8388593,
-      16777213,
-      33554393,
-      67108859,
-      134217689,
-      268435399,
-      536870909,
-      1073741789,
-      2147483647  /* For 1 << 31 */
-    };
-
-    if (unlikely (shift >= ARRAY_LENGTH (prime_mod)))
-      return prime_mod[ARRAY_LENGTH (prime_mod) - 1];
-
-    return prime_mod[shift];
-  }
-};
-
-
-#endif /* HB_MAP_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,10 +24,19 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-map-private.hh"
+#include "hb-map.hh"
 
 
-/* Public API */
+/**
+ * SECTION:hb-map
+ * @title: hb-map
+ * @short_description: Object representing integer to integer mapping
+ * @include: hb.h
+ *
+ * Map objects are integer-to-integer hash-maps.  Currently they are
+ * not used in the HarfBuzz public API, but are provided for client's
+ * use if desired.
+ **/
 
 
 /**
@@ -38,7 +47,7 @@
  * Since: 1.7.7
  **/
 hb_map_t *
-hb_map_create (void)
+hb_map_create ()
 {
   hb_map_t *map;
 
@@ -58,7 +67,7 @@
  * Since: 1.7.7
  **/
 hb_map_t *
-hb_map_get_empty (void)
+hb_map_get_empty ()
 {
   return const_cast<hb_map_t *> (&Null(hb_map_t));
 }
@@ -157,8 +166,6 @@
  *
  *
  *
- * Return value:
- *
  * Since: 1.7.7
  **/
 void
@@ -188,7 +195,7 @@
 /**
  * hb_map_del:
  * @map: a map.
- * @codepoint:
+ * @key:
  *
  *
  *
@@ -204,7 +211,7 @@
 /**
  * hb_map_has:
  * @map: a map.
- * @codepoint:
+ * @key:
  *
  *
  *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,252 @@
+/*
+ * 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_MAP_HH
+#define HB_MAP_HH
+
+#include "hb.hh"
+
+
+template <typename T>
+inline uint32_t Hash (const T &v)
+{
+  /* Knuth's multiplicative method: */
+  return (uint32_t) v * 2654435761u;
+}
+
+
+/*
+ * hb_map_t
+ */
+
+struct hb_map_t
+{
+  HB_NO_COPY_ASSIGN (hb_map_t);
+  hb_map_t ()  { init (); }
+  ~hb_map_t () { fini (); }
+
+  struct item_t
+  {
+    hb_codepoint_t key;
+    hb_codepoint_t value;
+
+    bool is_unused () const    { return key == INVALID; }
+    bool is_tombstone () const { return key != INVALID && value == INVALID; }
+  };
+
+  hb_object_header_t header;
+  bool successful; /* Allocations successful */
+  unsigned int population; /* Not including tombstones. */
+  unsigned int occupancy; /* Including tombstones. */
+  unsigned int mask;
+  unsigned int prime;
+  item_t *items;
+
+  void init_shallow ()
+  {
+    successful = true;
+    population = occupancy = 0;
+    mask = 0;
+    prime = 0;
+    items = nullptr;
+  }
+  void init ()
+  {
+    hb_object_init (this);
+    init_shallow ();
+  }
+  void fini_shallow ()
+  {
+    free (items);
+    items = nullptr;
+  }
+  void fini ()
+  {
+    population = occupancy = 0;
+    hb_object_fini (this);
+    fini_shallow ();
+  }
+
+  bool in_error () const { return !successful; }
+
+  bool resize ()
+  {
+    if (unlikely (!successful)) return false;
+
+    unsigned int power = hb_bit_storage (population * 2 + 8);
+    unsigned int new_size = 1u << power;
+    item_t *new_items = (item_t *) malloc ((size_t) new_size * sizeof (item_t));
+    if (unlikely (!new_items))
+    {
+      successful = false;
+      return false;
+    }
+    memset (new_items, 0xFF, (size_t) new_size * sizeof (item_t));
+
+    unsigned int old_size = mask + 1;
+    item_t *old_items = items;
+
+    /* Switch to new, empty, array. */
+    population = occupancy = 0;
+    mask = new_size - 1;
+    prime = prime_for (power);
+    items = new_items;
+
+    /* Insert back old items. */
+    if (old_items)
+      for (unsigned int i = 0; i < old_size; i++)
+        if (old_items[i].key != INVALID && old_items[i].value != INVALID)
+          set (old_items[i].key, old_items[i].value);
+
+    free (old_items);
+
+    return true;
+  }
+
+  void set (hb_codepoint_t key, hb_codepoint_t value)
+  {
+    if (unlikely (!successful)) return;
+    if (unlikely (key == INVALID)) return;
+    if ((occupancy + occupancy / 2) >= mask && !resize ()) return;
+    unsigned int i = bucket_for (key);
+
+    if (value == INVALID && items[i].key != key)
+      return; /* Trying to delete non-existent key. */
+
+    if (!items[i].is_unused ())
+    {
+      occupancy--;
+      if (items[i].is_tombstone ())
+        population--;
+    }
+
+    items[i].key = key;
+    items[i].value = value;
+
+    occupancy++;
+    if (!items[i].is_tombstone ())
+      population++;
+
+  }
+  hb_codepoint_t get (hb_codepoint_t key) const
+  {
+    if (unlikely (!items)) return INVALID;
+    unsigned int i = bucket_for (key);
+    return items[i].key == key ? items[i].value : INVALID;
+  }
+
+  void del (hb_codepoint_t key) { set (key, INVALID); }
+
+  bool has (hb_codepoint_t key) const
+  { return get (key) != INVALID; }
+
+  hb_codepoint_t operator [] (unsigned int key) const
+  { return get (key); }
+
+  static constexpr hb_codepoint_t INVALID = HB_MAP_VALUE_INVALID;
+
+  void clear ()
+  {
+    memset (items, 0xFF, ((size_t) mask + 1) * sizeof (item_t));
+    population = occupancy = 0;
+  }
+
+  bool is_empty () const { return population == 0; }
+
+  unsigned int get_population () const { return population; }
+
+  protected:
+
+  unsigned int bucket_for (hb_codepoint_t key) const
+  {
+    unsigned int i = Hash (key) % prime;
+    unsigned int step = 0;
+    unsigned int tombstone = INVALID;
+    while (!items[i].is_unused ())
+    {
+      if (items[i].key == key)
+        return i;
+      if (tombstone == INVALID && items[i].is_tombstone ())
+        tombstone = i;
+      i = (i + ++step) & mask;
+    }
+    return tombstone == INVALID ? i : tombstone;
+  }
+
+  static unsigned int prime_for (unsigned int shift)
+  {
+    /* Following comment and table copied from glib. */
+    /* Each table size has an associated prime modulo (the first prime
+     * lower than the table size) used to find the initial bucket. Probing
+     * then works modulo 2^n. The prime modulo is necessary to get a
+     * good distribution with poor hash functions.
+     */
+    /* Not declaring static to make all kinds of compilers happy... */
+    /*static*/ const unsigned int prime_mod [32] =
+    {
+      1,          /* For 1 << 0 */
+      2,
+      3,
+      7,
+      13,
+      31,
+      61,
+      127,
+      251,
+      509,
+      1021,
+      2039,
+      4093,
+      8191,
+      16381,
+      32749,
+      65521,      /* For 1 << 16 */
+      131071,
+      262139,
+      524287,
+      1048573,
+      2097143,
+      4194301,
+      8388593,
+      16777213,
+      33554393,
+      67108859,
+      134217689,
+      268435399,
+      536870909,
+      1073741789,
+      2147483647  /* For 1 << 31 */
+    };
+
+    if (unlikely (shift >= ARRAY_LENGTH (prime_mod)))
+      return prime_mod[ARRAY_LENGTH (prime_mod) - 1];
+
+    return prime_mod[shift];
+  }
+};
+
+
+#endif /* HB_MAP_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-mutex-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +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_MUTEX_PRIVATE_HH
-#define HB_MUTEX_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-/* mutex */
-
-/* We need external help for these */
-
-#if defined(HB_MUTEX_IMPL_INIT) \
- && defined(hb_mutex_impl_init) \
- && defined(hb_mutex_impl_lock) \
- && defined(hb_mutex_impl_unlock) \
- && defined(hb_mutex_impl_finish)
-
-/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */
-
-
-#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
-
-#include <windows.h>
-typedef CRITICAL_SECTION hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT      {0}
-#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
-#define hb_mutex_impl_init(M)   InitializeCriticalSectionEx (M, 0, 0)
-#else
-#define hb_mutex_impl_init(M)   InitializeCriticalSection (M)
-#endif
-#define hb_mutex_impl_lock(M)   EnterCriticalSection (M)
-#define hb_mutex_impl_unlock(M) LeaveCriticalSection (M)
-#define hb_mutex_impl_finish(M) DeleteCriticalSection (M)
-
-
-#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
-
-#include <pthread.h>
-typedef pthread_mutex_t hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT      PTHREAD_MUTEX_INITIALIZER
-#define hb_mutex_impl_init(M)   pthread_mutex_init (M, nullptr)
-#define hb_mutex_impl_lock(M)   pthread_mutex_lock (M)
-#define hb_mutex_impl_unlock(M) pthread_mutex_unlock (M)
-#define hb_mutex_impl_finish(M) pthread_mutex_destroy (M)
-
-
-#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
-
-#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
-# include <sched.h>
-# define HB_SCHED_YIELD() sched_yield ()
-#else
-# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
-#endif
-
-/* This actually is not a totally awful implementation. */
-typedef volatile int hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT      0
-#define hb_mutex_impl_init(M)   *(M) = 0
-#define hb_mutex_impl_lock(M)   HB_STMT_START { while (__sync_lock_test_and_set((M), 1)) HB_SCHED_YIELD (); } HB_STMT_END
-#define hb_mutex_impl_unlock(M) __sync_lock_release (M)
-#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
-
-
-#elif !defined(HB_NO_MT)
-
-#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
-# include <sched.h>
-# define HB_SCHED_YIELD() sched_yield ()
-#else
-# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
-#endif
-
-#define HB_MUTEX_INT_NIL 1 /* Warn that fallback implementation is in use. */
-typedef volatile int hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT      0
-#define hb_mutex_impl_init(M)   *(M) = 0
-#define hb_mutex_impl_lock(M)   HB_STMT_START { while (*(M)) HB_SCHED_YIELD (); (*(M))++; } HB_STMT_END
-#define hb_mutex_impl_unlock(M) (*(M))--;
-#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
-
-
-#else /* HB_NO_MT */
-
-typedef int hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT      0
-#define hb_mutex_impl_init(M)   HB_STMT_START {} HB_STMT_END
-#define hb_mutex_impl_lock(M)   HB_STMT_START {} HB_STMT_END
-#define hb_mutex_impl_unlock(M) HB_STMT_START {} HB_STMT_END
-#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
-
-
-#endif
-
-
-#define HB_MUTEX_INIT           {HB_MUTEX_IMPL_INIT}
-
-struct hb_mutex_t
-{
-  /* TODO Add tracing. */
-
-  hb_mutex_impl_t m;
-
-  inline void init   (void) { hb_mutex_impl_init   (&m); }
-  inline void lock   (void) { hb_mutex_impl_lock   (&m); }
-  inline void unlock (void) { hb_mutex_impl_unlock (&m); }
-  inline void fini (void) { hb_mutex_impl_finish (&m); }
-};
-
-
-#endif /* HB_MUTEX_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-mutex.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,149 @@
+/*
+ * 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_MUTEX_HH
+#define HB_MUTEX_HH
+
+#include "hb.hh"
+
+
+/* mutex */
+
+/* We need external help for these */
+
+#if defined(HB_MUTEX_IMPL_INIT) \
+ && defined(hb_mutex_impl_init) \
+ && defined(hb_mutex_impl_lock) \
+ && defined(hb_mutex_impl_unlock) \
+ && defined(hb_mutex_impl_finish)
+
+/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */
+
+
+#elif !defined(HB_NO_MT) && defined(_WIN32)
+
+#include <windows.h>
+typedef CRITICAL_SECTION hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT      {0}
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+#define hb_mutex_impl_init(M)   InitializeCriticalSectionEx (M, 0, 0)
+#else
+#define hb_mutex_impl_init(M)   InitializeCriticalSection (M)
+#endif
+#define hb_mutex_impl_lock(M)   EnterCriticalSection (M)
+#define hb_mutex_impl_unlock(M) LeaveCriticalSection (M)
+#define hb_mutex_impl_finish(M) DeleteCriticalSection (M)
+
+
+#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
+
+#include <pthread.h>
+typedef pthread_mutex_t hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT      PTHREAD_MUTEX_INITIALIZER
+#define hb_mutex_impl_init(M)   pthread_mutex_init (M, nullptr)
+#define hb_mutex_impl_lock(M)   pthread_mutex_lock (M)
+#define hb_mutex_impl_unlock(M) pthread_mutex_unlock (M)
+#define hb_mutex_impl_finish(M) pthread_mutex_destroy (M)
+
+
+#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
+
+#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
+# include <sched.h>
+# define HB_SCHED_YIELD() sched_yield ()
+#else
+# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
+#endif
+
+/* This actually is not a totally awful implementation. */
+typedef volatile int hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT      0
+#define hb_mutex_impl_init(M)   *(M) = 0
+#define hb_mutex_impl_lock(M)   HB_STMT_START { while (__sync_lock_test_and_set((M), 1)) HB_SCHED_YIELD (); } HB_STMT_END
+#define hb_mutex_impl_unlock(M) __sync_lock_release (M)
+#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
+
+
+#elif !defined(HB_NO_MT)
+
+#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
+# include <sched.h>
+# define HB_SCHED_YIELD() sched_yield ()
+#else
+# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
+#endif
+
+#define HB_MUTEX_INT_NIL 1 /* Warn that fallback implementation is in use. */
+typedef volatile int hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT      0
+#define hb_mutex_impl_init(M)   *(M) = 0
+#define hb_mutex_impl_lock(M)   HB_STMT_START { while (*(M)) HB_SCHED_YIELD (); (*(M))++; } HB_STMT_END
+#define hb_mutex_impl_unlock(M) (*(M))--;
+#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
+
+
+#else /* HB_NO_MT */
+
+typedef int hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT      0
+#define hb_mutex_impl_init(M)   HB_STMT_START {} HB_STMT_END
+#define hb_mutex_impl_lock(M)   HB_STMT_START {} HB_STMT_END
+#define hb_mutex_impl_unlock(M) HB_STMT_START {} HB_STMT_END
+#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
+
+
+#endif
+
+
+#define HB_MUTEX_INIT           {HB_MUTEX_IMPL_INIT}
+
+struct hb_mutex_t
+{
+  /* TODO Add tracing. */
+
+  hb_mutex_impl_t m;
+
+  void init   () { hb_mutex_impl_init   (&m); }
+  void lock   () { hb_mutex_impl_lock   (&m); }
+  void unlock () { hb_mutex_impl_unlock (&m); }
+  void fini ()   { hb_mutex_impl_finish (&m); }
+};
+
+struct hb_lock_t
+{
+  hb_lock_t (hb_mutex_t &mutex_) : mutex (mutex_) { mutex.lock (); }
+  ~hb_lock_t () { mutex.unlock (); }
+  private:
+  hb_mutex_t &mutex;
+};
+
+
+#endif /* HB_MUTEX_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-null.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,204 @@
+/*
+ * 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_NULL_HH
+#define HB_NULL_HH
+
+#include "hb.hh"
+
+
+/*
+ * Static pools
+ */
+
+/* Global nul-content Null pool.  Enlarge as necessary. */
+
+#define HB_NULL_POOL_SIZE 9880
+
+/* Use SFINAE to sniff whether T has min_size; in which case return T::null_size,
+ * otherwise return sizeof(T). */
+
+/* The hard way...
+ * https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
+ */
+
+template<bool> struct _hb_bool_type {};
+
+template <typename T, typename B>
+struct _hb_null_size
+{ enum { value = sizeof (T) }; };
+template <typename T>
+struct _hb_null_size<T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
+{ enum { value = T::null_size }; };
+
+template <typename T>
+struct hb_null_size
+{ enum { value = _hb_null_size<T, _hb_bool_type<true> >::value }; };
+#define hb_null_size(T) hb_null_size<T>::value
+
+/* These doesn't belong here, but since is copy/paste from above, put it here. */
+
+/* hb_static_size (T)
+ * Returns T::static_size if T::min_size is defined, or sizeof (T) otherwise. */
+
+template <typename T, typename B>
+struct _hb_static_size
+{ enum { value = sizeof (T) }; };
+template <typename T>
+struct _hb_static_size<T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
+{ enum { value = T::static_size }; };
+
+template <typename T>
+struct hb_static_size
+{ enum { value = _hb_static_size<T, _hb_bool_type<true> >::value }; };
+#define hb_static_size(T) hb_static_size<T>::value
+
+
+/* hb_assign (obj, value)
+ * Calls obj.set (value) if obj.min_size is defined and value has different type
+ * from obj, or obj = v otherwise. */
+
+template <typename T, typename V, typename B>
+struct _hb_assign
+{ static inline void value (T &o, const V v) { o = v; } };
+template <typename T, typename V>
+struct _hb_assign<T, V, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
+{ static inline void value (T &o, const V v) { o.set (v); } };
+template <typename T>
+struct _hb_assign<T, T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
+{ static inline void value (T &o, const T v) { o = v; } };
+
+template <typename T, typename V>
+static inline void hb_assign (T &o, const V v)
+{ _hb_assign<T, V, _hb_bool_type<true> >::value (o, v); }
+
+
+/*
+ * Null()
+ */
+
+extern HB_INTERNAL
+hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
+
+/* Generic nul-content Null objects. */
+template <typename Type>
+static inline Type const & Null () {
+  static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
+  return *reinterpret_cast<Type const *> (_hb_NullPool);
+}
+template <typename QType>
+struct NullHelper
+{
+  typedef typename hb_remove_const (typename hb_remove_reference (QType)) Type;
+  static const Type & get_null () { return Null<Type> (); }
+};
+#define Null(Type) NullHelper<Type>::get_null ()
+
+/* Specializations for arbitrary-content Null objects expressed in bytes. */
+#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
+        } /* Close namespace. */ \
+        extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]; \
+        template <> \
+        /*static*/ inline const Namespace::Type& Null<Namespace::Type> () { \
+          return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
+        } \
+        namespace Namespace { \
+        static_assert (true, "Just so we take semicolon after.")
+#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
+        const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]
+
+/* Specializations for arbitrary-content Null objects expressed as struct initializer. */
+#define DECLARE_NULL_INSTANCE(Type) \
+        extern HB_INTERNAL const Type _hb_Null_##Type; \
+        template <> \
+        /*static*/ inline const Type& Null<Type> () { \
+          return _hb_Null_##Type; \
+        } \
+static_assert (true, "Just so we take semicolon after.")
+#define DEFINE_NULL_INSTANCE(Type) \
+        const Type _hb_Null_##Type
+
+/* Global writable pool.  Enlarge as necessary. */
+
+/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
+ * for correct operation. It only exist to catch and divert program logic bugs instead of
+ * causing bad memory access. So, races there are not actually introducing incorrectness
+ * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
+extern HB_INTERNAL
+/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
+
+/* CRAP pool: Common Region for Access Protection. */
+template <typename Type>
+static inline Type& Crap () {
+  static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
+  Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
+  memcpy (obj, &Null(Type), sizeof (*obj));
+  return *obj;
+}
+template <typename QType>
+struct CrapHelper
+{
+  typedef typename hb_remove_const (typename hb_remove_reference (QType)) Type;
+  static Type & get_crap () { return Crap<Type> (); }
+};
+#define Crap(Type) CrapHelper<Type>::get_crap ()
+
+template <typename Type>
+struct CrapOrNullHelper {
+  static Type & get () { return Crap(Type); }
+};
+template <typename Type>
+struct CrapOrNullHelper<const Type> {
+  static const Type & get () { return Null(Type); }
+};
+#define CrapOrNull(Type) CrapOrNullHelper<Type>::get ()
+
+
+/*
+ * hb_nonnull_ptr_t
+ */
+
+template <typename P>
+struct hb_nonnull_ptr_t
+{
+  typedef typename hb_remove_pointer (P) T;
+
+  hb_nonnull_ptr_t (T *v_ = nullptr) : v (v_) {}
+  T * operator = (T *v_)   { return v = v_; }
+  T * operator -> () const { return get (); }
+  T & operator * () const  { return *get (); }
+  T ** operator & () const { return &v; }
+  /* Only auto-cast to const types. */
+  template <typename C> operator const C * () const { return get (); }
+  operator const char * () const { return (const char *) get (); }
+  T * get () const { return v ? v : const_cast<T *> (&Null(T)); }
+  T * get_raw () const { return v; }
+
+  T *v;
+};
+
+
+#endif /* HB_NULL_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-object-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,221 +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_OBJECT_PRIVATE_HH
-#define HB_OBJECT_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-
-#include "hb-atomic-private.hh"
-#include "hb-mutex-private.hh"
-
-
-/* reference_count */
-
-#define HB_REFERENCE_COUNT_INERT_VALUE 0
-#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
-#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT (HB_REFERENCE_COUNT_INERT_VALUE)}
-
-struct hb_reference_count_t
-{
-  hb_atomic_int_t ref_count;
-
-  inline void init (int v) { ref_count.set_unsafe (v); }
-  inline int get_unsafe (void) const { return ref_count.get_unsafe (); }
-  inline int inc (void) { return ref_count.inc (); }
-  inline int dec (void) { return ref_count.dec (); }
-  inline void fini (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); }
-
-  inline bool is_inert (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INERT_VALUE; }
-  inline bool is_valid (void) const { return ref_count.get_unsafe () > 0; }
-};
-
-
-/* user_data */
-
-struct hb_user_data_array_t
-{
-  struct hb_user_data_item_t {
-    hb_user_data_key_t *key;
-    void *data;
-    hb_destroy_func_t destroy;
-
-    inline bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; }
-    inline bool operator == (hb_user_data_item_t &other) const { return key == other.key; }
-
-    void fini (void) { if (destroy) destroy (data); }
-  };
-
-  hb_mutex_t lock;
-  hb_lockable_set_t<hb_user_data_item_t, hb_mutex_t> items;
-
-  inline void init (void) { lock.init (); items.init (); }
-
-  HB_INTERNAL bool set (hb_user_data_key_t *key,
-                        void *              data,
-                        hb_destroy_func_t   destroy,
-                        hb_bool_t           replace);
-
-  HB_INTERNAL void *get (hb_user_data_key_t *key);
-
-  inline void fini (void) { items.fini (lock); lock.fini (); }
-};
-
-
-/* object_header */
-
-struct hb_object_header_t
-{
-  hb_reference_count_t ref_count;
-  hb_user_data_array_t *user_data;
-
-#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, nullptr}
-
-  private:
-  ASSERT_POD ();
-};
-
-
-/* object */
-
-template <typename Type>
-static inline void hb_object_trace (const Type *obj, const char *function)
-{
-  DEBUG_MSG (OBJECT, (void *) obj,
-             "%s refcount=%d",
-             function,
-             obj ? obj->header.ref_count.get_unsafe () : 0);
-}
-
-template <typename Type>
-static inline Type *hb_object_create (void)
-{
-  Type *obj = (Type *) calloc (1, sizeof (Type));
-
-  if (unlikely (!obj))
-    return obj;
-
-  hb_object_init (obj);
-  hb_object_trace (obj, HB_FUNC);
-  return obj;
-}
-template <typename Type>
-static inline void hb_object_init (Type *obj)
-{
-  obj->header.ref_count.init (1);
-  obj->header.user_data = nullptr;
-}
-template <typename Type>
-static inline bool hb_object_is_inert (const Type *obj)
-{
-  return unlikely (obj->header.ref_count.is_inert ());
-}
-template <typename Type>
-static inline bool hb_object_is_valid (const Type *obj)
-{
-  return likely (obj->header.ref_count.is_valid ());
-}
-template <typename Type>
-static inline Type *hb_object_reference (Type *obj)
-{
-  hb_object_trace (obj, HB_FUNC);
-  if (unlikely (!obj || hb_object_is_inert (obj)))
-    return obj;
-  assert (hb_object_is_valid (obj));
-  obj->header.ref_count.inc ();
-  return obj;
-}
-template <typename Type>
-static inline bool hb_object_destroy (Type *obj)
-{
-  hb_object_trace (obj, HB_FUNC);
-  if (unlikely (!obj || hb_object_is_inert (obj)))
-    return false;
-  assert (hb_object_is_valid (obj));
-  if (obj->header.ref_count.dec () != 1)
-    return false;
-
-  hb_object_fini (obj);
-  return true;
-}
-template <typename Type>
-static inline void hb_object_fini (Type *obj)
-{
-  obj->header.ref_count.fini (); /* Do this before user_data */
-  if (obj->header.user_data)
-  {
-    obj->header.user_data->fini ();
-    free (obj->header.user_data);
-  }
-}
-template <typename Type>
-static inline bool hb_object_set_user_data (Type               *obj,
-                                            hb_user_data_key_t *key,
-                                            void *              data,
-                                            hb_destroy_func_t   destroy,
-                                            hb_bool_t           replace)
-{
-  if (unlikely (!obj || hb_object_is_inert (obj)))
-    return false;
-  assert (hb_object_is_valid (obj));
-
-retry:
-  hb_user_data_array_t *user_data = (hb_user_data_array_t *) hb_atomic_ptr_get (&obj->header.user_data);
-  if (unlikely (!user_data))
-  {
-    user_data = (hb_user_data_array_t *) calloc (sizeof (hb_user_data_array_t), 1);
-    if (unlikely (!user_data))
-      return false;
-    user_data->init ();
-    if (unlikely (!hb_atomic_ptr_cmpexch (&obj->header.user_data, nullptr, user_data)))
-    {
-      user_data->fini ();
-      free (user_data);
-      goto retry;
-    }
-  }
-
-  return user_data->set (key, data, destroy, replace);
-}
-
-template <typename Type>
-static inline void *hb_object_get_user_data (Type               *obj,
-                                             hb_user_data_key_t *key)
-{
-  if (unlikely (!obj || hb_object_is_inert (obj) || !obj->header.user_data))
-    return nullptr;
-  assert (hb_object_is_valid (obj));
-  return obj->header.user_data->get (key);
-}
-
-
-#endif /* HB_OBJECT_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-object.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,342 @@
+/*
+ * 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_OBJECT_HH
+#define HB_OBJECT_HH
+
+#include "hb.hh"
+#include "hb-atomic.hh"
+#include "hb-mutex.hh"
+#include "hb-vector.hh"
+
+
+/*
+ * Lockable set
+ */
+
+template <typename item_t, typename lock_t>
+struct hb_lockable_set_t
+{
+  hb_vector_t<item_t> items;
+
+  void init () { items.init (); }
+
+  template <typename T>
+  item_t *replace_or_insert (T v, lock_t &l, bool replace)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item) {
+      if (replace) {
+        item_t old = *item;
+        *item = v;
+        l.unlock ();
+        old.fini ();
+      }
+      else {
+        item = nullptr;
+        l.unlock ();
+      }
+    } else {
+      item = items.push (v);
+      l.unlock ();
+    }
+    return item;
+  }
+
+  template <typename T>
+  void remove (T v, lock_t &l)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item)
+    {
+      item_t old = *item;
+      *item = items[items.length - 1];
+      items.pop ();
+      l.unlock ();
+      old.fini ();
+    } else {
+      l.unlock ();
+    }
+  }
+
+  template <typename T>
+  bool find (T v, item_t *i, lock_t &l)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item)
+      *i = *item;
+    l.unlock ();
+    return !!item;
+  }
+
+  template <typename T>
+  item_t *find_or_insert (T v, lock_t &l)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (!item) {
+      item = items.push (v);
+    }
+    l.unlock ();
+    return item;
+  }
+
+  void fini (lock_t &l)
+  {
+    if (!items.length)
+    {
+      /* No need to lock. */
+      items.fini ();
+      return;
+    }
+    l.lock ();
+    while (items.length)
+    {
+      item_t old = items[items.length - 1];
+      items.pop ();
+      l.unlock ();
+      old.fini ();
+      l.lock ();
+    }
+    items.fini ();
+    l.unlock ();
+  }
+
+};
+
+
+/*
+ * Reference-count.
+ */
+
+#define HB_REFERENCE_COUNT_INERT_VALUE 0
+#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
+#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT (HB_REFERENCE_COUNT_INERT_VALUE)}
+
+struct hb_reference_count_t
+{
+  mutable hb_atomic_int_t ref_count;
+
+  void init (int v = 1) { ref_count.set_relaxed (v); }
+  int get_relaxed () const { return ref_count.get_relaxed (); }
+  int inc () const { return ref_count.inc (); }
+  int dec () const { return ref_count.dec (); }
+  void fini () { ref_count.set_relaxed (HB_REFERENCE_COUNT_POISON_VALUE); }
+
+  bool is_inert () const { return ref_count.get_relaxed () == HB_REFERENCE_COUNT_INERT_VALUE; }
+  bool is_valid () const { return ref_count.get_relaxed () > 0; }
+};
+
+
+/* user_data */
+
+struct hb_user_data_array_t
+{
+  struct hb_user_data_item_t {
+    hb_user_data_key_t *key;
+    void *data;
+    hb_destroy_func_t destroy;
+
+    bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; }
+    bool operator == (hb_user_data_item_t &other) const { return key == other.key; }
+
+    void fini () { if (destroy) destroy (data); }
+  };
+
+  hb_mutex_t lock;
+  hb_lockable_set_t<hb_user_data_item_t, hb_mutex_t> items;
+
+  void init () { lock.init (); items.init (); }
+
+  HB_INTERNAL bool set (hb_user_data_key_t *key,
+                        void *              data,
+                        hb_destroy_func_t   destroy,
+                        hb_bool_t           replace);
+
+  HB_INTERNAL void *get (hb_user_data_key_t *key);
+
+  void fini () { items.fini (lock); lock.fini (); }
+};
+
+
+/*
+ * Object header
+ */
+
+struct hb_object_header_t
+{
+  hb_reference_count_t ref_count;
+  mutable hb_atomic_int_t writable;
+  hb_atomic_ptr_t<hb_user_data_array_t> user_data;
+};
+#define HB_OBJECT_HEADER_STATIC \
+        { \
+          HB_REFERENCE_COUNT_INIT, \
+          HB_ATOMIC_INT_INIT (false), \
+          HB_ATOMIC_PTR_INIT (nullptr) \
+        }
+
+
+/*
+ * Object
+ */
+
+template <typename Type>
+static inline void hb_object_trace (const Type *obj, const char *function)
+{
+  DEBUG_MSG (OBJECT, (void *) obj,
+             "%s refcount=%d",
+             function,
+             obj ? obj->header.ref_count.get_relaxed () : 0);
+}
+
+template <typename Type>
+static inline Type *hb_object_create ()
+{
+  Type *obj = (Type *) calloc (1, sizeof (Type));
+
+  if (unlikely (!obj))
+    return obj;
+
+  hb_object_init (obj);
+  hb_object_trace (obj, HB_FUNC);
+  return obj;
+}
+template <typename Type>
+static inline void hb_object_init (Type *obj)
+{
+  obj->header.ref_count.init ();
+  obj->header.writable.set_relaxed (true);
+  obj->header.user_data.init ();
+}
+template <typename Type>
+static inline bool hb_object_is_inert (const Type *obj)
+{
+  return unlikely (obj->header.ref_count.is_inert ());
+}
+template <typename Type>
+static inline bool hb_object_is_valid (const Type *obj)
+{
+  return likely (obj->header.ref_count.is_valid ());
+}
+template <typename Type>
+static inline bool hb_object_is_immutable (const Type *obj)
+{
+  return !obj->header.writable.get_relaxed ();
+}
+template <typename Type>
+static inline void hb_object_make_immutable (const Type *obj)
+{
+  obj->header.writable.set_relaxed (false);
+}
+template <typename Type>
+static inline Type *hb_object_reference (Type *obj)
+{
+  hb_object_trace (obj, HB_FUNC);
+  if (unlikely (!obj || hb_object_is_inert (obj)))
+    return obj;
+  assert (hb_object_is_valid (obj));
+  obj->header.ref_count.inc ();
+  return obj;
+}
+template <typename Type>
+static inline bool hb_object_destroy (Type *obj)
+{
+  hb_object_trace (obj, HB_FUNC);
+  if (unlikely (!obj || hb_object_is_inert (obj)))
+    return false;
+  assert (hb_object_is_valid (obj));
+  if (obj->header.ref_count.dec () != 1)
+    return false;
+
+  hb_object_fini (obj);
+  return true;
+}
+template <typename Type>
+static inline void hb_object_fini (Type *obj)
+{
+  obj->header.ref_count.fini (); /* Do this before user_data */
+  hb_user_data_array_t *user_data = obj->header.user_data.get ();
+  if (user_data)
+  {
+    user_data->fini ();
+    free (user_data);
+    user_data = nullptr;
+  }
+}
+template <typename Type>
+static inline bool hb_object_set_user_data (Type               *obj,
+                                            hb_user_data_key_t *key,
+                                            void *              data,
+                                            hb_destroy_func_t   destroy,
+                                            hb_bool_t           replace)
+{
+  if (unlikely (!obj || hb_object_is_inert (obj)))
+    return false;
+  assert (hb_object_is_valid (obj));
+
+retry:
+  hb_user_data_array_t *user_data = obj->header.user_data.get ();
+  if (unlikely (!user_data))
+  {
+    user_data = (hb_user_data_array_t *) calloc (sizeof (hb_user_data_array_t), 1);
+    if (unlikely (!user_data))
+      return false;
+    user_data->init ();
+    if (unlikely (!obj->header.user_data.cmpexch (nullptr, user_data)))
+    {
+      user_data->fini ();
+      free (user_data);
+      goto retry;
+    }
+  }
+
+  return user_data->set (key, data, destroy, replace);
+}
+
+template <typename Type>
+static inline void *hb_object_get_user_data (Type               *obj,
+                                             hb_user_data_key_t *key)
+{
+  if (unlikely (!obj || hb_object_is_inert (obj)))
+    return nullptr;
+  assert (hb_object_is_valid (obj));
+  hb_user_data_array_t *user_data = obj->header.user_data.get ();
+  if (!user_data)
+    return nullptr;
+  return user_data->get (key);
+}
+
+
+#endif /* HB_OBJECT_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-file-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,570 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 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): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OPEN_FILE_PRIVATE_HH
-#define HB_OPEN_FILE_PRIVATE_HH
-
-#include "hb-open-type-private.hh"
-#include "hb-ot-head-table.hh"
-
-
-namespace OT {
-
-
-/*
- *
- * The OpenType Font File
- *
- */
-
-
-/*
- * Organization of an OpenType Font
- */
-
-struct OpenTypeFontFile;
-struct OffsetTable;
-struct TTCHeader;
-
-
-typedef struct TableRecord
-{
-  int cmp (Tag t) const
-  { return -t.cmp (tag); }
-
-  static int cmp (const void *pa, const void *pb)
-  {
-    const TableRecord *a = (const TableRecord *) pa;
-    const TableRecord *b = (const TableRecord *) pb;
-    return b->cmp (a->tag);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  Tag           tag;            /* 4-byte identifier. */
-  CheckSum      checkSum;       /* CheckSum for this table. */
-  Offset32      offset;         /* Offset from beginning of TrueType font
-                                 * file. */
-  HBUINT32      length;         /* Length of this table. */
-  public:
-  DEFINE_SIZE_STATIC (16);
-} OpenTypeTable;
-
-typedef struct OffsetTable
-{
-  friend struct OpenTypeFontFile;
-
-  inline unsigned int get_table_count (void) const
-  { return tables.len; }
-  inline const TableRecord& get_table (unsigned int i) const
-  {
-    return tables[i];
-  }
-  inline unsigned int get_table_tags (unsigned int  start_offset,
-                                      unsigned int *table_count, /* IN/OUT */
-                                      hb_tag_t     *table_tags /* OUT */) const
-  {
-    if (table_count)
-    {
-      if (start_offset >= tables.len)
-        *table_count = 0;
-      else
-        *table_count = MIN<unsigned int> (*table_count, tables.len - start_offset);
-
-      const TableRecord *sub_tables = tables.arrayZ + start_offset;
-      unsigned int count = *table_count;
-      for (unsigned int i = 0; i < count; i++)
-        table_tags[i] = sub_tables[i].tag;
-    }
-    return tables.len;
-  }
-  inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
-  {
-    Tag t;
-    t.set (tag);
-    /* Linear-search for small tables to work around fonts with unsorted
-     * table list. */
-    int i = tables.len < 64 ? tables.lsearch (t) : tables.bsearch (t);
-    if (table_index)
-      *table_index = i == -1 ? Index::NOT_FOUND_INDEX : (unsigned int) i;
-    return i != -1;
-  }
-  inline const TableRecord& get_table_by_tag (hb_tag_t tag) const
-  {
-    unsigned int table_index;
-    find_table_index (tag, &table_index);
-    return get_table (table_index);
-  }
-
-  public:
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         hb_tag_t sfnt_tag,
-                         Supplier<hb_tag_t> &tags,
-                         Supplier<hb_blob_t *> &blobs,
-                         unsigned int table_count)
-  {
-    TRACE_SERIALIZE (this);
-    /* Alloc 12 for the OTHeader. */
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    /* Write sfntVersion (bytes 0..3). */
-    sfnt_version.set (sfnt_tag);
-    /* Take space for numTables, searchRange, entrySelector, RangeShift
-     * and the TableRecords themselves.  */
-    if (unlikely (!tables.serialize (c, table_count))) return_trace (false);
-
-    const char *dir_end = (const char *) c->head;
-    HBUINT32 *checksum_adjustment = nullptr;
-
-    /* Write OffsetTables, alloc for and write actual table blobs. */
-    for (unsigned int i = 0; i < table_count; i++)
-    {
-      TableRecord &rec = tables.arrayZ[i];
-      hb_blob_t *blob = blobs[i];
-      rec.tag.set (tags[i]);
-      rec.length.set (hb_blob_get_length (blob));
-      rec.offset.serialize (c, this);
-
-      /* Allocate room for the table and copy it. */
-      char *start = (char *) c->allocate_size<void> (rec.length);
-      if (unlikely (!start)) {return false;}
-
-      memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
-
-      /* 4-byte allignment. */
-      if (rec.length % 4)
-        c->allocate_size<void> (4 - rec.length % 4);
-      const char *end = (const char *) c->head;
-
-      if (tags[i] == HB_OT_TAG_head && end - start >= head::static_size)
-      {
-        head *h = (head *) start;
-        checksum_adjustment = &h->checkSumAdjustment;
-        checksum_adjustment->set (0);
-      }
-
-      rec.checkSum.set_for_data (start, end - start);
-    }
-    tags += table_count;
-    blobs += table_count;
-
-    tables.qsort ();
-
-    if (checksum_adjustment)
-    {
-      CheckSum checksum;
-
-      /* The following line is a slower version of the following block. */
-      //checksum.set_for_data (this, (const char *) c->head - (const char *) this);
-      checksum.set_for_data (this, dir_end - (const char *) this);
-      for (unsigned int i = 0; i < table_count; i++)
-      {
-        TableRecord &rec = tables.arrayZ[i];
-        checksum.set (checksum + rec.checkSum);
-      }
-
-      checksum_adjustment->set (0xB1B0AFBAu - checksum);
-    }
-
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && tables.sanitize (c));
-  }
-
-  protected:
-  Tag           sfnt_version;   /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
-  BinSearchArrayOf<TableRecord>
-                tables;
-  public:
-  DEFINE_SIZE_ARRAY (12, tables);
-} OpenTypeFontFace;
-
-
-/*
- * TrueType Collections
- */
-
-struct TTCHeaderVersion1
-{
-  friend struct TTCHeader;
-
-  inline unsigned int get_face_count (void) const { return table.len; }
-  inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (table.sanitize (c, this));
-  }
-
-  protected:
-  Tag           ttcTag;         /* TrueType Collection ID string: 'ttcf' */
-  FixedVersion<>version;        /* Version of the TTC Header (1.0),
-                                 * 0x00010000u */
-  LArrayOf<LOffsetTo<OffsetTable> >
-                table;          /* Array of offsets to the OffsetTable for each font
-                                 * from the beginning of the file */
-  public:
-  DEFINE_SIZE_ARRAY (12, table);
-};
-
-struct TTCHeader
-{
-  friend struct OpenTypeFontFile;
-
-  private:
-
-  inline unsigned int get_face_count (void) const
-  {
-    switch (u.header.version.major) {
-    case 2: /* version 2 is compatible with version 1 */
-    case 1: return u.version1.get_face_count ();
-    default:return 0;
-    }
-  }
-  inline const OpenTypeFontFace& get_face (unsigned int i) const
-  {
-    switch (u.header.version.major) {
-    case 2: /* version 2 is compatible with version 1 */
-    case 1: return u.version1.get_face (i);
-    default:return Null(OpenTypeFontFace);
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
-    switch (u.header.version.major) {
-    case 2: /* version 2 is compatible with version 1 */
-    case 1: return_trace (u.version1.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  struct {
-  Tag           ttcTag;         /* TrueType Collection ID string: 'ttcf' */
-  FixedVersion<>version;        /* Version of the TTC Header (1.0 or 2.0),
-                                 * 0x00010000u or 0x00020000u */
-  }                     header;
-  TTCHeaderVersion1     version1;
-  } u;
-};
-
-/*
- * Mac Resource Fork
- */
-
-struct ResourceRefItem
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    // actual data sanitization is done on ResourceForkHeader sanitizer
-    return_trace (likely (c->check_struct (this)));
-  }
-
-  HBINT16       id;             /* Resource ID, is really should be signed? */
-  HBINT16       nameOffset;     /* Offset from beginning of resource name list
-                                 * to resource name, minus means there is no */
-  HBUINT8       attr;           /* Resource attributes */
-  HBUINT24      dataOffset;     /* Offset from beginning of resource data to
-                                 * data for this resource */
-  HBUINT32      reserved;       /* Reserved for handle to resource */
-  public:
-  DEFINE_SIZE_STATIC (12);
-};
-
-struct ResourceTypeItem
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    // RefList sanitization is done on ResourceMap sanitizer
-    return_trace (likely (c->check_struct (this)));
-  }
-
-  inline unsigned int get_resource_count () const
-  {
-    return numRes + 1;
-  }
-
-  inline bool is_sfnt () const
-  {
-    return type == HB_TAG ('s','f','n','t');
-  }
-
-  inline const ResourceRefItem& get_ref_item (const void *base,
-                                              unsigned int i) const
-  {
-    return (base+refList)[i];
-  }
-
-  protected:
-  Tag           type;           /* Resource type */
-  HBUINT16      numRes;         /* Number of resource this type in map minus 1 */
-  OffsetTo<UnsizedArrayOf<ResourceRefItem> >
-                refList;        /* Offset from beginning of resource type list
-                                 * to reference list for this type */
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct ResourceMap
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this)))
-      return_trace (false);
-    for (unsigned int i = 0; i < get_types_count (); ++i)
-    {
-      const ResourceTypeItem& type = get_type (i);
-      if (unlikely (!type.sanitize (c)))
-        return_trace (false);
-      for (unsigned int j = 0; j < type.get_resource_count (); ++j)
-        if (unlikely (!get_ref_item (type, j).sanitize (c)))
-          return_trace (false);
-    }
-    return_trace (true);
-  }
-
-  inline const ResourceTypeItem& get_type (unsigned int i) const
-  {
-    // Why offset from the second byte of the object? I'm not sure
-    return ((&reserved[2])+typeList)[i];
-  }
-
-  inline unsigned int get_types_count () const
-  {
-    return nTypes + 1;
-  }
-
-  inline const ResourceRefItem &get_ref_item (const ResourceTypeItem &type,
-                                              unsigned int i) const
-  {
-    return type.get_ref_item (&(this+typeList), i);
-  }
-
-  inline const PString& get_name (const ResourceRefItem &item,
-                                  unsigned int i) const
-  {
-    if (item.nameOffset == -1)
-      return Null (PString);
-
-    return StructAtOffset<PString> (this, nameList + item.nameOffset);
-  }
-
-  protected:
-  HBUINT8       reserved[16];   /* Reserved for copy of resource header */
-  LOffsetTo<ResourceMap>
-                reserved1;      /* Reserved for handle to next resource map */
-  HBUINT16      reserved2;      /* Reserved for file reference number */
-  HBUINT16      attr;           /* Resource fork attribute */
-  OffsetTo<UnsizedArrayOf<ResourceTypeItem> >
-                typeList;       /* Offset from beginning of map to
-                                 * resource type list */
-  HBUINT16      nameList;       /* Offset from beginning of map to
-                                 * resource name list */
-  HBUINT16      nTypes;         /* Number of types in the map minus 1 */
-  public:
-  DEFINE_SIZE_STATIC (30);
-};
-
-struct ResourceForkHeader
-{
-  inline unsigned int get_face_count () const
-  {
-    const ResourceMap &resource_map = this+map;
-    for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
-    {
-      const ResourceTypeItem& type = resource_map.get_type (i);
-      if (type.is_sfnt ())
-        return type.get_resource_count ();
-    }
-    return 0;
-  }
-
-  inline const LArrayOf<HBUINT8>& get_data (const ResourceTypeItem& type,
-                                            unsigned int idx) const
-  {
-    const ResourceMap &resource_map = this+map;
-    unsigned int offset = dataOffset;
-    offset += resource_map.get_ref_item (type, idx).dataOffset;
-    return StructAtOffset<LArrayOf<HBUINT8> > (this, offset);
-  }
-
-  inline const OpenTypeFontFace& get_face (unsigned int idx) const
-  {
-    const ResourceMap &resource_map = this+map;
-    for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
-    {
-      const ResourceTypeItem& type = resource_map.get_type (i);
-      if (type.is_sfnt () && idx < type.get_resource_count ())
-        return (OpenTypeFontFace&) get_data (type, idx).arrayZ;
-    }
-    return Null (OpenTypeFontFace);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this)))
-      return_trace (false);
-
-    const ResourceMap &resource_map = this+map;
-    if (unlikely (!resource_map.sanitize (c)))
-      return_trace (false);
-
-    for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
-    {
-      const ResourceTypeItem& type = resource_map.get_type (i);
-      for (unsigned int j = 0; j < type.get_resource_count (); ++j)
-      {
-        const LArrayOf<HBUINT8>& data = get_data (type, j);
-        if (unlikely (!(data.sanitize (c) &&
-                        ((OpenTypeFontFace&) data.arrayZ).sanitize (c))))
-          return_trace (false);
-      }
-    }
-
-    return_trace (true);
-  }
-
-  protected:
-  HBUINT32      dataOffset;     /* Offset from beginning of resource fork
-                                 * to resource data */
-  LOffsetTo<ResourceMap>
-                map;            /* Offset from beginning of resource fork
-                                 * to resource map */
-  HBUINT32      dataLen;        /* Length of resource data */
-  HBUINT32      mapLen;         /* Length of resource map */
-  public:
-  DEFINE_SIZE_STATIC (16);
-};
-
-/*
- * OpenType Font File
- */
-
-struct OpenTypeFontFile
-{
-  static const hb_tag_t tableTag        = HB_TAG ('_','_','_','_'); /* Sanitizer needs this. */
-
-  enum {
-    CFFTag              = HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */
-    TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */
-    TTCTag              = HB_TAG ('t','t','c','f'), /* TrueType Collection */
-    DFontTag            = HB_TAG ( 0 , 0 , 1 , 0 ), /* DFont Mac Resource Fork */
-    TrueTag             = HB_TAG ('t','r','u','e'), /* Obsolete Apple TrueType */
-    Typ1Tag             = HB_TAG ('t','y','p','1')  /* Obsolete Apple Type1 font in SFNT container */
-  };
-
-  inline hb_tag_t get_tag (void) const { return u.tag; }
-
-  inline unsigned int get_face_count (void) const
-  {
-    switch (u.tag) {
-    case CFFTag:        /* All the non-collection tags */
-    case TrueTag:
-    case Typ1Tag:
-    case TrueTypeTag:   return 1;
-    case TTCTag:        return u.ttcHeader.get_face_count ();
-//    case DFontTag:    return u.rfHeader.get_face_count ();
-    default:            return 0;
-    }
-  }
-  inline const OpenTypeFontFace& get_face (unsigned int i) const
-  {
-    switch (u.tag) {
-    /* Note: for non-collection SFNT data we ignore index.  This is because
-     * Apple dfont container is a container of SFNT's.  So each SFNT is a
-     * non-TTC, but the index is more than zero. */
-    case CFFTag:        /* All the non-collection tags */
-    case TrueTag:
-    case Typ1Tag:
-    case TrueTypeTag:   return u.fontFace;
-    case TTCTag:        return u.ttcHeader.get_face (i);
-//    case DFontTag:    return u.rfHeader.get_face (i);
-    default:            return Null(OpenTypeFontFace);
-    }
-  }
-
-  inline bool serialize_single (hb_serialize_context_t *c,
-                                hb_tag_t sfnt_tag,
-                                Supplier<hb_tag_t> &tags,
-                                Supplier<hb_blob_t *> &blobs,
-                                unsigned int table_count)
-  {
-    TRACE_SERIALIZE (this);
-    assert (sfnt_tag != TTCTag);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    return_trace (u.fontFace.serialize (c, sfnt_tag, tags, blobs, table_count));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!u.tag.sanitize (c))) return_trace (false);
-    switch (u.tag) {
-    case CFFTag:        /* All the non-collection tags */
-    case TrueTag:
-    case Typ1Tag:
-    case TrueTypeTag:   return_trace (u.fontFace.sanitize (c));
-    case TTCTag:        return_trace (u.ttcHeader.sanitize (c));
-//    case DFontTag:    return_trace (u.rfHeader.sanitize (c));
-    default:            return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  Tag                   tag;            /* 4-byte identifier. */
-  OpenTypeFontFace      fontFace;
-  TTCHeader             ttcHeader;
-  ResourceForkHeader    rfHeader;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (4, tag);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OPEN_FILE_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-file.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,525 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 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): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OPEN_FILE_HH
+#define HB_OPEN_FILE_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-head-table.hh"
+
+
+namespace OT {
+
+
+/*
+ *
+ * The OpenType Font File
+ *
+ */
+
+
+/*
+ * Organization of an OpenType Font
+ */
+
+struct OpenTypeFontFile;
+struct OffsetTable;
+struct TTCHeader;
+
+
+typedef struct TableRecord
+{
+  int cmp (Tag t) const { return -t.cmp (tag); }
+
+  static int cmp (const void *pa, const void *pb)
+  {
+    const TableRecord *a = (const TableRecord *) pa;
+    const TableRecord *b = (const TableRecord *) pb;
+    return b->cmp (a->tag);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  Tag           tag;            /* 4-byte identifier. */
+  CheckSum      checkSum;       /* CheckSum for this table. */
+  Offset32      offset;         /* Offset from beginning of TrueType font
+                                 * file. */
+  HBUINT32      length;         /* Length of this table. */
+  public:
+  DEFINE_SIZE_STATIC (16);
+} OpenTypeTable;
+
+typedef struct OffsetTable
+{
+  friend struct OpenTypeFontFile;
+
+  unsigned int get_table_count () const { return tables.len; }
+  const TableRecord& get_table (unsigned int i) const
+  { return tables[i]; }
+  unsigned int get_table_tags (unsigned int  start_offset,
+                                      unsigned int *table_count, /* IN/OUT */
+                                      hb_tag_t     *table_tags /* OUT */) const
+  {
+    if (table_count)
+    {
+      if (start_offset >= tables.len)
+        *table_count = 0;
+      else
+        *table_count = MIN<unsigned int> (*table_count, tables.len - start_offset);
+
+      const TableRecord *sub_tables = tables.arrayZ + start_offset;
+      unsigned int count = *table_count;
+      for (unsigned int i = 0; i < count; i++)
+        table_tags[i] = sub_tables[i].tag;
+    }
+    return tables.len;
+  }
+  bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
+  {
+    Tag t;
+    t.set (tag);
+    return tables.bfind (t, table_index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
+  }
+  const TableRecord& get_table_by_tag (hb_tag_t tag) const
+  {
+    unsigned int table_index;
+    find_table_index (tag, &table_index);
+    return get_table (table_index);
+  }
+
+  public:
+
+  template <typename item_t>
+  bool serialize (hb_serialize_context_t *c,
+                  hb_tag_t sfnt_tag,
+                  hb_array_t<item_t> items)
+  {
+    TRACE_SERIALIZE (this);
+    /* Alloc 12 for the OTHeader. */
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    /* Write sfntVersion (bytes 0..3). */
+    sfnt_version.set (sfnt_tag);
+    /* Take space for numTables, searchRange, entrySelector, RangeShift
+     * and the TableRecords themselves.  */
+    if (unlikely (!tables.serialize (c, items.length))) return_trace (false);
+
+    const char *dir_end = (const char *) c->head;
+    HBUINT32 *checksum_adjustment = nullptr;
+
+    /* Write OffsetTables, alloc for and write actual table blobs. */
+    for (unsigned int i = 0; i < tables.len; i++)
+    {
+      TableRecord &rec = tables.arrayZ[i];
+      hb_blob_t *blob = items[i].blob;
+      rec.tag.set (items[i].tag);
+      rec.length.set (hb_blob_get_length (blob));
+      rec.offset.serialize (c, this);
+
+      /* Allocate room for the table and copy it. */
+      char *start = (char *) c->allocate_size<void> (rec.length);
+      if (unlikely (!start)) {return false;}
+
+      memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
+
+      /* 4-byte alignment. */
+      c->align (4);
+      const char *end = (const char *) c->head;
+
+      if (items[i].tag == HB_OT_TAG_head &&
+          (unsigned) (end - start) >= head::static_size)
+      {
+        head *h = (head *) start;
+        checksum_adjustment = &h->checkSumAdjustment;
+        checksum_adjustment->set (0);
+      }
+
+      rec.checkSum.set_for_data (start, end - start);
+    }
+
+    tables.qsort ();
+
+    if (checksum_adjustment)
+    {
+      CheckSum checksum;
+
+      /* The following line is a slower version of the following block. */
+      //checksum.set_for_data (this, (const char *) c->head - (const char *) this);
+      checksum.set_for_data (this, dir_end - (const char *) this);
+      for (unsigned int i = 0; i < items.length; i++)
+      {
+        TableRecord &rec = tables.arrayZ[i];
+        checksum.set (checksum + rec.checkSum);
+      }
+
+      checksum_adjustment->set (0xB1B0AFBAu - checksum);
+    }
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && tables.sanitize (c));
+  }
+
+  protected:
+  Tag           sfnt_version;   /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
+  BinSearchArrayOf<TableRecord>
+                tables;
+  public:
+  DEFINE_SIZE_ARRAY (12, tables);
+} OpenTypeFontFace;
+
+
+/*
+ * TrueType Collections
+ */
+
+struct TTCHeaderVersion1
+{
+  friend struct TTCHeader;
+
+  unsigned int get_face_count () const { return table.len; }
+  const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (table.sanitize (c, this));
+  }
+
+  protected:
+  Tag           ttcTag;         /* TrueType Collection ID string: 'ttcf' */
+  FixedVersion<>version;        /* Version of the TTC Header (1.0),
+                                 * 0x00010000u */
+  LArrayOf<LOffsetTo<OffsetTable> >
+                table;          /* Array of offsets to the OffsetTable for each font
+                                 * from the beginning of the file */
+  public:
+  DEFINE_SIZE_ARRAY (12, table);
+};
+
+struct TTCHeader
+{
+  friend struct OpenTypeFontFile;
+
+  private:
+
+  unsigned int get_face_count () const
+  {
+    switch (u.header.version.major) {
+    case 2: /* version 2 is compatible with version 1 */
+    case 1: return u.version1.get_face_count ();
+    default:return 0;
+    }
+  }
+  const OpenTypeFontFace& get_face (unsigned int i) const
+  {
+    switch (u.header.version.major) {
+    case 2: /* version 2 is compatible with version 1 */
+    case 1: return u.version1.get_face (i);
+    default:return Null(OpenTypeFontFace);
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
+    switch (u.header.version.major) {
+    case 2: /* version 2 is compatible with version 1 */
+    case 1: return_trace (u.version1.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  struct {
+  Tag           ttcTag;         /* TrueType Collection ID string: 'ttcf' */
+  FixedVersion<>version;        /* Version of the TTC Header (1.0 or 2.0),
+                                 * 0x00010000u or 0x00020000u */
+  }                     header;
+  TTCHeaderVersion1     version1;
+  } u;
+};
+
+/*
+ * Mac Resource Fork
+ *
+ * http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html
+ */
+
+struct ResourceRecord
+{
+  const OpenTypeFontFace & get_face (const void *data_base) const
+  { return CastR<OpenTypeFontFace> ((data_base+offset).arrayZ); }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                        const void *data_base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  offset.sanitize (c, data_base) &&
+                  get_face (data_base).sanitize (c));
+  }
+
+  protected:
+  HBUINT16      id;             /* Resource ID. */
+  HBINT16       nameOffset;     /* Offset from beginning of resource name list
+                                 * to resource name, -1 means there is none. */
+  HBUINT8       attrs;          /* Resource attributes */
+  NNOffsetTo<LArrayOf<HBUINT8>, HBUINT24>
+                offset;         /* Offset from beginning of data block to
+                                 * data for this resource */
+  HBUINT32      reserved;       /* Reserved for handle to resource */
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+#define HB_TAG_sfnt HB_TAG ('s','f','n','t')
+
+struct ResourceTypeRecord
+{
+  unsigned int get_resource_count () const
+  { return tag == HB_TAG_sfnt ? resCountM1 + 1 : 0; }
+
+  bool is_sfnt () const { return tag == HB_TAG_sfnt; }
+
+  const ResourceRecord& get_resource_record (unsigned int i,
+                                             const void *type_base) const
+  { return (type_base+resourcesZ).as_array (get_resource_count ())[i]; }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                 const void *type_base,
+                 const void *data_base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  resourcesZ.sanitize (c, type_base,
+                                       get_resource_count (),
+                                       data_base));
+  }
+
+  protected:
+  Tag           tag;            /* Resource type. */
+  HBUINT16      resCountM1;     /* Number of resources minus 1. */
+  NNOffsetTo<UnsizedArrayOf<ResourceRecord> >
+                resourcesZ;     /* Offset from beginning of resource type list
+                                 * to reference item list for this type. */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct ResourceMap
+{
+  unsigned int get_face_count () const
+  {
+    unsigned int count = get_type_count ();
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const ResourceTypeRecord& type = get_type_record (i);
+      if (type.is_sfnt ())
+        return type.get_resource_count ();
+    }
+    return 0;
+  }
+
+  const OpenTypeFontFace& get_face (unsigned int idx,
+                                    const void *data_base) const
+  {
+    unsigned int count = get_type_count ();
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const ResourceTypeRecord& type = get_type_record (i);
+      /* The check for idx < count is here because ResourceRecord is NOT null-safe.
+       * Because an offset of 0 there does NOT mean null. */
+      if (type.is_sfnt () && idx < type.get_resource_count ())
+        return type.get_resource_record (idx, &(this+typeList)).get_face (data_base);
+    }
+    return Null (OpenTypeFontFace);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *data_base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  typeList.sanitize (c, this,
+                                     &(this+typeList),
+                                     data_base));
+  }
+
+  private:
+  unsigned int get_type_count () const { return (this+typeList).lenM1 + 1; }
+
+  const ResourceTypeRecord& get_type_record (unsigned int i) const
+  { return (this+typeList)[i]; }
+
+  protected:
+  HBUINT8       reserved0[16];  /* Reserved for copy of resource header */
+  HBUINT32      reserved1;      /* Reserved for handle to next resource map */
+  HBUINT16      resreved2;      /* Reserved for file reference number */
+  HBUINT16      attrs;          /* Resource fork attribute */
+  NNOffsetTo<ArrayOfM1<ResourceTypeRecord> >
+                typeList;       /* Offset from beginning of map to
+                                 * resource type list */
+  Offset16      nameList;       /* Offset from beginning of map to
+                                 * resource name list */
+  public:
+  DEFINE_SIZE_STATIC (28);
+};
+
+struct ResourceForkHeader
+{
+  unsigned int get_face_count () const
+  { return (this+map).get_face_count (); }
+
+  const OpenTypeFontFace& get_face (unsigned int idx,
+                                    unsigned int *base_offset = nullptr) const
+  {
+    const OpenTypeFontFace &face = (this+map).get_face (idx, &(this+data));
+    if (base_offset)
+      *base_offset = (const char *) &face - (const char *) this;
+    return face;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  data.sanitize (c, this, dataLen) &&
+                  map.sanitize (c, this, &(this+data)));
+  }
+
+  protected:
+  LNNOffsetTo<UnsizedArrayOf<HBUINT8> >
+                data;           /* Offset from beginning of resource fork
+                                 * to resource data */
+  LNNOffsetTo<ResourceMap >
+                map;            /* Offset from beginning of resource fork
+                                 * to resource map */
+  HBUINT32      dataLen;        /* Length of resource data */
+  HBUINT32      mapLen;         /* Length of resource map */
+  public:
+  DEFINE_SIZE_STATIC (16);
+};
+
+/*
+ * OpenType Font File
+ */
+
+struct OpenTypeFontFile
+{
+  enum {
+    CFFTag              = HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */
+    TrueTypeTag         = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */
+    TTCTag              = HB_TAG ('t','t','c','f'), /* TrueType Collection */
+    DFontTag            = HB_TAG ( 0 , 0 , 1 , 0 ), /* DFont Mac Resource Fork */
+    TrueTag             = HB_TAG ('t','r','u','e'), /* Obsolete Apple TrueType */
+    Typ1Tag             = HB_TAG ('t','y','p','1')  /* Obsolete Apple Type1 font in SFNT container */
+  };
+
+  hb_tag_t get_tag () const { return u.tag; }
+
+  unsigned int get_face_count () const
+  {
+    switch (u.tag) {
+    case CFFTag:        /* All the non-collection tags */
+    case TrueTag:
+    case Typ1Tag:
+    case TrueTypeTag:   return 1;
+    case TTCTag:        return u.ttcHeader.get_face_count ();
+    case DFontTag:      return u.rfHeader.get_face_count ();
+    default:            return 0;
+    }
+  }
+  const OpenTypeFontFace& get_face (unsigned int i, unsigned int *base_offset = nullptr) const
+  {
+    if (base_offset)
+      *base_offset = 0;
+    switch (u.tag) {
+    /* Note: for non-collection SFNT data we ignore index.  This is because
+     * Apple dfont container is a container of SFNT's.  So each SFNT is a
+     * non-TTC, but the index is more than zero. */
+    case CFFTag:        /* All the non-collection tags */
+    case TrueTag:
+    case Typ1Tag:
+    case TrueTypeTag:   return u.fontFace;
+    case TTCTag:        return u.ttcHeader.get_face (i);
+    case DFontTag:      return u.rfHeader.get_face (i, base_offset);
+    default:            return Null(OpenTypeFontFace);
+    }
+  }
+
+  template <typename item_t>
+  bool serialize_single (hb_serialize_context_t *c,
+                         hb_tag_t sfnt_tag,
+                         hb_array_t<item_t> items)
+  {
+    TRACE_SERIALIZE (this);
+    assert (sfnt_tag != TTCTag);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    return_trace (u.fontFace.serialize (c, sfnt_tag, items));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!u.tag.sanitize (c))) return_trace (false);
+    switch (u.tag) {
+    case CFFTag:        /* All the non-collection tags */
+    case TrueTag:
+    case Typ1Tag:
+    case TrueTypeTag:   return_trace (u.fontFace.sanitize (c));
+    case TTCTag:        return_trace (u.ttcHeader.sanitize (c));
+    case DFontTag:      return_trace (u.rfHeader.sanitize (c));
+    default:            return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  Tag                   tag;            /* 4-byte identifier. */
+  OpenTypeFontFace      fontFace;
+  TTCHeader             ttcHeader;
+  ResourceForkHeader    rfHeader;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (4, tag);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OPEN_FILE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1300 +0,0 @@
-/*
- * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
- * Copyright © 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): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OPEN_TYPE_PRIVATE_HH
-#define HB_OPEN_TYPE_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-blob-private.hh"
-#include "hb-face-private.hh"
-
-
-namespace OT {
-
-
-
-/*
- * Casts
- */
-
-/* Cast to struct T, reference to reference */
-template<typename Type, typename TObject>
-static inline const Type& CastR(const TObject &X)
-{ return reinterpret_cast<const Type&> (X); }
-template<typename Type, typename TObject>
-static inline Type& CastR(TObject &X)
-{ return reinterpret_cast<Type&> (X); }
-
-/* Cast to struct T, pointer to pointer */
-template<typename Type, typename TObject>
-static inline const Type* CastP(const TObject *X)
-{ return reinterpret_cast<const Type*> (X); }
-template<typename Type, typename TObject>
-static inline Type* CastP(TObject *X)
-{ return reinterpret_cast<Type*> (X); }
-
-/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
- * location pointed to by P plus Ofs bytes. */
-template<typename Type>
-static inline const Type& StructAtOffset(const void *P, unsigned int offset)
-{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
-template<typename Type>
-static inline Type& StructAtOffset(void *P, unsigned int offset)
-{ return * reinterpret_cast<Type*> ((char *) P + offset); }
-
-/* StructAfter<T>(X) returns the struct T& that is placed after X.
- * Works with X of variable size also.  X must implement get_size() */
-template<typename Type, typename TObject>
-static inline const Type& StructAfter(const TObject &X)
-{ return StructAtOffset<Type>(&X, X.get_size()); }
-template<typename Type, typename TObject>
-static inline Type& StructAfter(TObject &X)
-{ return StructAtOffset<Type>(&X, X.get_size()); }
-
-
-
-/*
- * Size checking
- */
-
-/* Check _assertion in a method environment */
-#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
-  inline void _instance_assertion_on_line_##_line (void) const \
-  { \
-    static_assert ((_assertion), ""); \
-    ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
-  }
-# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
-# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
-
-/* Check that _code compiles in a method environment */
-#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
-  inline void _compiles_assertion_on_line_##_line (void) const \
-  { _code; }
-# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
-# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
-
-
-#define DEFINE_SIZE_STATIC(size) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
-  static const unsigned int static_size = (size); \
-  static const unsigned int min_size = (size); \
-  inline unsigned int get_size (void) const { return (size); }
-
-#define DEFINE_SIZE_UNION(size, _member) \
-  DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \
-  static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_MIN(size) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
-  static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_ARRAY(size, array) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
-  DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
-  static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
-  DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
-  static const unsigned int min_size = (size)
-
-
-
-/*
- * Dispatch
- */
-
-template <typename Context, typename Return, unsigned int MaxDebugDepth>
-struct hb_dispatch_context_t
-{
-  static const unsigned int max_debug_depth = MaxDebugDepth;
-  typedef Return return_t;
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
-  static return_t no_dispatch_return_value (void) { return Context::default_return_value (); }
-};
-
-
-/*
- * Sanitize
- */
-
-/* This limits sanitizing time on really broken fonts. */
-#ifndef HB_SANITIZE_MAX_EDITS
-#define HB_SANITIZE_MAX_EDITS 32
-#endif
-#ifndef HB_SANITIZE_MAX_OPS_FACTOR
-#define HB_SANITIZE_MAX_OPS_FACTOR 8
-#endif
-#ifndef HB_SANITIZE_MAX_OPS_MIN
-#define HB_SANITIZE_MAX_OPS_MIN 16384
-#endif
-
-struct hb_sanitize_context_t :
-       hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
-{
-  inline hb_sanitize_context_t (void) :
-        debug_depth (0),
-        start (nullptr), end (nullptr),
-        writable (false), edit_count (0), max_ops (0),
-        blob (nullptr),
-        num_glyphs (0) {}
-
-  inline const char *get_name (void) { return "SANITIZE"; }
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format)
-  { return format->sanitize (this); }
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
-  static return_t default_return_value (void) { return true; }
-  static return_t no_dispatch_return_value (void) { return false; }
-  bool stop_sublookup_iteration (const return_t r) const { return !r; }
-
-  inline void init (hb_blob_t *b)
-  {
-    this->blob = hb_blob_reference (b);
-    this->writable = false;
-  }
-
-  inline void start_processing (void)
-  {
-    this->start = hb_blob_get_data (this->blob, nullptr);
-    this->end = this->start + this->blob->length;
-    assert (this->start <= this->end); /* Must not overflow. */
-    this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
-                         (unsigned) HB_SANITIZE_MAX_OPS_MIN);
-    this->edit_count = 0;
-    this->debug_depth = 0;
-
-    DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
-                     "start [%p..%p] (%lu bytes)",
-                     this->start, this->end,
-                     (unsigned long) (this->end - this->start));
-  }
-
-  inline void end_processing (void)
-  {
-    DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
-                     "end [%p..%p] %u edit requests",
-                     this->start, this->end, this->edit_count);
-
-    hb_blob_destroy (this->blob);
-    this->blob = nullptr;
-    this->start = this->end = nullptr;
-  }
-
-  inline bool check_range (const void *base, unsigned int len) const
-  {
-    const char *p = (const char *) base;
-    bool ok = this->max_ops-- > 0 &&
-              this->start <= p &&
-              p <= this->end &&
-              (unsigned int) (this->end - p) >= len;
-
-    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
-       "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
-       p, p + len, len,
-       this->start, this->end,
-       ok ? "OK" : "OUT-OF-RANGE");
-
-    return likely (ok);
-  }
-
-  inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
-  {
-    const char *p = (const char *) base;
-    bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
-    unsigned int array_size = record_size * len;
-    bool ok = !overflows && this->check_range (base, array_size);
-
-    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
-       "check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s",
-       p, p + (record_size * len), record_size, len, (unsigned int) array_size,
-       this->start, this->end,
-       overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE");
-
-    return likely (ok);
-  }
-
-  template <typename Type>
-  inline bool check_struct (const Type *obj) const
-  {
-    return likely (this->check_range (obj, obj->min_size));
-  }
-
-  inline bool may_edit (const void *base, unsigned int len)
-  {
-    if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
-      return false;
-
-    const char *p = (const char *) base;
-    this->edit_count++;
-
-    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
-       "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
-       this->edit_count,
-       p, p + len, len,
-       this->start, this->end,
-       this->writable ? "GRANTED" : "DENIED");
-
-    return this->writable;
-  }
-
-  template <typename Type, typename ValueType>
-  inline bool try_set (const Type *obj, const ValueType &v) {
-    if (this->may_edit (obj, obj->static_size)) {
-      const_cast<Type *> (obj)->set (v);
-      return true;
-    }
-    return false;
-  }
-
-  mutable unsigned int debug_depth;
-  const char *start, *end;
-  bool writable;
-  unsigned int edit_count;
-  mutable int max_ops;
-  hb_blob_t *blob;
-  unsigned int num_glyphs;
-};
-
-
-
-/* Template to sanitize an object. */
-template <typename Type>
-struct Sanitizer
-{
-  inline Sanitizer (void) {}
-
-  inline hb_blob_t *sanitize (hb_blob_t *blob) {
-    bool sane;
-
-    /* TODO is_sane() stuff */
-
-    c->init (blob);
-
-  retry:
-    DEBUG_MSG_FUNC (SANITIZE, c->start, "start");
-
-    c->start_processing ();
-
-    if (unlikely (!c->start)) {
-      c->end_processing ();
-      return blob;
-    }
-
-    Type *t = CastP<Type> (const_cast<char *> (c->start));
-
-    sane = t->sanitize (c);
-    if (sane) {
-      if (c->edit_count) {
-        DEBUG_MSG_FUNC (SANITIZE, c->start, "passed first round with %d edits; going for second round", c->edit_count);
-
-        /* sanitize again to ensure no toe-stepping */
-        c->edit_count = 0;
-        sane = t->sanitize (c);
-        if (c->edit_count) {
-          DEBUG_MSG_FUNC (SANITIZE, c->start, "requested %d edits in second round; FAILLING", c->edit_count);
-          sane = false;
-        }
-      }
-    } else {
-      unsigned int edit_count = c->edit_count;
-      if (edit_count && !c->writable) {
-        c->start = hb_blob_get_data_writable (blob, nullptr);
-        c->end = c->start + blob->length;
-
-        if (c->start) {
-          c->writable = true;
-          /* ok, we made it writable by relocating.  try again */
-          DEBUG_MSG_FUNC (SANITIZE, c->start, "retry");
-          goto retry;
-        }
-      }
-    }
-
-    c->end_processing ();
-
-    DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED");
-    if (sane)
-    {
-      blob->lock ();
-      return blob;
-    }
-    else
-    {
-      hb_blob_destroy (blob);
-      return hb_blob_get_empty ();
-    }
-  }
-
-  inline void set_num_glyphs (unsigned int num_glyphs) { c->num_glyphs = num_glyphs; }
-
-  private:
-  hb_sanitize_context_t c[1];
-};
-
-
-
-/*
- * Serialize
- */
-
-
-struct hb_serialize_context_t
-{
-  inline hb_serialize_context_t (void *start_, unsigned int size)
-  {
-    this->start = (char *) start_;
-    this->end = this->start + size;
-
-    this->ran_out_of_room = false;
-    this->head = this->start;
-    this->debug_depth = 0;
-  }
-
-  template <typename Type>
-  inline Type *start_serialize (void)
-  {
-    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
-                     "start [%p..%p] (%lu bytes)",
-                     this->start, this->end,
-                     (unsigned long) (this->end - this->start));
-
-    return start_embed<Type> ();
-  }
-
-  inline void end_serialize (void)
-  {
-    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
-                     "end [%p..%p] serialized %d bytes; %s",
-                     this->start, this->end,
-                     (int) (this->head - this->start),
-                     this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room");
-
-  }
-
-  template <typename Type>
-  inline Type *copy (void)
-  {
-    assert (!this->ran_out_of_room);
-    unsigned int len = this->head - this->start;
-    void *p = malloc (len);
-    if (p)
-      memcpy (p, this->start, len);
-    return reinterpret_cast<Type *> (p);
-  }
-
-  template <typename Type>
-  inline Type *allocate_size (unsigned int size)
-  {
-    if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) {
-      this->ran_out_of_room = true;
-      return nullptr;
-    }
-    memset (this->head, 0, size);
-    char *ret = this->head;
-    this->head += size;
-    return reinterpret_cast<Type *> (ret);
-  }
-
-  template <typename Type>
-  inline Type *allocate_min (void)
-  {
-    return this->allocate_size<Type> (Type::min_size);
-  }
-
-  template <typename Type>
-  inline Type *start_embed (void)
-  {
-    Type *ret = reinterpret_cast<Type *> (this->head);
-    return ret;
-  }
-
-  template <typename Type>
-  inline Type *embed (const Type &obj)
-  {
-    unsigned int size = obj.get_size ();
-    Type *ret = this->allocate_size<Type> (size);
-    if (unlikely (!ret)) return nullptr;
-    memcpy (ret, obj, size);
-    return ret;
-  }
-
-  template <typename Type>
-  inline Type *extend_min (Type &obj)
-  {
-    unsigned int size = obj.min_size;
-    assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
-    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
-    return reinterpret_cast<Type *> (&obj);
-  }
-
-  template <typename Type>
-  inline Type *extend (Type &obj)
-  {
-    unsigned int size = obj.get_size ();
-    assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
-    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
-    return reinterpret_cast<Type *> (&obj);
-  }
-
-  inline void truncate (void *new_head)
-  {
-    assert (this->start < new_head && new_head <= this->head);
-    this->head = (char *) new_head;
-  }
-
-  unsigned int debug_depth;
-  char *start, *end, *head;
-  bool ran_out_of_room;
-};
-
-template <typename Type>
-struct Supplier
-{
-  inline Supplier (const Type *array, unsigned int len_, unsigned int stride_=sizeof(Type))
-  {
-    head = array;
-    len = len_;
-    stride = stride_;
-  }
-  inline const Type operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len)) return Type ();
-    return * (const Type *) (const void *) ((const char *) head + stride * i);
-  }
-
-  inline Supplier<Type> & operator += (unsigned int count)
-  {
-    if (unlikely (count > len))
-      count = len;
-    len -= count;
-    head = (const Type *) (const void *) ((const char *) head + stride * count);
-    return *this;
-  }
-
-  private:
-  inline Supplier (const Supplier<Type> &); /* Disallow copy */
-  inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */
-
-  unsigned int len;
-  unsigned int stride;
-  const Type *head;
-};
-
-
-/*
- *
- * The OpenType Font File: Data Types
- */
-
-
-/* "The following data types are used in the OpenType font file.
- *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
-
-/*
- * Int types
- */
-
-
-template <typename Type, int Bytes> struct BEInt;
-
-template <typename Type>
-struct BEInt<Type, 1>
-{
-  public:
-  inline void set (Type V)
-  {
-    v = V;
-  }
-  inline operator Type (void) const
-  {
-    return v;
-  }
-  private: uint8_t v;
-};
-template <typename Type>
-struct BEInt<Type, 2>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[0] = (V >>  8) & 0xFF;
-    v[1] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[0] <<  8)
-         + (v[1]      );
-  }
-  private: uint8_t v[2];
-};
-template <typename Type>
-struct BEInt<Type, 3>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[0] = (V >> 16) & 0xFF;
-    v[1] = (V >>  8) & 0xFF;
-    v[2] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[0] << 16)
-         + (v[1] <<  8)
-         + (v[2]      );
-  }
-  private: uint8_t v[3];
-};
-template <typename Type>
-struct BEInt<Type, 4>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[0] = (V >> 24) & 0xFF;
-    v[1] = (V >> 16) & 0xFF;
-    v[2] = (V >>  8) & 0xFF;
-    v[3] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[0] << 24)
-         + (v[1] << 16)
-         + (v[2] <<  8)
-         + (v[3]      );
-  }
-  private: uint8_t v[4];
-};
-
-/* Integer types in big-endian order and no alignment requirement */
-template <typename Type, unsigned int Size>
-struct IntType
-{
-  inline void set (Type i) { v.set (i); }
-  inline operator Type(void) const { return v; }
-  inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
-  inline bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
-  static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
-  template <typename Type2>
-  inline int cmp (Type2 a) const
-  {
-    Type b = v;
-    if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
-      return (int) a - (int) b;
-    else
-      return a < b ? -1 : a == b ? 0 : +1;
-  }
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this)));
-  }
-  protected:
-  BEInt<Type, Size> v;
-  public:
-  DEFINE_SIZE_STATIC (Size);
-};
-
-typedef IntType<uint8_t,  1> HBUINT8;   /* 8-bit unsigned integer. */
-typedef IntType<int8_t,   1> HBINT8;    /* 8-bit signed integer. */
-typedef IntType<uint16_t, 2> HBUINT16;  /* 16-bit unsigned integer. */
-typedef IntType<int16_t,  2> HBINT16;   /* 16-bit signed integer. */
-typedef IntType<uint32_t, 4> HBUINT32;  /* 32-bit unsigned integer. */
-typedef IntType<int32_t,  4> HBINT32;   /* 32-bit signed integer. */
-typedef IntType<uint32_t, 3> HBUINT24;  /* 24-bit unsigned integer. */
-
-/* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
-typedef HBINT16 FWORD;
-
-/* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
-typedef HBUINT16 UFWORD;
-
-/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
-struct F2DOT14 : HBINT16
-{
-  // 16384 means 1<<14
-  inline float to_float (void) const { return ((int32_t) v) / 16384.f; }
-  inline void set_float (float f) { v.set (round (f * 16384.f)); }
-  public:
-  DEFINE_SIZE_STATIC (2);
-};
-
-/* 32-bit signed fixed-point number (16.16). */
-struct Fixed : HBINT32
-{
-  // 65536 means 1<<16
-  inline float to_float (void) const { return ((int32_t) v) / 65536.f; }
-  inline void set_float (float f) { v.set (round (f * 65536.f)); }
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-/* Date represented in number of seconds since 12:00 midnight, January 1,
- * 1904. The value is represented as a signed 64-bit integer. */
-struct LONGDATETIME
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this)));
-  }
-  protected:
-  HBINT32 major;
-  HBUINT32 minor;
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-/* Array of four uint8s (length = 32 bits) used to identify a script, language
- * system, feature, or baseline */
-struct Tag : HBUINT32
-{
-  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
-  inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); }
-  inline operator char* (void) { return reinterpret_cast<char *> (&this->v); }
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-DEFINE_NULL_DATA (OT, Tag, "    ");
-
-/* Glyph index number, same as uint16 (length = 16 bits) */
-typedef HBUINT16 GlyphID;
-
-/* Name-table index, same as uint16 (length = 16 bits) */
-typedef HBUINT16 NameID;
-
-/* Script/language-system/feature index */
-struct Index : HBUINT16 {
-  static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
-};
-DEFINE_NULL_DATA (OT, Index, "\xff\xff");
-
-/* Offset, Null offset = 0 */
-template <typename Type>
-struct Offset : Type
-{
-  inline bool is_null (void) const { return 0 == *this; }
-
-  inline void *serialize (hb_serialize_context_t *c, const void *base)
-  {
-    void *t = c->start_embed<void> ();
-    this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
-    return t;
-  }
-
-  public:
-  DEFINE_SIZE_STATIC (sizeof(Type));
-};
-
-typedef Offset<HBUINT16> Offset16;
-typedef Offset<HBUINT32> Offset32;
-
-
-/* CheckSum */
-struct CheckSum : HBUINT32
-{
-  /* This is reference implementation from the spec. */
-  static inline uint32_t CalcTableChecksum (const HBUINT32 *Table, uint32_t Length)
-  {
-    uint32_t Sum = 0L;
-    assert (0 == (Length & 3));
-    const HBUINT32 *EndPtr = Table + Length / HBUINT32::static_size;
-
-    while (Table < EndPtr)
-      Sum += *Table++;
-    return Sum;
-  }
-
-  /* Note: data should be 4byte aligned and have 4byte padding at the end. */
-  inline void set_for_data (const void *data, unsigned int length)
-  { set (CalcTableChecksum ((const HBUINT32 *) data, length)); }
-
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-
-/*
- * Version Numbers
- */
-
-template <typename FixedType=HBUINT16>
-struct FixedVersion
-{
-  inline uint32_t to_int (void) const { return (major << (sizeof(FixedType) * 8)) + minor; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  FixedType major;
-  FixedType minor;
-  public:
-  DEFINE_SIZE_STATIC (2 * sizeof(FixedType));
-};
-
-
-
-/*
- * Template subclasses of Offset that do the dereferencing.
- * Use: (base+offset)
- */
-
-template <typename Type, typename OffsetType=HBUINT16>
-struct OffsetTo : Offset<OffsetType>
-{
-  inline const Type& operator () (const void *base) const
-  {
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return Null(Type);
-    return StructAtOffset<const Type> (base, offset);
-  }
-  inline Type& operator () (void *base) const
-  {
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return Crap(Type);
-    return StructAtOffset<Type> (base, offset);
-  }
-
-  inline Type& serialize (hb_serialize_context_t *c, const void *base)
-  {
-    return * (Type *) Offset<OffsetType>::serialize (c, base);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return_trace (false);
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return_trace (true);
-    if (unlikely (!c->check_range (base, offset))) return_trace (false);
-    const Type &obj = StructAtOffset<Type> (base, offset);
-    return_trace (likely (obj.sanitize (c)) || neuter (c));
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return_trace (false);
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return_trace (true);
-    if (unlikely (!c->check_range (base, offset))) return_trace (false);
-    const Type &obj = StructAtOffset<Type> (base, offset);
-    return_trace (likely (obj.sanitize (c, user_data)) || neuter (c));
-  }
-
-  /* Set the offset to Null */
-  inline bool neuter (hb_sanitize_context_t *c) const {
-    return c->try_set (this, 0);
-  }
-  DEFINE_SIZE_STATIC (sizeof(OffsetType));
-};
-template <typename Type> struct LOffsetTo : OffsetTo<Type, HBUINT32> {};
-template <typename Base, typename OffsetType, typename Type>
-static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
-template <typename Base, typename OffsetType, typename Type>
-static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
-
-
-/*
- * Array Types
- */
-
-
-/* TODO Use it in ArrayOf, HeadlessArrayOf, and other places around the code base?? */
-template <typename Type>
-struct UnsizedArrayOf
-{
-  inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; }
-  inline Type& operator [] (unsigned int i) { return arrayZ[i]; }
-
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize(), ie. they do not
-     * reference other structs via offsets.
-     */
-    (void) (false && arrayZ[0].sanitize (c));
-
-    return_trace (true);
-  }
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, base)))
-        return_trace (false);
-    return_trace (true);
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
-        return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_array (arrayZ, arrayZ[0].static_size, count));
-  }
-
-  public:
-  Type  arrayZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (0, arrayZ);
-};
-
-/* Unsized array of offset's */
-template <typename Type, typename OffsetType>
-struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType> > {};
-
-/* Unsized array of offsets relative to the beginning of the array itself. */
-template <typename Type, typename OffsetType>
-struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType>
-{
-  inline const Type& operator [] (unsigned int i) const
-  {
-    return this+this->arrayZ[i];
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this)));
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this, user_data)));
-  }
-};
-
-
-/* An array with a number of elements. */
-template <typename Type, typename LenType=HBUINT16>
-struct ArrayOf
-{
-  const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
-  {
-    unsigned int count = len;
-    if (unlikely (start_offset > count))
-      count = 0;
-    else
-      count -= start_offset;
-    count = MIN (count, *pcount);
-    *pcount = count;
-    return arrayZ + start_offset;
-  }
-
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len)) return Null(Type);
-    return arrayZ[i];
-  }
-  inline Type& operator [] (unsigned int i)
-  {
-    if (unlikely (i >= len)) return Crap(Type);
-    return arrayZ[i];
-  }
-  inline unsigned int get_size (void) const
-  { return len.static_size + len * Type::static_size; }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         unsigned int items_len)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    len.set (items_len); /* TODO(serialize) Overflow? */
-    if (unlikely (!c->extend (*this))) return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<Type> &items,
-                         unsigned int items_len)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!serialize (c, items_len))) return_trace (false);
-    for (unsigned int i = 0; i < items_len; i++)
-      arrayZ[i] = items[i];
-    items += items_len;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize(), ie. they do not
-     * reference other structs via offsets.
-     */
-    (void) (false && arrayZ[0].sanitize (c));
-
-    return_trace (true);
-  }
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, base)))
-        return_trace (false);
-    return_trace (true);
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
-        return_trace (false);
-    return_trace (true);
-  }
-
-  template <typename SearchType>
-  inline int lsearch (const SearchType &x) const
-  {
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!this->arrayZ[i].cmp (x))
-        return i;
-    return -1;
-  }
-
-  inline void qsort (void)
-  {
-    ::qsort (arrayZ, len, sizeof (Type), Type::cmp);
-  }
-
-  private:
-  inline bool sanitize_shallow (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (len.sanitize (c) && c->check_array (arrayZ, Type::static_size, len));
-  }
-
-  public:
-  LenType len;
-  Type arrayZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
-};
-template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {};
-typedef ArrayOf<HBUINT8, HBUINT8> PString;
-
-/* Array of Offset's */
-template <typename Type, typename OffsetType=HBUINT16>
-struct OffsetArrayOf : ArrayOf<OffsetTo<Type, OffsetType> > {};
-
-/* Array of offsets relative to the beginning of the array itself. */
-template <typename Type>
-struct OffsetListOf : OffsetArrayOf<Type>
-{
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= this->len)) return Null(Type);
-    return this+this->arrayZ[i];
-  }
-  inline const Type& operator [] (unsigned int i)
-  {
-    if (unlikely (i >= this->len)) return Crap(Type);
-    return this+this->arrayZ[i];
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (OffsetArrayOf<Type>::sanitize (c, this));
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data));
-  }
-};
-
-
-/* An array starting at second element. */
-template <typename Type, typename LenType=HBUINT16>
-struct HeadlessArrayOf
-{
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len || !i)) return Null(Type);
-    return arrayZ[i-1];
-  }
-  inline Type& operator [] (unsigned int i)
-  {
-    if (unlikely (i >= len || !i)) return Crap(Type);
-    return arrayZ[i-1];
-  }
-  inline unsigned int get_size (void) const
-  { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<Type> &items,
-                         unsigned int items_len)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    len.set (items_len); /* TODO(serialize) Overflow? */
-    if (unlikely (!items_len)) return_trace (true);
-    if (unlikely (!c->extend (*this))) return_trace (false);
-    for (unsigned int i = 0; i < items_len - 1; i++)
-      arrayZ[i] = items[i];
-    items += items_len - 1;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize(), ie. they do not
-     * reference other structs via offsets.
-     */
-    (void) (false && arrayZ[0].sanitize (c));
-
-    return_trace (true);
-  }
-
-  private:
-  inline bool sanitize_shallow (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (len.sanitize (c) &&
-                  (!len || c->check_array (arrayZ, Type::static_size, len - 1)));
-  }
-
-  public:
-  LenType len;
-  Type arrayZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
-};
-
-
-/*
- * An array with sorted elements.  Supports binary searching.
- */
-template <typename Type, typename LenType=HBUINT16>
-struct SortedArrayOf : ArrayOf<Type, LenType>
-{
-  template <typename SearchType>
-  inline int bsearch (const SearchType &x) const
-  {
-    /* Hand-coded bsearch here since this is in the hot inner loop. */
-    const Type *arr = this->arrayZ;
-    int min = 0, max = (int) this->len - 1;
-    while (min <= max)
-    {
-      int mid = (min + max) / 2;
-      int c = arr[mid].cmp (x);
-      if (c < 0)
-        max = mid - 1;
-      else if (c > 0)
-        min = mid + 1;
-      else
-        return mid;
-    }
-    return -1;
-  }
-};
-
-/*
- * Binary-search arrays
- */
-
-struct BinSearchHeader
-{
-  inline operator uint32_t (void) const { return len; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  inline void set (unsigned int v)
-  {
-    len.set (v);
-    assert (len == v);
-    entrySelector.set (MAX (1u, _hb_bit_storage (v)) - 1);
-    searchRange.set (16 * (1u << entrySelector));
-    rangeShift.set (v * 16 > searchRange
-                    ? 16 * v - searchRange
-                    : 0);
-  }
-
-  protected:
-  HBUINT16      len;
-  HBUINT16      searchRange;
-  HBUINT16      entrySelector;
-  HBUINT16      rangeShift;
-
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-template <typename Type>
-struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader> {};
-
-
-/* Lazy struct and blob loaders. */
-
-/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
-template <typename T>
-struct hb_lazy_loader_t
-{
-  inline void init (hb_face_t *face_)
-  {
-    face = face_;
-    instance = nullptr;
-  }
-
-  inline void fini (void)
-  {
-    if (instance && instance != &Null(T))
-    {
-      instance->fini();
-      free (instance);
-    }
-  }
-
-  inline const T* get (void) const
-  {
-  retry:
-    T *p = (T *) hb_atomic_ptr_get (&instance);
-    if (unlikely (!p))
-    {
-      p = (T *) calloc (1, sizeof (T));
-      if (unlikely (!p))
-        p = const_cast<T *> (&Null(T));
-      else
-        p->init (face);
-      if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), nullptr, p)))
-      {
-        if (p != &Null(T))
-          p->fini ();
-        goto retry;
-      }
-    }
-    return p;
-  }
-
-  inline const T* operator-> (void) const
-  {
-    return get ();
-  }
-
-  private:
-  hb_face_t *face;
-  T *instance;
-};
-
-/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
-template <typename T>
-struct hb_table_lazy_loader_t
-{
-  inline void init (hb_face_t *face_)
-  {
-    face = face_;
-    blob = nullptr;
-  }
-
-  inline void fini (void)
-  {
-    hb_blob_destroy (blob);
-  }
-
-  inline const T* get (void) const
-  {
-  retry:
-    hb_blob_t *blob_ = (hb_blob_t *) hb_atomic_ptr_get (&blob);
-    if (unlikely (!blob_))
-    {
-      blob_ = OT::Sanitizer<T>().sanitize (face->reference_table (T::tableTag));
-      if (!hb_atomic_ptr_cmpexch (&blob, nullptr, blob_))
-      {
-        hb_blob_destroy (blob_);
-        goto retry;
-      }
-      blob = blob_;
-    }
-    return blob_->as<T> ();
-  }
-
-  inline const T* operator-> (void) const
-  {
-    return get();
-  }
-
-  private:
-  hb_face_t *face;
-  mutable hb_blob_t *blob;
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OPEN_TYPE_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,1008 @@
+/*
+ * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
+ * Copyright © 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): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OPEN_TYPE_HH
+#define HB_OPEN_TYPE_HH
+
+#include "hb.hh"
+#include "hb-blob.hh"
+#include "hb-face.hh"
+#include "hb-machinery.hh"
+#include "hb-subset.hh"
+
+
+namespace OT {
+
+
+/*
+ *
+ * The OpenType Font File: Data Types
+ */
+
+
+/* "The following data types are used in the OpenType font file.
+ *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
+
+/*
+ * Int types
+ */
+
+template <bool is_signed> struct hb_signedness_int;
+template <> struct hb_signedness_int<false> { typedef unsigned int value; };
+template <> struct hb_signedness_int<true>  { typedef   signed int value; };
+
+/* Integer types in big-endian order and no alignment requirement */
+template <typename Type, unsigned int Size>
+struct IntType
+{
+  typedef Type type;
+  typedef typename hb_signedness_int<hb_is_signed<Type>::value>::value wide_type;
+
+  void set (wide_type i) { v.set (i); }
+  operator wide_type () const { return v; }
+  bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
+  bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
+  static int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
+  template <typename Type2>
+  int cmp (Type2 a) const
+  {
+    Type b = v;
+    if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
+      return (int) a - (int) b;
+    else
+      return a < b ? -1 : a == b ? 0 : +1;
+  }
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+  protected:
+  BEInt<Type, Size> v;
+  public:
+  DEFINE_SIZE_STATIC (Size);
+};
+
+typedef IntType<uint8_t,  1> HBUINT8;   /* 8-bit unsigned integer. */
+typedef IntType<int8_t,   1> HBINT8;    /* 8-bit signed integer. */
+typedef IntType<uint16_t, 2> HBUINT16;  /* 16-bit unsigned integer. */
+typedef IntType<int16_t,  2> HBINT16;   /* 16-bit signed integer. */
+typedef IntType<uint32_t, 4> HBUINT32;  /* 32-bit unsigned integer. */
+typedef IntType<int32_t,  4> HBINT32;   /* 32-bit signed integer. */
+/* Note: we cannot defined a signed HBINT24 because there's no corresponding C type.
+ * Works for unsigned, but not signed, since we rely on compiler for sign-extension. */
+typedef IntType<uint32_t, 3> HBUINT24;  /* 24-bit unsigned integer. */
+
+/* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
+typedef HBINT16 FWORD;
+
+/* 32-bit signed integer (HBINT32) that describes a quantity in FUnits. */
+typedef HBINT32 FWORD32;
+
+/* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
+typedef HBUINT16 UFWORD;
+
+/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
+struct F2DOT14 : HBINT16
+{
+  // 16384 means 1<<14
+  float to_float () const  { return ((int32_t) v) / 16384.f; }
+  void set_float (float f) { v.set (round (f * 16384.f)); }
+  public:
+  DEFINE_SIZE_STATIC (2);
+};
+
+/* 32-bit signed fixed-point number (16.16). */
+struct Fixed : HBINT32
+{
+  // 65536 means 1<<16
+  float to_float () const  { return ((int32_t) v) / 65536.f; }
+  void set_float (float f) { v.set (round (f * 65536.f)); }
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+/* Date represented in number of seconds since 12:00 midnight, January 1,
+ * 1904. The value is represented as a signed 64-bit integer. */
+struct LONGDATETIME
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+  protected:
+  HBINT32 major;
+  HBUINT32 minor;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+/* Array of four uint8s (length = 32 bits) used to identify a script, language
+ * system, feature, or baseline */
+struct Tag : HBUINT32
+{
+  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
+  operator const char* () const { return reinterpret_cast<const char *> (&this->v); }
+  operator char* ()             { return reinterpret_cast<char *> (&this->v); }
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+/* Glyph index number, same as uint16 (length = 16 bits) */
+typedef HBUINT16 GlyphID;
+
+/* Script/language-system/feature index */
+struct Index : HBUINT16 {
+  static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFu;
+};
+DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
+
+typedef Index NameID;
+
+/* Offset, Null offset = 0 */
+template <typename Type, bool has_null=true>
+struct Offset : Type
+{
+  typedef Type type;
+
+  bool is_null () const { return has_null && 0 == *this; }
+
+  void *serialize (hb_serialize_context_t *c, const void *base)
+  {
+    void *t = c->start_embed<void> ();
+    this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
+    return t;
+  }
+
+  public:
+  DEFINE_SIZE_STATIC (sizeof (Type));
+};
+
+typedef Offset<HBUINT16> Offset16;
+typedef Offset<HBUINT32> Offset32;
+
+
+/* CheckSum */
+struct CheckSum : HBUINT32
+{
+  /* This is reference implementation from the spec. */
+  static uint32_t CalcTableChecksum (const HBUINT32 *Table, uint32_t Length)
+  {
+    uint32_t Sum = 0L;
+    assert (0 == (Length & 3));
+    const HBUINT32 *EndPtr = Table + Length / HBUINT32::static_size;
+
+    while (Table < EndPtr)
+      Sum += *Table++;
+    return Sum;
+  }
+
+  /* Note: data should be 4byte aligned and have 4byte padding at the end. */
+  void set_for_data (const void *data, unsigned int length)
+  { set (CalcTableChecksum ((const HBUINT32 *) data, length)); }
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+
+/*
+ * Version Numbers
+ */
+
+template <typename FixedType=HBUINT16>
+struct FixedVersion
+{
+  uint32_t to_int () const { return (major << (sizeof (FixedType) * 8)) + minor; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  FixedType major;
+  FixedType minor;
+  public:
+  DEFINE_SIZE_STATIC (2 * sizeof (FixedType));
+};
+
+
+/*
+ * Template subclasses of Offset that do the dereferencing.
+ * Use: (base+offset)
+ */
+
+template <typename Type, bool has_null>
+struct _hb_has_null
+{
+  static const Type *get_null () { return nullptr; }
+  static Type *get_crap ()       { return nullptr; }
+};
+template <typename Type>
+struct _hb_has_null<Type, true>
+{
+  static const Type *get_null () { return &Null(Type); }
+  static Type *get_crap ()       { return &Crap(Type); }
+};
+
+template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
+struct OffsetTo : Offset<OffsetType, has_null>
+{
+  const Type& operator () (const void *base) const
+  {
+    if (unlikely (this->is_null ())) return *_hb_has_null<Type, has_null>::get_null ();
+    return StructAtOffset<const Type> (base, *this);
+  }
+  Type& operator () (void *base) const
+  {
+    if (unlikely (this->is_null ())) return *_hb_has_null<Type, has_null>::get_crap ();
+    return StructAtOffset<Type> (base, *this);
+  }
+
+  Type& serialize (hb_serialize_context_t *c, const void *base)
+  {
+    return * (Type *) Offset<OffsetType>::serialize (c, base);
+  }
+
+  template <typename T>
+  void serialize_subset (hb_subset_context_t *c, const T &src, const void *base)
+  {
+    if (&src == &Null (T))
+    {
+      this->set (0);
+      return;
+    }
+    serialize (c->serializer, base);
+    if (!src.subset (c))
+      this->set (0);
+  }
+
+  bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this))) return_trace (false);
+    if (unlikely (this->is_null ())) return_trace (true);
+    if (unlikely (!c->check_range (base, *this))) return_trace (false);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (sanitize_shallow (c, base) &&
+                  (this->is_null () ||
+                   StructAtOffset<Type> (base, *this).sanitize (c) ||
+                   neuter (c)));
+  }
+  template <typename T1>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (sanitize_shallow (c, base) &&
+                  (this->is_null () ||
+                   StructAtOffset<Type> (base, *this).sanitize (c, d1) ||
+                   neuter (c)));
+  }
+  template <typename T1, typename T2>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (sanitize_shallow (c, base) &&
+                  (this->is_null () ||
+                   StructAtOffset<Type> (base, *this).sanitize (c, d1, d2) ||
+                   neuter (c)));
+  }
+  template <typename T1, typename T2, typename T3>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2, T3 d3) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (sanitize_shallow (c, base) &&
+                  (this->is_null () ||
+                   StructAtOffset<Type> (base, *this).sanitize (c, d1, d2, d3) ||
+                   neuter (c)));
+  }
+
+  /* Set the offset to Null */
+  bool neuter (hb_sanitize_context_t *c) const
+  {
+    if (!has_null) return false;
+    return c->try_set (this, 0);
+  }
+  DEFINE_SIZE_STATIC (sizeof (OffsetType));
+};
+/* Partial specializations. */
+template <typename Type,                               bool has_null=true> struct   LOffsetTo : OffsetTo<Type, HBUINT32,   has_null> {};
+template <typename Type, typename OffsetType=HBUINT16                    > struct  NNOffsetTo : OffsetTo<Type, OffsetType, false> {};
+template <typename Type                                                  > struct LNNOffsetTo : OffsetTo<Type, HBUINT32,   false> {};
+
+template <typename Base, typename OffsetType, bool has_null, typename Type>
+static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
+template <typename Base, typename OffsetType, bool has_null, typename Type>
+static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
+
+
+/*
+ * Array Types
+ */
+
+template <typename Type>
+struct UnsizedArrayOf
+{
+  typedef Type item_t;
+  static constexpr unsigned item_size = hb_static_size (Type);
+
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (UnsizedArrayOf, Type);
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    const Type *p = &arrayZ[i];
+    if (unlikely (p < arrayZ)) return Null (Type); /* Overflowed. */
+    return *p;
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    Type *p = &arrayZ[i];
+    if (unlikely (p < arrayZ)) return Crap (Type); /* Overflowed. */
+    return *p;
+  }
+
+  unsigned int get_size (unsigned int len) const
+  { return len * Type::static_size; }
+
+  template <typename T> operator T * () { return arrayZ; }
+  template <typename T> operator const T * () const { return arrayZ; }
+  hb_array_t<Type> as_array (unsigned int len)
+  { return hb_array (arrayZ, len); }
+  hb_array_t<const Type> as_array (unsigned int len) const
+  { return hb_array (arrayZ, len); }
+  operator hb_array_t<Type> ()             { return as_array (); }
+  operator hb_array_t<const Type> () const { return as_array (); }
+
+  template <typename T>
+  Type &lsearch (unsigned int len, const T &x, Type &not_found = Crap (Type))
+  { return *as_array (len).lsearch (x, &not_found); }
+  template <typename T>
+  const Type &lsearch (unsigned int len, const T &x, const Type &not_found = Null (Type)) const
+  { return *as_array (len).lsearch (x, &not_found); }
+
+  void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
+  { as_array (len).qsort (start, end); }
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
+
+    /* Note: for structs that do not reference other structs,
+     * we do not need to call their sanitize() as we already did
+     * a bound check on the aggregate array size.  We just include
+     * a small unreachable expression to make sure the structs
+     * pointed to do have a simple sanitize(), ie. they do not
+     * reference other structs via offsets.
+     */
+    (void) (false && arrayZ[0].sanitize (c));
+
+    return_trace (true);
+  }
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base)))
+        return_trace (false);
+    return_trace (true);
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
+        return_trace (false);
+    return_trace (true);
+  }
+
+  bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_array (arrayZ, count));
+  }
+
+  public:
+  Type          arrayZ[VAR];
+  public:
+  DEFINE_SIZE_UNBOUNDED (0);
+};
+
+/* Unsized array of offset's */
+template <typename Type, typename OffsetType, bool has_null=true>
+struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null> > {};
+
+/* Unsized array of offsets relative to the beginning of the array itself. */
+template <typename Type, typename OffsetType, bool has_null=true>
+struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
+{
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
+    if (unlikely (p < this->arrayZ)) return Null (Type); /* Overflowed. */
+    return this+*p;
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
+    if (unlikely (p < this->arrayZ)) return Crap (Type); /* Overflowed. */
+    return this+*p;
+  }
+
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>::sanitize (c, count, this)));
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>::sanitize (c, count, this, user_data)));
+  }
+};
+
+/* An array with sorted elements.  Supports binary searching. */
+template <typename Type>
+struct SortedUnsizedArrayOf : UnsizedArrayOf<Type>
+{
+  hb_sorted_array_t<Type> as_array (unsigned int len)
+  { return hb_sorted_array (this->arrayZ, len); }
+  hb_sorted_array_t<const Type> as_array (unsigned int len) const
+  { return hb_sorted_array (this->arrayZ, len); }
+  operator hb_sorted_array_t<Type> ()             { return as_array (); }
+  operator hb_sorted_array_t<const Type> () const { return as_array (); }
+
+  template <typename T>
+  Type &bsearch (unsigned int len, const T &x, Type &not_found = Crap (Type))
+  { return *as_array (len).bsearch (x, &not_found); }
+  template <typename T>
+  const Type &bsearch (unsigned int len, const T &x, const Type &not_found = Null (Type)) const
+  { return *as_array (len).bsearch (x, &not_found); }
+  template <typename T>
+  bool bfind (unsigned int len, 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
+  { return as_array (len).bfind (x, i, not_found, to_store); }
+};
+
+
+/* An array with a number of elements. */
+template <typename Type, typename LenType=HBUINT16>
+struct ArrayOf
+{
+  typedef Type item_t;
+  static constexpr unsigned item_size = hb_static_size (Type);
+
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOf, Type, LenType);
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= len)) return Null (Type);
+    return arrayZ[i];
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= len)) return Crap (Type);
+    return arrayZ[i];
+  }
+
+  unsigned int get_size () const
+  { return len.static_size + len * Type::static_size; }
+
+  hb_array_t<Type> as_array ()
+  { return hb_array (arrayZ, len); }
+  hb_array_t<const Type> as_array () const
+  { return hb_array (arrayZ, len); }
+  operator hb_array_t<Type> (void)             { return as_array (); }
+  operator hb_array_t<const Type> (void) const { return as_array (); }
+
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
+  { return as_array ().sub_array (start_offset, count);}
+
+  bool serialize (hb_serialize_context_t *c, unsigned int items_len)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    len.set (items_len); /* TODO(serialize) Overflow? */
+    if (unlikely (!c->extend (*this))) return_trace (false);
+    return_trace (true);
+  }
+  template <typename T>
+  bool serialize (hb_serialize_context_t *c, hb_array_t<const T> items)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!serialize (c, items.length))) return_trace (false);
+    for (unsigned int i = 0; i < items.length; i++)
+      hb_assign (arrayZ[i], items[i]);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+
+    /* Note: for structs that do not reference other structs,
+     * we do not need to call their sanitize() as we already did
+     * a bound check on the aggregate array size.  We just include
+     * a small unreachable expression to make sure the structs
+     * pointed to do have a simple sanitize(), ie. they do not
+     * reference other structs via offsets.
+     */
+    (void) (false && arrayZ[0].sanitize (c));
+
+    return_trace (true);
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base)))
+        return_trace (false);
+    return_trace (true);
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
+        return_trace (false);
+    return_trace (true);
+  }
+
+  template <typename T>
+  Type &lsearch (const T &x, Type &not_found = Crap (Type))
+  { return *as_array ().lsearch (x, &not_found); }
+  template <typename T>
+  const Type &lsearch (const T &x, const Type &not_found = Null (Type)) const
+  { return *as_array ().lsearch (x, &not_found); }
+
+  void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
+  { as_array ().qsort (start, end); }
+
+  bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (len.sanitize (c) && c->check_array (arrayZ, len));
+  }
+
+  public:
+  LenType       len;
+  Type          arrayZ[VAR];
+  public:
+  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
+};
+template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {};
+typedef ArrayOf<HBUINT8, HBUINT8> PString;
+
+/* Array of Offset's */
+template <typename Type>
+struct OffsetArrayOf : ArrayOf<OffsetTo<Type, HBUINT16> > {};
+template <typename Type>
+struct LOffsetArrayOf : ArrayOf<OffsetTo<Type, HBUINT32> > {};
+template <typename Type>
+struct LOffsetLArrayOf : ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32> {};
+
+/* Array of offsets relative to the beginning of the array itself. */
+template <typename Type>
+struct OffsetListOf : OffsetArrayOf<Type>
+{
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= this->len)) return Null (Type);
+    return this+this->arrayZ[i];
+  }
+  const Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= this->len)) return Crap (Type);
+    return this+this->arrayZ[i];
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct OffsetListOf<Type> *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    unsigned int count = this->len;
+    for (unsigned int i = 0; i < count; i++)
+      out->arrayZ[i].serialize_subset (c, (*this)[i], out);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (OffsetArrayOf<Type>::sanitize (c, this));
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data));
+  }
+};
+
+/* An array starting at second element. */
+template <typename Type, typename LenType=HBUINT16>
+struct HeadlessArrayOf
+{
+  static constexpr unsigned item_size = Type::static_size;
+
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (HeadlessArrayOf, Type, LenType);
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= lenP1 || !i)) return Null (Type);
+    return arrayZ[i-1];
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= lenP1 || !i)) return Crap (Type);
+    return arrayZ[i-1];
+  }
+  unsigned int get_size () const
+  { return lenP1.static_size + (lenP1 ? lenP1 - 1 : 0) * Type::static_size; }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const Type> items)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    lenP1.set (items.length + 1); /* TODO(serialize) Overflow? */
+    if (unlikely (!c->extend (*this))) return_trace (false);
+    for (unsigned int i = 0; i < items.length; i++)
+      arrayZ[i] = items[i];
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+
+    /* Note: for structs that do not reference other structs,
+     * we do not need to call their sanitize() as we already did
+     * a bound check on the aggregate array size.  We just include
+     * a small unreachable expression to make sure the structs
+     * pointed to do have a simple sanitize(), ie. they do not
+     * reference other structs via offsets.
+     */
+    (void) (false && arrayZ[0].sanitize (c));
+
+    return_trace (true);
+  }
+
+  private:
+  bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (lenP1.sanitize (c) &&
+                  (!lenP1 || c->check_array (arrayZ, lenP1 - 1)));
+  }
+
+  public:
+  LenType       lenP1;
+  Type          arrayZ[VAR];
+  public:
+  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
+};
+
+/* An array storing length-1. */
+template <typename Type, typename LenType=HBUINT16>
+struct ArrayOfM1
+{
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOfM1, Type, LenType);
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i > lenM1)) return Null (Type);
+    return arrayZ[i];
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i > lenM1)) return Crap (Type);
+    return arrayZ[i];
+  }
+  unsigned int get_size () const
+  { return lenM1.static_size + (lenM1 + 1) * Type::static_size; }
+
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = lenM1 + 1;
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
+        return_trace (false);
+    return_trace (true);
+  }
+
+  private:
+  bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (lenM1.sanitize (c) &&
+                  (c->check_array (arrayZ, lenM1 + 1)));
+  }
+
+  public:
+  LenType       lenM1;
+  Type          arrayZ[VAR];
+  public:
+  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
+};
+
+/* An array with sorted elements.  Supports binary searching. */
+template <typename Type, typename LenType=HBUINT16>
+struct SortedArrayOf : ArrayOf<Type, LenType>
+{
+  hb_sorted_array_t<Type> as_array ()
+  { return hb_sorted_array (this->arrayZ, this->len); }
+  hb_sorted_array_t<const Type> as_array () const
+  { return hb_sorted_array (this->arrayZ, this->len); }
+  operator hb_sorted_array_t<Type> ()             { return as_array (); }
+  operator hb_sorted_array_t<const Type> () const { return as_array (); }
+
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
+  { return as_array ().sub_array (start_offset, count);}
+
+  template <typename T>
+  Type &bsearch (const T &x, Type &not_found = Crap (Type))
+  { return *as_array ().bsearch (x, &not_found); }
+  template <typename T>
+  const Type &bsearch (const T &x, const Type &not_found = Null (Type)) const
+  { return *as_array ().bsearch (x, &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
+  { return as_array ().bfind (x, i, not_found, to_store); }
+};
+
+/*
+ * Binary-search arrays
+ */
+
+template <typename LenType=HBUINT16>
+struct BinSearchHeader
+{
+  operator uint32_t () const { return len; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  void set (unsigned int v)
+  {
+    len.set (v);
+    assert (len == v);
+    entrySelector.set (MAX (1u, hb_bit_storage (v)) - 1);
+    searchRange.set (16 * (1u << entrySelector));
+    rangeShift.set (v * 16 > searchRange
+                    ? 16 * v - searchRange
+                    : 0);
+  }
+
+  protected:
+  LenType       len;
+  LenType       searchRange;
+  LenType       entrySelector;
+  LenType       rangeShift;
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+template <typename Type, typename LenType=HBUINT16>
+struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader<LenType> > {};
+
+
+struct VarSizedBinSearchHeader
+{
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT16      unitSize;       /* Size of a lookup unit for this search in bytes. */
+  HBUINT16      nUnits;         /* Number of units of the preceding size to be searched. */
+  HBUINT16      searchRange;    /* The value of unitSize times the largest power of 2
+                                 * that is less than or equal to the value of nUnits. */
+  HBUINT16      entrySelector;  /* The log base 2 of the largest power of 2 less than
+                                 * or equal to the value of nUnits. */
+  HBUINT16      rangeShift;     /* The value of unitSize times the difference of the
+                                 * value of nUnits minus the largest power of 2 less
+                                 * than or equal to the value of nUnits. */
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+template <typename Type>
+struct VarSizedBinSearchArrayOf
+{
+  static constexpr unsigned item_size = Type::static_size;
+
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (VarSizedBinSearchArrayOf, Type);
+
+  bool last_is_terminator () const
+  {
+    if (unlikely (!header.nUnits)) return false;
+
+    /* Gah.
+     *
+     * "The number of termination values that need to be included is table-specific.
+     * The value that indicates binary search termination is 0xFFFF." */
+    const HBUINT16 *words = &StructAtOffset<HBUINT16> (&bytesZ, (header.nUnits - 1) * header.unitSize);
+    unsigned int count = Type::TerminationWordCount;
+    for (unsigned int i = 0; i < count; i++)
+      if (words[i] != 0xFFFFu)
+        return false;
+    return true;
+  }
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= get_length ())) return Null (Type);
+    return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= get_length ())) return Crap (Type);
+    return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
+  }
+  unsigned int get_length () const
+  { return header.nUnits - last_is_terminator (); }
+  unsigned int get_size () const
+  { return header.static_size + header.nUnits * header.unitSize; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+
+    /* Note: for structs that do not reference other structs,
+     * we do not need to call their sanitize() as we already did
+     * a bound check on the aggregate array size.  We just include
+     * a small unreachable expression to make sure the structs
+     * pointed to do have a simple sanitize(), ie. they do not
+     * reference other structs via offsets.
+     */
+    (void) (false && StructAtOffset<Type> (&bytesZ, 0).sanitize (c));
+
+    return_trace (true);
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = get_length ();
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!(*this)[i].sanitize (c, base)))
+        return_trace (false);
+    return_trace (true);
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = get_length ();
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!(*this)[i].sanitize (c, base, user_data)))
+        return_trace (false);
+    return_trace (true);
+  }
+
+  template <typename T>
+  const Type *bsearch (const T &key) const
+  {
+    unsigned int size = header.unitSize;
+    int min = 0, max = (int) get_length () - 1;
+    while (min <= max)
+    {
+      int mid = ((unsigned int) min + (unsigned int) max) / 2;
+      const Type *p = (const Type *) (((const char *) &bytesZ) + (mid * size));
+      int c = p->cmp (key);
+      if (c < 0) max = mid - 1;
+      else if (c > 0) min = mid + 1;
+      else return p;
+    }
+    return nullptr;
+  }
+
+  private:
+  bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (header.sanitize (c) &&
+                  Type::static_size <= header.unitSize &&
+                  c->check_range (bytesZ.arrayZ,
+                                  header.nUnits,
+                                  header.unitSize));
+  }
+
+  protected:
+  VarSizedBinSearchHeader       header;
+  UnsizedArrayOf<HBUINT8>       bytesZ;
+  public:
+  DEFINE_SIZE_ARRAY (10, bytesZ);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OPEN_TYPE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff-common.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,713 @@
+/*
+ * 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_OT_CFF_COMMON_HH
+#define HB_OT_CFF_COMMON_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-cff-interp-dict-common.hh"
+#include "hb-subset-plan.hh"
+
+namespace CFF {
+
+using namespace OT;
+
+#define CFF_UNDEF_CODE  0xFFFFFFFF
+
+/* utility macro */
+template<typename Type>
+static inline const Type& StructAtOffsetOrNull(const void *P, unsigned int offset)
+{ return offset? (* reinterpret_cast<const Type*> ((const char *) P + offset)): Null(Type); }
+
+inline unsigned int calcOffSize(unsigned int dataSize)
+{
+  unsigned int size = 1;
+  unsigned int offset = dataSize + 1;
+  while ((offset & ~0xFF) != 0)
+  {
+    size++;
+    offset >>= 8;
+  }
+  /* format does not support size > 4; caller should handle it as an error */
+  return size;
+}
+
+struct code_pair_t
+{
+  hb_codepoint_t  code;
+  hb_codepoint_t  glyph;
+};
+
+typedef hb_vector_t<unsigned char> str_buff_t;
+struct str_buff_vec_t : hb_vector_t<str_buff_t>
+{
+  void fini () { SUPER::fini_deep (); }
+
+  unsigned int total_size () const
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < length; i++)
+      size += (*this)[i].length;
+    return size;
+  }
+
+  private:
+  typedef hb_vector_t<str_buff_t> SUPER;
+};
+
+/* CFF INDEX */
+template <typename COUNT>
+struct CFFIndex
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */
+                          (c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
+                           c->check_array (offsets, offSize, count + 1) &&
+                           c->check_array ((const HBUINT8*)data_base (), 1, max_offset () - 1))));
+  }
+
+  static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count)
+  { return offSize * (count + 1); }
+
+  unsigned int offset_array_size () const
+  { return calculate_offset_array_size (offSize, count); }
+
+  static unsigned int calculate_serialized_size (unsigned int offSize, unsigned int count, unsigned int dataSize)
+  {
+    if (count == 0)
+      return COUNT::static_size;
+    else
+      return min_size + calculate_offset_array_size (offSize, count) + dataSize;
+  }
+
+  bool serialize (hb_serialize_context_t *c, const CFFIndex &src)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size ();
+    CFFIndex *dest = c->allocate_size<CFFIndex> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  unsigned int offSize_,
+                  const byte_str_array_t &byteArray)
+  {
+    TRACE_SERIALIZE (this);
+    if (byteArray.length == 0)
+    {
+      COUNT *dest = c->allocate_min<COUNT> ();
+      if (unlikely (dest == nullptr)) return_trace (false);
+      dest->set (0);
+    }
+    else
+    {
+      /* serialize CFFIndex header */
+      if (unlikely (!c->extend_min (*this))) return_trace (false);
+      this->count.set (byteArray.length);
+      this->offSize.set (offSize_);
+      if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
+        return_trace (false);
+
+      /* serialize indices */
+      unsigned int  offset = 1;
+      unsigned int  i = 0;
+      for (; i < byteArray.length; i++)
+      {
+        set_offset_at (i, offset);
+        offset += byteArray[i].get_size ();
+      }
+      set_offset_at (i, offset);
+
+      /* serialize data */
+      for (unsigned int i = 0; i < byteArray.length; i++)
+      {
+        const byte_str_t &bs = byteArray[i];
+        unsigned char  *dest = c->allocate_size<unsigned char> (bs.length);
+        if (unlikely (dest == nullptr))
+          return_trace (false);
+        memcpy (dest, &bs[0], bs.length);
+      }
+    }
+    return_trace (true);
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  unsigned int offSize_,
+                  const str_buff_vec_t &buffArray)
+  {
+    byte_str_array_t  byteArray;
+    byteArray.init ();
+    byteArray.resize (buffArray.length);
+    for (unsigned int i = 0; i < byteArray.length; i++)
+    {
+      byteArray[i] = byte_str_t (buffArray[i].arrayZ (), buffArray[i].length);
+    }
+    bool result = this->serialize (c, offSize_, byteArray);
+    byteArray.fini ();
+    return result;
+  }
+
+  void set_offset_at (unsigned int index, unsigned int offset)
+  {
+    HBUINT8 *p = offsets + offSize * index + offSize;
+    unsigned int size = offSize;
+    for (; size; size--)
+    {
+      --p;
+      p->set (offset & 0xFF);
+      offset >>= 8;
+    }
+  }
+
+  unsigned int offset_at (unsigned int index) const
+  {
+    assert (index <= count);
+    const HBUINT8 *p = offsets + offSize * index;
+    unsigned int size = offSize;
+    unsigned int offset = 0;
+    for (; size; size--)
+      offset = (offset << 8) + *p++;
+    return offset;
+  }
+
+  unsigned int length_at (unsigned int index) const
+  {
+        if (likely ((offset_at (index + 1) >= offset_at (index)) &&
+                    (offset_at (index + 1) <= offset_at (count))))
+          return offset_at (index + 1) - offset_at (index);
+        else
+          return 0;
+  }
+
+  const unsigned char *data_base () const
+  { return (const unsigned char *)this + min_size + offset_array_size (); }
+
+  unsigned int data_size () const { return HBINT8::static_size; }
+
+  byte_str_t operator [] (unsigned int index) const
+  {
+    if (likely (index < count))
+      return byte_str_t (data_base () + offset_at (index) - 1, length_at (index));
+    else
+      return Null(byte_str_t);
+  }
+
+  unsigned int get_size () const
+  {
+    if (this != &Null(CFFIndex))
+    {
+      if (count > 0)
+        return min_size + offset_array_size () + (offset_at (count) - 1);
+      else
+        return count.static_size;  /* empty CFFIndex contains count only */
+    }
+    else
+      return 0;
+  }
+
+  protected:
+  unsigned int max_offset () const
+  {
+    unsigned int max = 0;
+    for (unsigned int i = 0; i < count + 1u; i++)
+    {
+      unsigned int off = offset_at (i);
+      if (off > max) max = off;
+    }
+    return max;
+  }
+
+  public:
+  COUNT     count;      /* Number of object data. Note there are (count+1) offsets */
+  HBUINT8   offSize;      /* The byte size of each offset in the offsets array. */
+  HBUINT8   offsets[VAR]; /* The array of (count + 1) offsets into objects array (1-base). */
+  /* HBUINT8 data[VAR];      Object data */
+  public:
+  DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets);
+};
+
+template <typename COUNT, typename TYPE>
+struct CFFIndexOf : CFFIndex<COUNT>
+{
+  const byte_str_t operator [] (unsigned int index) const
+  {
+    if (likely (index < CFFIndex<COUNT>::count))
+      return byte_str_t (CFFIndex<COUNT>::data_base () + CFFIndex<COUNT>::offset_at (index) - 1, CFFIndex<COUNT>::length_at (index));
+    return Null(byte_str_t);
+  }
+
+  template <typename DATA, typename PARAM1, typename PARAM2>
+  bool serialize (hb_serialize_context_t *c,
+                  unsigned int offSize_,
+                  const DATA *dataArray,
+                  unsigned int dataArrayLen,
+                  const hb_vector_t<unsigned int> &dataSizeArray,
+                  const PARAM1 &param1,
+                  const PARAM2 &param2)
+  {
+    TRACE_SERIALIZE (this);
+    /* serialize CFFIndex header */
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    this->count.set (dataArrayLen);
+    this->offSize.set (offSize_);
+    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
+      return_trace (false);
+
+    /* serialize indices */
+    unsigned int  offset = 1;
+    unsigned int  i = 0;
+    for (; i < dataArrayLen; i++)
+    {
+      CFFIndex<COUNT>::set_offset_at (i, offset);
+      offset += dataSizeArray[i];
+    }
+    CFFIndex<COUNT>::set_offset_at (i, offset);
+
+    /* serialize data */
+    for (unsigned int i = 0; i < dataArrayLen; i++)
+    {
+      TYPE  *dest = c->start_embed<TYPE> ();
+      if (unlikely (dest == nullptr ||
+                    !dest->serialize (c, dataArray[i], param1, param2)))
+        return_trace (false);
+    }
+    return_trace (true);
+  }
+
+  /* in parallel to above */
+  template <typename DATA, typename PARAM>
+  static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
+                                                 const DATA *dataArray,
+                                                 unsigned int dataArrayLen,
+                                                 hb_vector_t<unsigned int> &dataSizeArray, /* OUT */
+                                                 const PARAM &param)
+  {
+    /* determine offset size */
+    unsigned int  totalDataSize = 0;
+    for (unsigned int i = 0; i < dataArrayLen; i++)
+    {
+      unsigned int dataSize = TYPE::calculate_serialized_size (dataArray[i], param);
+      dataSizeArray[i] = dataSize;
+      totalDataSize += dataSize;
+    }
+    offSize_ = calcOffSize (totalDataSize);
+
+    return CFFIndex<COUNT>::calculate_serialized_size (offSize_, dataArrayLen, totalDataSize);
+  }
+};
+
+/* Top Dict, Font Dict, Private Dict */
+struct Dict : UnsizedByteStr
+{
+  template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
+  bool serialize (hb_serialize_context_t *c,
+                  const DICTVAL &dictval,
+                  OP_SERIALIZER& opszr,
+                  PARAM& param)
+  {
+    TRACE_SERIALIZE (this);
+    for (unsigned int i = 0; i < dictval.get_count (); i++)
+    {
+      if (unlikely (!opszr.serialize (c, dictval[i], param)))
+        return_trace (false);
+    }
+    return_trace (true);
+  }
+
+  /* in parallel to above */
+  template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
+  static unsigned int calculate_serialized_size (const DICTVAL &dictval,
+                                                 OP_SERIALIZER& opszr,
+                                                 PARAM& param)
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < dictval.get_count (); i++)
+      size += opszr.calculate_serialized_size (dictval[i], param);
+    return size;
+  }
+
+  template <typename DICTVAL, typename OP_SERIALIZER>
+  static unsigned int calculate_serialized_size (const DICTVAL &dictval,
+                                                 OP_SERIALIZER& opszr)
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < dictval.get_count (); i++)
+      size += opszr.calculate_serialized_size (dictval[i]);
+    return size;
+  }
+
+  template <typename INTTYPE, int minVal, int maxVal>
+  static bool serialize_int_op (hb_serialize_context_t *c, op_code_t op, int value, op_code_t intOp)
+  {
+    // XXX: not sure why but LLVM fails to compile the following 'unlikely' macro invocation
+    if (/*unlikely*/ (!serialize_int<INTTYPE, minVal, maxVal> (c, intOp, value)))
+      return false;
+
+    TRACE_SERIALIZE (this);
+    /* serialize the opcode */
+    HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op));
+    if (unlikely (p == nullptr)) return_trace (false);
+    if (Is_OpCode_ESC (op))
+    {
+      p->set (OpCode_escape);
+      op = Unmake_OpCode_ESC (op);
+      p++;
+    }
+    p->set (op);
+    return_trace (true);
+  }
+
+  static bool serialize_uint4_op (hb_serialize_context_t *c, op_code_t op, int value)
+  { return serialize_int_op<HBUINT32, 0, 0x7FFFFFFF> (c, op, value, OpCode_longintdict); }
+
+  static bool serialize_uint2_op (hb_serialize_context_t *c, op_code_t op, int value)
+  { return serialize_int_op<HBUINT16, 0, 0x7FFF> (c, op, value, OpCode_shortint); }
+
+  static bool serialize_offset4_op (hb_serialize_context_t *c, op_code_t op, int value)
+  {
+    return serialize_uint4_op (c, op, value);
+  }
+
+  static bool serialize_offset2_op (hb_serialize_context_t *c, op_code_t op, int value)
+  {
+    return serialize_uint2_op (c, op, value);
+  }
+};
+
+struct TopDict : Dict {};
+struct FontDict : Dict {};
+struct PrivateDict : Dict {};
+
+struct table_info_t
+{
+  void init () { offSize = offset = size = 0; }
+
+  unsigned int    offset;
+  unsigned int    size;
+  unsigned int    offSize;
+};
+
+/* used to remap font index or SID from fullset to subset.
+ * set to CFF_UNDEF_CODE if excluded from subset */
+struct remap_t : hb_vector_t<hb_codepoint_t>
+{
+  void init () { SUPER::init (); }
+
+  void fini () { SUPER::fini (); }
+
+  bool reset (unsigned int size)
+  {
+    if (unlikely (!SUPER::resize (size)))
+      return false;
+    for (unsigned int i = 0; i < length; i++)
+      (*this)[i] = CFF_UNDEF_CODE;
+    count = 0;
+    return true;
+  }
+
+  bool identity (unsigned int size)
+  {
+    if (unlikely (!SUPER::resize (size)))
+      return false;
+    unsigned int i;
+    for (i = 0; i < length; i++)
+      (*this)[i] = i;
+    count = i;
+    return true;
+  }
+
+  bool excludes (hb_codepoint_t id) const
+  { return (id < length) && ((*this)[id] == CFF_UNDEF_CODE); }
+
+  bool includes (hb_codepoint_t id) const
+  { return !excludes (id); }
+
+  unsigned int add (unsigned int i)
+  {
+    if ((*this)[i] == CFF_UNDEF_CODE)
+      (*this)[i] = count++;
+    return (*this)[i];
+  }
+
+  hb_codepoint_t get_count () const { return count; }
+
+  protected:
+  hb_codepoint_t  count;
+
+  private:
+  typedef hb_vector_t<hb_codepoint_t> SUPER;
+};
+
+template <typename COUNT>
+struct FDArray : CFFIndexOf<COUNT, FontDict>
+{
+  /* used by CFF1 */
+  template <typename DICTVAL, typename OP_SERIALIZER>
+  bool serialize (hb_serialize_context_t *c,
+                  unsigned int offSize_,
+                  const hb_vector_t<DICTVAL> &fontDicts,
+                  OP_SERIALIZER& opszr)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    this->count.set (fontDicts.length);
+    this->offSize.set (offSize_);
+    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (fontDicts.length + 1))))
+      return_trace (false);
+
+    /* serialize font dict offsets */
+    unsigned int  offset = 1;
+    unsigned int fid = 0;
+    for (; fid < fontDicts.length; fid++)
+    {
+      CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
+      offset += FontDict::calculate_serialized_size (fontDicts[fid], opszr);
+    }
+    CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
+
+    /* serialize font dicts */
+    for (unsigned int i = 0; i < fontDicts.length; i++)
+    {
+      FontDict *dict = c->start_embed<FontDict> ();
+      if (unlikely (!dict->serialize (c, fontDicts[i], opszr, fontDicts[i])))
+        return_trace (false);
+    }
+    return_trace (true);
+  }
+
+  /* used by CFF2 */
+  template <typename DICTVAL, typename OP_SERIALIZER>
+  bool serialize (hb_serialize_context_t *c,
+                  unsigned int offSize_,
+                  const hb_vector_t<DICTVAL> &fontDicts,
+                  unsigned int fdCount,
+                  const remap_t &fdmap,
+                  OP_SERIALIZER& opszr,
+                  const hb_vector_t<table_info_t> &privateInfos)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    this->count.set (fdCount);
+    this->offSize.set (offSize_);
+    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (fdCount + 1))))
+      return_trace (false);
+
+    /* serialize font dict offsets */
+    unsigned int  offset = 1;
+    unsigned int  fid = 0;
+    for (unsigned i = 0; i < fontDicts.length; i++)
+      if (fdmap.includes (i))
+      {
+        CFFIndexOf<COUNT, FontDict>::set_offset_at (fid++, offset);
+        offset += FontDict::calculate_serialized_size (fontDicts[i], opszr);
+      }
+    CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
+
+    /* serialize font dicts */
+    for (unsigned int i = 0; i < fontDicts.length; i++)
+      if (fdmap.includes (i))
+      {
+        FontDict *dict = c->start_embed<FontDict> ();
+        if (unlikely (!dict->serialize (c, fontDicts[i], opszr, privateInfos[fdmap[i]])))
+          return_trace (false);
+      }
+    return_trace (true);
+  }
+
+  /* in parallel to above */
+  template <typename OP_SERIALIZER, typename DICTVAL>
+  static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
+                                                 const hb_vector_t<DICTVAL> &fontDicts,
+                                                 unsigned int fdCount,
+                                                 const remap_t &fdmap,
+                                                 OP_SERIALIZER& opszr)
+  {
+    unsigned int dictsSize = 0;
+    for (unsigned int i = 0; i < fontDicts.len; i++)
+      if (fdmap.includes (i))
+        dictsSize += FontDict::calculate_serialized_size (fontDicts[i], opszr);
+
+    offSize_ = calcOffSize (dictsSize);
+    return CFFIndex<COUNT>::calculate_serialized_size (offSize_, fdCount, dictsSize);
+  }
+};
+
+/* FDSelect */
+struct FDSelect0 {
+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!(c->check_struct (this))))
+      return_trace (false);
+    for (unsigned int i = 0; i < c->get_num_glyphs (); i++)
+      if (unlikely (!fds[i].sanitize (c)))
+        return_trace (false);
+
+    return_trace (true);
+  }
+
+  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+  {
+    return (hb_codepoint_t)fds[glyph];
+  }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  { return HBUINT8::static_size * num_glyphs; }
+
+  HBUINT8     fds[VAR];
+
+  DEFINE_SIZE_MIN (1);
+};
+
+template <typename GID_TYPE, typename FD_TYPE>
+struct FDSelect3_4_Range {
+  bool sanitize (hb_sanitize_context_t *c, const void */*nullptr*/, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (first < c->get_num_glyphs () && (fd < fdcount));
+  }
+
+  GID_TYPE    first;
+  FD_TYPE     fd;
+
+  DEFINE_SIZE_STATIC (GID_TYPE::static_size + FD_TYPE::static_size);
+};
+
+template <typename GID_TYPE, typename FD_TYPE>
+struct FDSelect3_4 {
+  unsigned int get_size () const
+  { return GID_TYPE::static_size * 2 + ranges.get_size (); }
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this) || !ranges.sanitize (c, nullptr, fdcount) ||
+                  (nRanges () == 0) || ranges[0].first != 0))
+      return_trace (false);
+
+    for (unsigned int i = 1; i < nRanges (); i++)
+    {
+      if (unlikely (ranges[i - 1].first >= ranges[i].first))
+          return_trace (false);
+    }
+
+    if (unlikely (!sentinel().sanitize (c) || (sentinel() != c->get_num_glyphs ())))
+      return_trace (false);
+
+    return_trace (true);
+  }
+
+  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+  {
+    unsigned int i;
+    for (i = 1; i < nRanges (); i++)
+      if (glyph < ranges[i].first)
+        break;
+
+    return (hb_codepoint_t)ranges[i - 1].fd;
+  }
+
+  GID_TYPE &nRanges () { return ranges.len; }
+  GID_TYPE nRanges () const { return ranges.len; }
+  GID_TYPE &sentinel ()  { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); }
+  const GID_TYPE &sentinel () const  { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); }
+
+  ArrayOf<FDSelect3_4_Range<GID_TYPE, FD_TYPE>, GID_TYPE> ranges;
+  /* GID_TYPE sentinel */
+
+  DEFINE_SIZE_ARRAY (GID_TYPE::static_size, ranges);
+};
+
+typedef FDSelect3_4<HBUINT16, HBUINT8> FDSelect3;
+typedef FDSelect3_4_Range<HBUINT16, HBUINT8> FDSelect3_Range;
+
+struct FDSelect {
+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+
+    return_trace (likely (c->check_struct (this) && (format == 0 || format == 3) &&
+                          (format == 0)?
+                          u.format0.sanitize (c, fdcount):
+                          u.format3.sanitize (c, fdcount)));
+  }
+
+  bool serialize (hb_serialize_context_t *c, const FDSelect &src, unsigned int num_glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size (num_glyphs);
+    FDSelect *dest = c->allocate_size<FDSelect> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  unsigned int calculate_serialized_size (unsigned int num_glyphs) const
+  { return get_size (num_glyphs); }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    unsigned int size = format.static_size;
+    if (format == 0)
+      size += u.format0.get_size (num_glyphs);
+    else
+      size += u.format3.get_size ();
+    return size;
+  }
+
+  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+  {
+    if (this == &Null(FDSelect))
+      return 0;
+    if (format == 0)
+      return u.format0.get_fd (glyph);
+    else
+      return u.format3.get_fd (glyph);
+  }
+
+  HBUINT8       format;
+  union {
+    FDSelect0   format0;
+    FDSelect3   format3;
+  } u;
+
+  DEFINE_SIZE_MIN (1);
+};
+
+template <typename COUNT>
+struct Subrs : CFFIndex<COUNT>
+{
+  typedef COUNT count_type;
+  typedef CFFIndex<COUNT> SUPER;
+};
+
+} /* namespace CFF */
+
+#endif /* HB_OT_CFF_COMMON_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff1-table.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,385 @@
+/*
+ * 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
+ */
+
+#include "hb-ot-cff1-table.hh"
+#include "hb-cff1-interp-cs.hh"
+
+using namespace CFF;
+
+/* SID to code */
+static const uint8_t standard_encoding_to_code [] =
+{
+    0,   32,   33,   34,   35,   36,   37,   38,  39,   40,   41,   42,   43,   44,   45,   46,
+   47,   48,   49,   50,   51,   52,   53,   54,  55,   56,   57,   58,   59,   60,   61,   62,
+   63,   64,   65,   66,   67,   68,   69,   70,  71,   72,   73,   74,   75,   76,   77,   78,
+   79,   80,   81,   82,   83,   84,   85,   86,  87,   88,   89,   90,   91,   92,   93,   94,
+   95,   96,   97,   98,   99,  100,  101,  102, 103,  104,  105,  106,  107,  108,  109,  110,
+  111,  112,  113,  114,  115,  116,  117,  118, 119,  120,  121,  122,  123,  124,  125,  126,
+  161,  162,  163,  164,  165,  166,  167,  168, 169,  170,  171,  172,  173,  174,  175,  177,
+  178,  179,  180,  182,  183,  184,  185,  186, 187,  188,  189,  191,  193,  194,  195,  196,
+  197,  198,  199,  200,  202,  203,  205,  206, 207,  208,  225,  227,  232,  233,  234,  235,
+  241,  245,  248,  249,  250,  251
+};
+
+/* SID to code */
+static const uint8_t expert_encoding_to_code [] =
+{
+    0,   32,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   44,   45,   46,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   58,   59,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,   47,    0,    0,    0,    0,    0,    0,    0,    0,    0,   87,   88,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,  201,    0,    0,    0,    0,  189,    0,    0,  188,    0,
+    0,    0,    0,  190,  202,    0,    0,    0,    0,  203,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,   33,   34,   36,   37,   38,   39,   40,   41,   42,   43,   48,
+   49,   50,   51,   52,   53,   54,   55,   56,   57,   60,   61,   62,   63,   65,   66,   67,
+   68,   69,   73,   76,   77,   78,   79,   82,   83,   84,   86,   89,   90,   91,   93,   94,
+   95,   96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,  110,
+  111,  112,  113,  114,  115,  116,  117,  118,  119,  120,  121,  122,  123,  124,  125,  126,
+  161,  162,  163,  166,  167,  168,  169,  170,  172,  175,  178,  179,  182,  183,  184,  191,
+  192,  193,  194,  195,  196,  197,  200,  204,  205,  206,  207,  208,  209,  210,  211,  212,
+  213,  214,  215,  216,  217,  218,  219,  220,  221,  222,  223,  224,  225,  226,  227,  228,
+  229,  230,  231,  232,  233,  234,  235,  236,  237,  238,  239,  240,  241,  242,  243,  244,
+  245,  246,  247,  248,  249,  250,  251,  252,  253,  254,  255
+};
+
+/* glyph ID to SID */
+static const uint16_t expert_charset_to_sid [] =
+{
+    0,    1,  229,  230,  231,  232,  233,  234,  235,  236,  237,  238,   13,   14,   15,   99,
+  239,  240,  241,  242,  243,  244,  245,  246,  247,  248,   27,   28,  249,  250,  251,  252,
+  253,  254,  255,  256,  257,  258,  259,  260,  261,  262,  263,  264,  265,  266,  109,  110,
+  267,  268,  269,  270,  271,  272,  273,  274,  275,  276,  277,  278,  279,  280,  281,  282,
+  283,  284,  285,  286,  287,  288,  289,  290,  291,  292,  293,  294,  295,  296,  297,  298,
+  299,  300,  301,  302,  303,  304,  305,  306,  307,  308,  309,  310,  311,  312,  313,  314,
+  315,  316,  317,  318,  158,  155,  163,  319,  320,  321,  322,  323,  324,  325,  326,  150,
+  164,  169,  327,  328,  329,  330,  331,  332,  333,  334,  335,  336,  337,  338,  339,  340,
+  341,  342,  343,  344,  345,  346,  347,  348,  349,  350,  351,  352,  353,  354,  355,  356,
+  357,  358,  359,  360,  361,  362,  363,  364,  365,  366,  367,  368,  369,  370,  371,  372,
+  373,  374,  375,  376,  377,  378
+};
+
+/* glyph ID to SID */
+static const uint16_t expert_subset_charset_to_sid [] =
+{
+    0,    1,  231,  232,  235,  236,  237,  238,   13,   14,   15,   99,  239,  240,  241,  242,
+  243,  244,  245,  246,  247,  248,   27,   28,  249,  250,  251,  253,  254,  255,  256,  257,
+  258,  259,  260,  261,  262,  263,  264,  265,  266,  109,  110,  267,  268,  269,  270,  272,
+  300,  301,  302,  305,  314,  315,  158,  155,  163,  320,  321,  322,  323,  324,  325,  326,
+  150,  164,  169,  327,  328,  329,  330,  331,  332,  333,  334,  335,  336,  337,  338,  339,
+  340,  341,  342,  343,  344,  345,  346
+};
+
+/* code to SID */
+static const uint8_t standard_encoding_to_sid [] =
+{
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,
+    17,  18,   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,
+    33,  34,   35,   36,   37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,   48,
+    49,  50,   51,   52,   53,   54,   55,   56,   57,   58,   59,   60,   61,   62,   63,   64,
+    65,  66,   67,   68,   69,   70,   71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
+    81,  82,   83,   84,   85,   86,   87,   88,   89,   90,   91,   92,   93,   94,   95,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,  110,
+    0,  111,  112,  113,  114,    0,  115,  116,  117,  118,  119,  120,  121,  122,    0,  123,
+    0,  124,  125,  126,  127,  128,  129,  130,  131,    0,  132,  133,    0,  134,  135,  136,
+  137,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   138,   0,  139,    0,    0,    0,    0,  140,  141,  142,  143,    0,    0,    0,    0,
+    0,   144,   0,    0,    0,  145,    0,    0,  146,  147,  148,  149,    0,    0,    0,    0
+};
+
+hb_codepoint_t OT::cff1::lookup_standard_encoding_for_code (hb_codepoint_t sid)
+{
+  if (sid < ARRAY_LENGTH (standard_encoding_to_code))
+    return (hb_codepoint_t)standard_encoding_to_code[sid];
+  else
+    return 0;
+}
+
+hb_codepoint_t OT::cff1::lookup_expert_encoding_for_code (hb_codepoint_t sid)
+{
+  if (sid < ARRAY_LENGTH (expert_encoding_to_code))
+    return (hb_codepoint_t)expert_encoding_to_code[sid];
+  else
+    return 0;
+}
+
+hb_codepoint_t OT::cff1::lookup_expert_charset_for_sid (hb_codepoint_t glyph)
+{
+  if (glyph < ARRAY_LENGTH (expert_charset_to_sid))
+    return (hb_codepoint_t)expert_charset_to_sid[glyph];
+  else
+    return 0;
+}
+
+hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph)
+{
+  if (glyph < ARRAY_LENGTH (expert_subset_charset_to_sid))
+    return (hb_codepoint_t)expert_subset_charset_to_sid[glyph];
+  else
+    return 0;
+}
+
+hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code)
+{
+  if (code < ARRAY_LENGTH (standard_encoding_to_sid))
+    return (hb_codepoint_t)standard_encoding_to_sid[code];
+  else
+    return CFF_UNDEF_SID;
+}
+
+struct bounds_t
+{
+  void init ()
+  {
+    min.set_int (0x7FFFFFFF, 0x7FFFFFFF);
+    max.set_int (-0x80000000, -0x80000000);
+  }
+
+  void update (const point_t &pt)
+  {
+    if (pt.x < min.x) min.x = pt.x;
+    if (pt.x > max.x) max.x = pt.x;
+    if (pt.y < min.y) min.y = pt.y;
+    if (pt.y > max.y) max.y = pt.y;
+  }
+
+  void merge (const bounds_t &b)
+  {
+    if (empty ())
+      *this = b;
+    else if (!b.empty ())
+    {
+      if (b.min.x < min.x) min.x = b.min.x;
+      if (b.max.x > max.x) max.x = b.max.x;
+      if (b.min.y < min.y) min.y = b.min.y;
+      if (b.max.y > max.y) max.y = b.max.y;
+    }
+  }
+
+  void offset (const point_t &delta)
+  {
+    if (!empty ())
+    {
+      min.move (delta);
+      max.move (delta);
+    }
+  }
+
+  bool empty () const
+  { return (min.x >= max.x) || (min.y >= max.y); }
+
+  point_t min;
+  point_t max;
+};
+
+struct extents_param_t
+{
+  void init (const OT::cff1::accelerator_t *_cff)
+  {
+    path_open = false;
+    cff = _cff;
+    bounds.init ();
+  }
+
+  void start_path ()         { path_open = true; }
+  void end_path ()           { path_open = false; }
+  bool is_path_open () const { return path_open; }
+
+  bool    path_open;
+  bounds_t  bounds;
+
+  const OT::cff1::accelerator_t *cff;
+};
+
+struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, extents_param_t>
+{
+  static void moveto (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt)
+  {
+    param.end_path ();
+    env.moveto (pt);
+  }
+
+  static void line (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1)
+  {
+    if (!param.is_path_open ())
+    {
+      param.start_path ();
+      param.bounds.update (env.get_pt ());
+    }
+    env.moveto (pt1);
+    param.bounds.update (env.get_pt ());
+  }
+
+  static void curve (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+  {
+    if (!param.is_path_open ())
+    {
+      param.start_path ();
+      param.bounds.update (env.get_pt ());
+    }
+    /* include control points */
+    param.bounds.update (pt1);
+    param.bounds.update (pt2);
+    env.moveto (pt3);
+    param.bounds.update (env.get_pt ());
+  }
+};
+
+static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac=false);
+
+struct cff1_cs_opset_extents_t : cff1_cs_opset_t<cff1_cs_opset_extents_t, extents_param_t, cff1_path_procs_extents_t>
+{
+  static void process_seac (cff1_cs_interp_env_t &env, extents_param_t& param)
+  {
+    unsigned int  n = env.argStack.get_count ();
+    point_t delta;
+    delta.x = env.argStack[n-4];
+    delta.y = env.argStack[n-3];
+    hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
+    hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
+
+    bounds_t  base_bounds, accent_bounds;
+    if (likely (!env.in_seac && base && accent
+               && _get_bounds (param.cff, base, base_bounds, true)
+               && _get_bounds (param.cff, accent, accent_bounds, true)))
+    {
+      param.bounds.merge (base_bounds);
+      accent_bounds.offset (delta);
+      param.bounds.merge (accent_bounds);
+    }
+    else
+      env.set_error ();
+  }
+};
+
+bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac)
+{
+  bounds.init ();
+  if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
+
+  unsigned int fd = cff->fdSelect->get_fd (glyph);
+  cff1_cs_interpreter_t<cff1_cs_opset_extents_t, extents_param_t> interp;
+  const byte_str_t str = (*cff->charStrings)[glyph];
+  interp.env.init (str, *cff, fd);
+  interp.env.set_in_seac (in_seac);
+  extents_param_t  param;
+  param.init (cff);
+  if (unlikely (!interp.interpret (param))) return false;
+  bounds = param.bounds;
+  return true;
+}
+
+bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+{
+  bounds_t  bounds;
+
+  if (!_get_bounds (this, glyph, bounds))
+    return false;
+
+  if (bounds.min.x >= bounds.max.x)
+  {
+    extents->width = 0;
+    extents->x_bearing = 0;
+  }
+  else
+  {
+    extents->x_bearing = (int32_t)bounds.min.x.floor ();
+    extents->width = (int32_t)bounds.max.x.ceil () - extents->x_bearing;
+  }
+  if (bounds.min.y >= bounds.max.y)
+  {
+    extents->height = 0;
+    extents->y_bearing = 0;
+  }
+  else
+  {
+    extents->y_bearing = (int32_t)bounds.max.y.ceil ();
+    extents->height = (int32_t)bounds.min.y.floor () - extents->y_bearing;
+  }
+
+  return true;
+}
+
+struct get_seac_param_t
+{
+  void init (const OT::cff1::accelerator_t *_cff)
+  {
+    cff = _cff;
+    base = 0;
+    accent = 0;
+  }
+
+  bool has_seac () const { return base && accent; }
+
+  const OT::cff1::accelerator_t *cff;
+  hb_codepoint_t  base;
+  hb_codepoint_t  accent;
+};
+
+struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t>
+{
+  static void process_seac (cff1_cs_interp_env_t &env, get_seac_param_t& param)
+  {
+    unsigned int  n = env.argStack.get_count ();
+    hb_codepoint_t  base_char = (hb_codepoint_t)env.argStack[n-2].to_int ();
+    hb_codepoint_t  accent_char = (hb_codepoint_t)env.argStack[n-1].to_int ();
+
+    param.base = param.cff->std_code_to_glyph (base_char);
+    param.accent = param.cff->std_code_to_glyph (accent_char);
+  }
+};
+
+bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
+{
+  if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
+
+  unsigned int fd = fdSelect->get_fd (glyph);
+  cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp;
+  const byte_str_t str = (*charStrings)[glyph];
+  interp.env.init (str, *this, fd);
+  get_seac_param_t  param;
+  param.init (this);
+  if (unlikely (!interp.interpret (param))) return false;
+
+  if (param.has_seac ())
+  {
+    *base = param.base;
+    *accent = param.accent;
+    return true;
+  }
+  return false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff1-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,1299 @@
+/*
+ * 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_OT_CFF1_TABLE_HH
+#define HB_OT_CFF1_TABLE_HH
+
+#include "hb-ot-head-table.hh"
+#include "hb-ot-cff-common.hh"
+#include "hb-subset-cff1.hh"
+
+namespace CFF {
+
+/*
+ * CFF -- Compact Font Format (CFF)
+ * http://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
+ */
+#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ')
+
+#define CFF_UNDEF_SID   CFF_UNDEF_CODE
+
+enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
+enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
+
+typedef CFFIndex<HBUINT16>  CFF1Index;
+template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {};
+
+typedef CFFIndex<HBUINT16> CFF1Index;
+typedef CFF1Index          CFF1CharStrings;
+typedef FDArray<HBUINT16>  CFF1FDArray;
+typedef Subrs<HBUINT16>    CFF1Subrs;
+
+struct CFF1FDSelect : FDSelect {};
+
+/* Encoding */
+struct Encoding0 {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && codes[nCodes - 1].sanitize (c));
+  }
+
+  hb_codepoint_t get_code (hb_codepoint_t glyph) const
+  {
+    assert (glyph > 0);
+    glyph--;
+    if (glyph < nCodes)
+    {
+      return (hb_codepoint_t)codes[glyph];
+    }
+    else
+      return CFF_UNDEF_CODE;
+  }
+
+  unsigned int get_size () const
+  { return HBUINT8::static_size * (nCodes + 1); }
+
+  HBUINT8     nCodes;
+  HBUINT8     codes[VAR];
+
+  DEFINE_SIZE_ARRAY(1, codes);
+};
+
+struct Encoding1_Range {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT8   first;
+  HBUINT8   nLeft;
+
+  DEFINE_SIZE_STATIC (2);
+};
+
+struct Encoding1 {
+  unsigned int get_size () const
+  { return HBUINT8::static_size + Encoding1_Range::static_size * nRanges; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && ((nRanges == 0) || (ranges[nRanges - 1]).sanitize (c)));
+  }
+
+  hb_codepoint_t get_code (hb_codepoint_t glyph) const
+  {
+    assert (glyph > 0);
+    glyph--;
+    for (unsigned int i = 0; i < nRanges; i++)
+    {
+      if (glyph <= ranges[i].nLeft)
+      {
+        return (hb_codepoint_t)ranges[i].first + glyph;
+      }
+      glyph -= (ranges[i].nLeft + 1);
+    }
+    return CFF_UNDEF_CODE;
+  }
+
+  HBUINT8          nRanges;
+  Encoding1_Range   ranges[VAR];
+
+  DEFINE_SIZE_ARRAY (1, ranges);
+};
+
+struct SuppEncoding {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT8   code;
+  HBUINT16  glyph;
+
+  DEFINE_SIZE_STATIC (3);
+};
+
+struct CFF1SuppEncData {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && ((nSups == 0) || (supps[nSups - 1]).sanitize (c)));
+  }
+
+  void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
+  {
+    for (unsigned int i = 0; i < nSups; i++)
+      if (sid == supps[i].glyph)
+        codes.push (supps[i].code);
+  }
+
+  unsigned int get_size () const
+  { return HBUINT8::static_size + SuppEncoding::static_size * nSups; }
+
+  HBUINT8        nSups;
+  SuppEncoding   supps[VAR];
+
+  DEFINE_SIZE_ARRAY (1, supps);
+};
+
+struct Encoding {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+    unsigned int fmt = format & 0x7F;
+    if (unlikely (fmt > 1))
+      return_trace (false);
+    if (unlikely (!((fmt == 0)? u.format0.sanitize (c): u.format1.sanitize (c))))
+      return_trace (false);
+    return_trace (((format & 0x80) == 0) || suppEncData ().sanitize (c));
+  }
+
+  /* serialize a fullset Encoding */
+  bool serialize (hb_serialize_context_t *c, const Encoding &src)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size ();
+    Encoding *dest = c->allocate_size<Encoding> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  /* serialize a subset Encoding */
+  bool serialize (hb_serialize_context_t *c,
+                  uint8_t format,
+                  unsigned int enc_count,
+                  const hb_vector_t<code_pair_t>& code_ranges,
+                  const hb_vector_t<code_pair_t>& supp_codes)
+  {
+    TRACE_SERIALIZE (this);
+    Encoding *dest = c->extend_min (*this);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    dest->format.set (format | ((supp_codes.length > 0)? 0x80: 0));
+    if (format == 0)
+    {
+      Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
+    if (unlikely (fmt0 == nullptr)) return_trace (false);
+      fmt0->nCodes.set (enc_count);
+      unsigned int glyph = 0;
+      for (unsigned int i = 0; i < code_ranges.length; i++)
+      {
+        hb_codepoint_t code = code_ranges[i].code;
+        for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
+          fmt0->codes[glyph++].set (code++);
+        if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
+          return_trace (false);
+      }
+    }
+    else
+    {
+      Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
+      if (unlikely (fmt1 == nullptr)) return_trace (false);
+      fmt1->nRanges.set (code_ranges.length);
+      for (unsigned int i = 0; i < code_ranges.length; i++)
+      {
+        if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
+          return_trace (false);
+        fmt1->ranges[i].first.set (code_ranges[i].code);
+        fmt1->ranges[i].nLeft.set (code_ranges[i].glyph);
+      }
+    }
+    if (supp_codes.length > 0)
+    {
+      CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
+      if (unlikely (suppData == nullptr)) return_trace (false);
+      suppData->nSups.set (supp_codes.length);
+      for (unsigned int i = 0; i < supp_codes.length; i++)
+      {
+        suppData->supps[i].code.set (supp_codes[i].code);
+        suppData->supps[i].glyph.set (supp_codes[i].glyph); /* actually SID */
+      }
+    }
+    return_trace (true);
+  }
+
+  /* parallel to above: calculate the size of a subset Encoding */
+  static unsigned int calculate_serialized_size (uint8_t format,
+                                                 unsigned int enc_count,
+                                                 unsigned int supp_count)
+  {
+    unsigned int  size = min_size;
+    if (format == 0)
+      size += Encoding0::min_size + HBUINT8::static_size * enc_count;
+    else
+      size += Encoding1::min_size + Encoding1_Range::static_size * enc_count;
+    if (supp_count > 0)
+      size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count;
+    return size;
+  }
+
+  unsigned int get_size () const
+  {
+    unsigned int size = min_size;
+    if (table_format () == 0)
+      size += u.format0.get_size ();
+    else
+      size += u.format1.get_size ();
+    if (has_supplement ())
+      size += suppEncData ().get_size ();
+    return size;
+  }
+
+  hb_codepoint_t get_code (hb_codepoint_t glyph) const
+  {
+    if (table_format () == 0)
+      return u.format0.get_code (glyph);
+    else
+      return u.format1.get_code (glyph);
+  }
+
+  uint8_t table_format () const { return (format & 0x7F); }
+  bool  has_supplement () const { return (format & 0x80) != 0; }
+
+  void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
+  {
+    codes.resize (0);
+    if (has_supplement ())
+      suppEncData().get_codes (sid, codes);
+  }
+
+  protected:
+  const CFF1SuppEncData &suppEncData () const
+  {
+    if ((format & 0x7F) == 0)
+      return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes-1]);
+    else
+      return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges-1]);
+  }
+
+  public:
+  HBUINT8       format;
+
+  union {
+    Encoding0   format0;
+    Encoding1   format1;
+  } u;
+  /* CFF1SuppEncData  suppEncData; */
+
+  DEFINE_SIZE_MIN (1);
+};
+
+/* Charset */
+struct Charset0 {
+  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
+  }
+
+  hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+  {
+    if (glyph == 0)
+      return 0;
+    else
+      return sids[glyph - 1];
+  }
+
+  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
+  {
+    if (sid == 0)
+      return 0;
+
+    for (unsigned int glyph = 1; glyph < num_glyphs; glyph++)
+    {
+      if (sids[glyph-1] == sid)
+        return glyph;
+    }
+    return 0;
+  }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    assert (num_glyphs > 0);
+    return HBUINT16::static_size * (num_glyphs - 1);
+  }
+
+  HBUINT16  sids[VAR];
+
+  DEFINE_SIZE_ARRAY(0, sids);
+};
+
+template <typename TYPE>
+struct Charset_Range {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT16  first;
+  TYPE      nLeft;
+
+  DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size);
+};
+
+template <typename TYPE>
+struct Charset1_2 {
+  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+    num_glyphs--;
+    for (unsigned int i = 0; num_glyphs > 0; i++)
+    {
+      if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
+        return_trace (false);
+      num_glyphs -= (ranges[i].nLeft + 1);
+    }
+    return_trace (true);
+  }
+
+  hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+  {
+    if (glyph == 0) return 0;
+    glyph--;
+    for (unsigned int i = 0;; i++)
+    {
+      if (glyph <= ranges[i].nLeft)
+        return (hb_codepoint_t)ranges[i].first + glyph;
+      glyph -= (ranges[i].nLeft + 1);
+    }
+
+    return 0;
+  }
+
+  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
+  {
+    if (sid == 0) return 0;
+    hb_codepoint_t  glyph = 1;
+    for (unsigned int i = 0;; i++)
+    {
+      if (glyph >= num_glyphs)
+        return 0;
+      if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
+        return glyph + (sid - ranges[i].first);
+      glyph += (ranges[i].nLeft + 1);
+    }
+
+    return 0;
+  }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    unsigned int size = HBUINT8::static_size;
+    int glyph = (int)num_glyphs;
+
+    assert (glyph > 0);
+    glyph--;
+    for (unsigned int i = 0; glyph > 0; i++)
+    {
+      glyph -= (ranges[i].nLeft + 1);
+      size += Charset_Range<TYPE>::static_size;
+    }
+
+    return size;
+  }
+
+  Charset_Range<TYPE>   ranges[VAR];
+
+  DEFINE_SIZE_ARRAY (0, ranges);
+};
+
+typedef Charset1_2<HBUINT8>     Charset1;
+typedef Charset1_2<HBUINT16>    Charset2;
+typedef Charset_Range<HBUINT8>  Charset1_Range;
+typedef Charset_Range<HBUINT16> Charset2_Range;
+
+struct Charset {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+    if (format == 0)
+      return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
+    else if (format == 1)
+      return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
+    else if (likely (format == 2))
+      return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
+    else
+      return_trace (false);
+  }
+
+  /* serialize a fullset Charset */
+  bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size (num_glyphs);
+    Charset *dest = c->allocate_size<Charset> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  /* serialize a subset Charset */
+  bool serialize (hb_serialize_context_t *c,
+                  uint8_t format,
+                  unsigned int num_glyphs,
+                  const hb_vector_t<code_pair_t>& sid_ranges)
+  {
+    TRACE_SERIALIZE (this);
+    Charset *dest = c->extend_min (*this);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    dest->format.set (format);
+    if (format == 0)
+    {
+      Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
+    if (unlikely (fmt0 == nullptr)) return_trace (false);
+      unsigned int glyph = 0;
+      for (unsigned int i = 0; i < sid_ranges.length; i++)
+      {
+        hb_codepoint_t sid = sid_ranges[i].code;
+        for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
+          fmt0->sids[glyph++].set (sid++);
+      }
+    }
+    else if (format == 1)
+    {
+      Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
+      if (unlikely (fmt1 == nullptr)) return_trace (false);
+      for (unsigned int i = 0; i < sid_ranges.length; i++)
+      {
+        if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
+          return_trace (false);
+        fmt1->ranges[i].first.set (sid_ranges[i].code);
+        fmt1->ranges[i].nLeft.set (sid_ranges[i].glyph);
+      }
+    }
+    else /* format 2 */
+    {
+      Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
+      if (unlikely (fmt2 == nullptr)) return_trace (false);
+      for (unsigned int i = 0; i < sid_ranges.length; i++)
+      {
+        if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
+          return_trace (false);
+        fmt2->ranges[i].first.set (sid_ranges[i].code);
+        fmt2->ranges[i].nLeft.set (sid_ranges[i].glyph);
+      }
+    }
+    return_trace (true);
+  }
+
+  /* parallel to above: calculate the size of a subset Charset */
+  static unsigned int calculate_serialized_size (
+                        uint8_t format,
+                        unsigned int count)
+  {
+    unsigned int  size = min_size;
+    if (format == 0)
+      size += Charset0::min_size + HBUINT16::static_size * (count - 1);
+    else if (format == 1)
+      size += Charset1::min_size + Charset1_Range::static_size * count;
+    else
+      size += Charset2::min_size + Charset2_Range::static_size * count;
+
+    return size;
+  }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    unsigned int size = min_size;
+    if (format == 0)
+      size += u.format0.get_size (num_glyphs);
+    else if (format == 1)
+      size += u.format1.get_size (num_glyphs);
+    else
+      size += u.format2.get_size (num_glyphs);
+    return size;
+  }
+
+  hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+  {
+    if (format == 0)
+      return u.format0.get_sid (glyph);
+    else if (format == 1)
+      return u.format1.get_sid (glyph);
+    else
+      return u.format2.get_sid (glyph);
+  }
+
+  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
+  {
+    if (format == 0)
+      return u.format0.get_glyph (sid, num_glyphs);
+    else if (format == 1)
+      return u.format1.get_glyph (sid, num_glyphs);
+    else
+      return u.format2.get_glyph (sid, num_glyphs);
+  }
+
+  HBUINT8       format;
+  union {
+    Charset0    format0;
+    Charset1    format1;
+    Charset2    format2;
+  } u;
+
+  DEFINE_SIZE_MIN (1);
+};
+
+struct CFF1StringIndex : CFF1Index
+{
+  bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
+                  unsigned int offSize_, const remap_t &sidmap)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely ((strings.count == 0) || (sidmap.get_count () == 0)))
+    {
+      if (!unlikely (c->extend_min (this->count)))
+        return_trace (false);
+      count.set (0);
+      return_trace (true);
+    }
+
+    byte_str_array_t bytesArray;
+    bytesArray.init ();
+    if (!bytesArray.resize (sidmap.get_count ()))
+      return_trace (false);
+    for (unsigned int i = 0; i < strings.count; i++)
+    {
+      hb_codepoint_t  j = sidmap[i];
+      if (j != CFF_UNDEF_CODE)
+        bytesArray[j] = strings[i];
+    }
+
+    bool result = CFF1Index::serialize (c, offSize_, bytesArray);
+    bytesArray.fini ();
+    return_trace (result);
+  }
+
+  /* in parallel to above */
+  unsigned int calculate_serialized_size (unsigned int &offSize /*OUT*/, const remap_t &sidmap) const
+  {
+    offSize = 0;
+    if ((count == 0) || (sidmap.get_count () == 0))
+      return count.static_size;
+
+    unsigned int dataSize = 0;
+    for (unsigned int i = 0; i < count; i++)
+      if (sidmap[i] != CFF_UNDEF_CODE)
+        dataSize += length_at (i);
+
+    offSize = calcOffSize(dataSize);
+    return CFF1Index::calculate_serialized_size (offSize, sidmap.get_count (), dataSize);
+  }
+};
+
+struct cff1_top_dict_interp_env_t : num_interp_env_t
+{
+  cff1_top_dict_interp_env_t ()
+    : num_interp_env_t(), prev_offset(0), last_offset(0) {}
+
+  unsigned int prev_offset;
+  unsigned int last_offset;
+};
+
+struct name_dict_values_t
+{
+  enum name_dict_val_index_t
+  {
+      version,
+      notice,
+      copyright,
+      fullName,
+      familyName,
+      weight,
+      postscript,
+      fontName,
+      baseFontName,
+      registry,
+      ordering,
+
+      ValCount
+  };
+
+  void init ()
+  {
+    for (unsigned int i = 0; i < ValCount; i++)
+      values[i] = CFF_UNDEF_SID;
+  }
+
+  unsigned int& operator[] (unsigned int i)
+  { assert (i < ValCount); return values[i]; }
+
+  unsigned int operator[] (unsigned int i) const
+  { assert (i < ValCount); return values[i]; }
+
+  static enum name_dict_val_index_t name_op_to_index (op_code_t op)
+  {
+    switch (op) {
+      default: // can't happen - just make some compiler happy
+      case OpCode_version:
+        return version;
+      case OpCode_Notice:
+        return notice;
+      case OpCode_Copyright:
+        return copyright;
+      case OpCode_FullName:
+        return fullName;
+      case OpCode_FamilyName:
+        return familyName;
+      case OpCode_Weight:
+        return weight;
+      case OpCode_PostScript:
+        return postscript;
+      case OpCode_FontName:
+        return fontName;
+      case OpCode_BaseFontName:
+        return baseFontName;
+    }
+  }
+
+  unsigned int  values[ValCount];
+};
+
+struct cff1_top_dict_val_t : op_str_t
+{
+  unsigned int  last_arg_offset;
+};
+
+struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
+{
+  void init ()
+  {
+    top_dict_values_t<cff1_top_dict_val_t>::init ();
+
+    nameSIDs.init ();
+    ros_supplement = 0;
+    cidCount = 8720;
+    EncodingOffset = 0;
+    CharsetOffset = 0;
+    FDSelectOffset = 0;
+    privateDictInfo.init ();
+  }
+  void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); }
+
+  bool is_CID () const
+  { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; }
+
+  name_dict_values_t  nameSIDs;
+  unsigned int    ros_supplement_offset;
+  unsigned int    ros_supplement;
+  unsigned int    cidCount;
+
+  unsigned int    EncodingOffset;
+  unsigned int    CharsetOffset;
+  unsigned int    FDSelectOffset;
+  table_info_t       privateDictInfo;
+};
+
+struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
+{
+  static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval)
+  {
+    cff1_top_dict_val_t  val;
+    val.last_arg_offset = (env.last_offset-1) - dictval.opStart;  /* offset to the last argument */
+
+    switch (op) {
+      case OpCode_version:
+      case OpCode_Notice:
+      case OpCode_Copyright:
+      case OpCode_FullName:
+      case OpCode_FamilyName:
+      case OpCode_Weight:
+      case OpCode_PostScript:
+      case OpCode_BaseFontName:
+        dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+      case OpCode_isFixedPitch:
+      case OpCode_ItalicAngle:
+      case OpCode_UnderlinePosition:
+      case OpCode_UnderlineThickness:
+      case OpCode_PaintType:
+      case OpCode_CharstringType:
+      case OpCode_UniqueID:
+      case OpCode_StrokeWidth:
+      case OpCode_SyntheticBase:
+      case OpCode_CIDFontVersion:
+      case OpCode_CIDFontRevision:
+      case OpCode_CIDFontType:
+      case OpCode_UIDBase:
+      case OpCode_FontBBox:
+      case OpCode_XUID:
+      case OpCode_BaseFontBlend:
+        env.clear_args ();
+        break;
+
+      case OpCode_CIDCount:
+        dictval.cidCount = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      case OpCode_ROS:
+        dictval.ros_supplement = env.argStack.pop_uint ();
+        dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint ();
+        dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      case OpCode_Encoding:
+        dictval.EncodingOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        if (unlikely (dictval.EncodingOffset == 0)) return;
+        break;
+
+      case OpCode_charset:
+        dictval.CharsetOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        if (unlikely (dictval.CharsetOffset == 0)) return;
+        break;
+
+      case OpCode_FDSelect:
+        dictval.FDSelectOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      case OpCode_Private:
+        dictval.privateDictInfo.offset = env.argStack.pop_uint ();
+        dictval.privateDictInfo.size = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      default:
+        env.last_offset = env.str_ref.offset;
+        top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
+        /* Record this operand below if stack is empty, otherwise done */
+        if (!env.argStack.is_empty ()) return;
+        break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref, val);
+  }
+};
+
+struct cff1_font_dict_values_t : dict_values_t<op_str_t>
+{
+  void init ()
+  {
+    dict_values_t<op_str_t>::init ();
+    privateDictInfo.init ();
+    fontName = CFF_UNDEF_SID;
+  }
+  void fini () { dict_values_t<op_str_t>::fini (); }
+
+  table_info_t       privateDictInfo;
+  unsigned int    fontName;
+};
+
+struct cff1_font_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval)
+  {
+    switch (op) {
+      case OpCode_FontName:
+        dictval.fontName = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+      case OpCode_FontMatrix:
+      case OpCode_PaintType:
+        env.clear_args ();
+        break;
+      case OpCode_Private:
+        dictval.privateDictInfo.offset = env.argStack.pop_uint ();
+        dictval.privateDictInfo.size = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      default:
+        dict_opset_t::process_op (op, env);
+        if (!env.argStack.is_empty ()) return;
+        break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+};
+
+template <typename VAL>
+struct cff1_private_dict_values_base_t : dict_values_t<VAL>
+{
+  void init ()
+  {
+    dict_values_t<VAL>::init ();
+    subrsOffset = 0;
+    localSubrs = &Null(CFF1Subrs);
+  }
+  void fini () { dict_values_t<VAL>::fini (); }
+
+  unsigned int calculate_serialized_size () const
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < dict_values_t<VAL>::get_count; i++)
+      if (dict_values_t<VAL>::get_value (i).op == OpCode_Subrs)
+        size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
+      else
+        size += dict_values_t<VAL>::get_value (i).str.length;
+    return size;
+  }
+
+  unsigned int      subrsOffset;
+  const CFF1Subrs    *localSubrs;
+};
+
+typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
+typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;
+
+struct cff1_private_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval)
+  {
+    num_dict_val_t val;
+    val.init ();
+
+    switch (op) {
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+        env.clear_args ();
+        break;
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_ForceBold:
+      case OpCode_LanguageGroup:
+      case OpCode_ExpansionFactor:
+      case OpCode_initialRandomSeed:
+      case OpCode_defaultWidthX:
+      case OpCode_nominalWidthX:
+        val.single_val = env.argStack.pop_num ();
+        env.clear_args ();
+        break;
+      case OpCode_Subrs:
+        dictval.subrsOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      default:
+        dict_opset_t::process_op (op, env);
+        if (!env.argStack.is_empty ()) return;
+        break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref, val);
+  }
+};
+
+struct cff1_private_dict_opset_subset : dict_opset_t
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
+  {
+    switch (op) {
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_ForceBold:
+      case OpCode_LanguageGroup:
+      case OpCode_ExpansionFactor:
+      case OpCode_initialRandomSeed:
+      case OpCode_defaultWidthX:
+      case OpCode_nominalWidthX:
+        env.clear_args ();
+        break;
+
+      case OpCode_Subrs:
+        dictval.subrsOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      default:
+        dict_opset_t::process_op (op, env);
+        if (!env.argStack.is_empty ()) return;
+        break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+};
+
+typedef dict_interpreter_t<cff1_top_dict_opset_t, cff1_top_dict_values_t, cff1_top_dict_interp_env_t> cff1_top_dict_interpreter_t;
+typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
+
+typedef CFF1Index CFF1NameIndex;
+typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
+
+} /* namespace CFF */
+
+namespace OT {
+
+using namespace CFF;
+
+struct cff1
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  likely (version.major == 1));
+  }
+
+  template <typename PRIVOPSET, typename PRIVDICTVAL>
+  struct accelerator_templ_t
+  {
+    void init (hb_face_t *face)
+    {
+      topDict.init ();
+      fontDicts.init ();
+      privateDicts.init ();
+
+      this->blob = sc.reference_table<cff1> (face);
+
+      /* setup for run-time santization */
+      sc.init (this->blob);
+      sc.start_processing ();
+
+      const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
+
+      if (cff == &Null(OT::cff1))
+      { fini (); return; }
+
+      nameIndex = &cff->nameIndex (cff);
+      if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
+      { fini (); return; }
+
+      topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
+      if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
+      { fini (); return; }
+
+      { /* parse top dict */
+        const byte_str_t topDictStr = (*topDictIndex)[0];
+        if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
+        cff1_top_dict_interpreter_t top_interp;
+        top_interp.env.init (topDictStr);
+        topDict.init ();
+        if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
+      }
+
+      if (is_predef_charset ())
+        charset = &Null(Charset);
+      else
+      {
+        charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
+        if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
+      }
+
+      fdCount = 1;
+      if (is_CID ())
+      {
+        fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
+        fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
+        if (unlikely ((fdArray == &Null(CFF1FDArray)) || !fdArray->sanitize (&sc) ||
+            (fdSelect == &Null(CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
+        { fini (); return; }
+
+        fdCount = fdArray->count;
+      }
+      else
+      {
+        fdArray = &Null(CFF1FDArray);
+        fdSelect = &Null(CFF1FDSelect);
+      }
+
+      stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
+      if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
+      { fini (); return; }
+
+      globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
+      if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
+      { fini (); return; }
+
+      charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
+
+      if ((charStrings == &Null(CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
+      { fini (); return; }
+
+      num_glyphs = charStrings->count;
+      if (num_glyphs != sc.get_num_glyphs ())
+      { fini (); return; }
+
+      privateDicts.resize (fdCount);
+      for (unsigned int i = 0; i < fdCount; i++)
+        privateDicts[i].init ();
+
+      // parse CID font dicts and gather private dicts
+      if (is_CID ())
+      {
+        for (unsigned int i = 0; i < fdCount; i++)
+        {
+          byte_str_t fontDictStr = (*fdArray)[i];
+          if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
+          cff1_font_dict_values_t  *font;
+          cff1_font_dict_interpreter_t font_interp;
+          font_interp.env.init (fontDictStr);
+          font = fontDicts.push ();
+          if (unlikely (font == &Crap(cff1_font_dict_values_t))) { fini (); return; }
+          font->init ();
+          if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
+          PRIVDICTVAL  *priv = &privateDicts[i];
+          const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
+          if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
+          dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
+          priv_interp.env.init (privDictStr);
+          priv->init ();
+          if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
+
+          priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
+          if (priv->localSubrs != &Null(CFF1Subrs) &&
+              unlikely (!priv->localSubrs->sanitize (&sc)))
+          { fini (); return; }
+        }
+      }
+      else  /* non-CID */
+      {
+        cff1_top_dict_values_t  *font = &topDict;
+        PRIVDICTVAL  *priv = &privateDicts[0];
+
+        const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
+        if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
+        dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
+        priv_interp.env.init (privDictStr);
+        priv->init ();
+        if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
+
+        priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
+        if (priv->localSubrs != &Null(CFF1Subrs) &&
+            unlikely (!priv->localSubrs->sanitize (&sc)))
+        { fini (); return; }
+      }
+    }
+
+    void fini ()
+    {
+      sc.end_processing ();
+      topDict.fini ();
+      fontDicts.fini_deep ();
+      privateDicts.fini_deep ();
+      hb_blob_destroy (blob);
+      blob = nullptr;
+    }
+
+    bool is_valid () const { return blob != nullptr; }
+    bool is_CID () const { return topDict.is_CID (); }
+
+    bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
+
+    unsigned int std_code_to_glyph (hb_codepoint_t code) const
+    {
+      hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
+      if (unlikely (sid == CFF_UNDEF_SID))
+        return 0;
+
+      if (charset != &Null(Charset))
+        return charset->get_glyph (sid, num_glyphs);
+      else if ((topDict.CharsetOffset == ISOAdobeCharset)
+              && (code <= 228 /*zcaron*/)) return sid;
+      return 0;
+    }
+
+    protected:
+    hb_blob_t          *blob;
+    hb_sanitize_context_t   sc;
+
+    public:
+    const Charset          *charset;
+    const CFF1NameIndex     *nameIndex;
+    const CFF1TopDictIndex  *topDictIndex;
+    const CFF1StringIndex   *stringIndex;
+    const CFF1Subrs      *globalSubrs;
+    const CFF1CharStrings   *charStrings;
+    const CFF1FDArray       *fdArray;
+    const CFF1FDSelect      *fdSelect;
+    unsigned int            fdCount;
+
+    cff1_top_dict_values_t       topDict;
+    hb_vector_t<cff1_font_dict_values_t>   fontDicts;
+    hb_vector_t<PRIVDICTVAL>      privateDicts;
+
+    unsigned int            num_glyphs;
+  };
+
+  struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
+  {
+    HB_INTERNAL bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
+    HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
+  };
+
+  struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t>
+  {
+    void init (hb_face_t *face)
+    {
+      SUPER::init (face);
+      if (blob == nullptr) return;
+
+      const OT::cff1 *cff = this->blob->as<OT::cff1> ();
+      encoding = &Null(Encoding);
+      if (is_CID ())
+      {
+        if (unlikely (charset == &Null(Charset))) { fini (); return; }
+      }
+      else
+      {
+        if (!is_predef_encoding ())
+        {
+          encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
+          if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
+        }
+      }
+    }
+
+    bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
+
+    hb_codepoint_t  glyph_to_code (hb_codepoint_t glyph) const
+    {
+      if (encoding != &Null(Encoding))
+        return encoding->get_code (glyph);
+      else
+      {
+        hb_codepoint_t  sid = glyph_to_sid (glyph);
+        if (sid == 0) return 0;
+        hb_codepoint_t  code = 0;
+        switch (topDict.EncodingOffset)
+        {
+          case  StandardEncoding:
+            code = lookup_standard_encoding_for_code (sid);
+            break;
+          case  ExpertEncoding:
+            code = lookup_expert_encoding_for_code (sid);
+            break;
+          default:
+            break;
+        }
+        return code;
+      }
+    }
+
+    hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
+    {
+      if (charset != &Null(Charset))
+        return charset->get_sid (glyph);
+      else
+      {
+        hb_codepoint_t sid = 0;
+        switch (topDict.CharsetOffset)
+        {
+          case  ISOAdobeCharset:
+            if (glyph <= 228 /*zcaron*/) sid = glyph;
+            break;
+          case  ExpertCharset:
+            sid = lookup_expert_charset_for_sid (glyph);
+            break;
+          case  ExpertSubsetCharset:
+              sid = lookup_expert_subset_charset_for_sid (glyph);
+            break;
+          default:
+            break;
+        }
+        return sid;
+      }
+    }
+
+    const Encoding        *encoding;
+
+    private:
+    typedef accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> SUPER;
+  };
+
+  bool subset (hb_subset_plan_t *plan) const
+  {
+    hb_blob_t *cff_prime = nullptr;
+
+    bool success = true;
+    if (hb_subset_cff1 (plan, &cff_prime)) {
+      success = success && plan->add_table (HB_OT_TAG_cff1, cff_prime);
+      hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
+      success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
+      hb_blob_destroy (head_blob);
+    } else {
+      success = false;
+    }
+    hb_blob_destroy (cff_prime);
+
+    return success;
+  }
+
+  protected:
+  HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
+  HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
+  HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
+  HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
+  HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
+
+  public:
+  FixedVersion<HBUINT8> version;          /* Version of CFF table. set to 0x0100u */
+  OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
+  HBUINT8              offSize;   /* offset size (unused?) */
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct cff1_accelerator_t : cff1::accelerator_t {};
+} /* namespace OT */
+
+#endif /* HB_OT_CFF1_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff2-table.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,136 @@
+/*
+ * 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
+ */
+
+#include "hb-ot-cff2-table.hh"
+#include "hb-cff2-interp-cs.hh"
+
+using namespace CFF;
+
+struct extents_param_t
+{
+  void init ()
+  {
+    path_open = false;
+    min_x.set_int (0x7FFFFFFF);
+    min_y.set_int (0x7FFFFFFF);
+    max_x.set_int (-0x80000000);
+    max_y.set_int (-0x80000000);
+  }
+
+  void start_path ()         { path_open = true; }
+  void end_path ()           { path_open = false; }
+  bool is_path_open () const { return path_open; }
+
+  void update_bounds (const point_t &pt)
+  {
+    if (pt.x < min_x) min_x = pt.x;
+    if (pt.x > max_x) max_x = pt.x;
+    if (pt.y < min_y) min_y = pt.y;
+    if (pt.y > max_y) max_y = pt.y;
+  }
+
+  bool  path_open;
+  number_t min_x;
+  number_t min_y;
+  number_t max_x;
+  number_t max_y;
+};
+
+struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t, extents_param_t>
+{
+  static void moveto (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt)
+  {
+    param.end_path ();
+    env.moveto (pt);
+  }
+
+  static void line (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1)
+  {
+    if (!param.is_path_open ())
+    {
+      param.start_path ();
+      param.update_bounds (env.get_pt ());
+    }
+    env.moveto (pt1);
+    param.update_bounds (env.get_pt ());
+  }
+
+  static void curve (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+  {
+    if (!param.is_path_open ())
+    {
+      param.start_path ();
+      param.update_bounds (env.get_pt ());
+    }
+    /* include control points */
+    param.update_bounds (pt1);
+    param.update_bounds (pt2);
+    env.moveto (pt3);
+    param.update_bounds (env.get_pt ());
+  }
+};
+
+struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, extents_param_t, cff2_path_procs_extents_t> {};
+
+bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
+                                           hb_codepoint_t glyph,
+                                           hb_glyph_extents_t *extents) const
+{
+  if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
+
+  unsigned int num_coords;
+  const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
+  unsigned int fd = fdSelect->get_fd (glyph);
+  cff2_cs_interpreter_t<cff2_cs_opset_extents_t, extents_param_t> interp;
+  const byte_str_t str = (*charStrings)[glyph];
+  interp.env.init (str, *this, fd, coords, num_coords);
+  extents_param_t  param;
+  param.init ();
+  if (unlikely (!interp.interpret (param))) return false;
+
+  if (param.min_x >= param.max_x)
+  {
+    extents->width = 0;
+    extents->x_bearing = 0;
+  }
+  else
+  {
+    extents->x_bearing = (int32_t)param.min_x.floor ();
+    extents->width = (int32_t)param.max_x.ceil () - extents->x_bearing;
+  }
+  if (param.min_y >= param.max_y)
+  {
+    extents->height = 0;
+    extents->y_bearing = 0;
+  }
+  else
+  {
+    extents->y_bearing = (int32_t)param.max_y.ceil ();
+    extents->height = (int32_t)param.min_y.floor () - extents->y_bearing;
+  }
+
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff2-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,566 @@
+/*
+ * 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_OT_CFF2_TABLE_HH
+#define HB_OT_CFF2_TABLE_HH
+
+#include "hb-ot-head-table.hh"
+#include "hb-ot-cff-common.hh"
+#include "hb-subset-cff2.hh"
+
+namespace CFF {
+
+/*
+ * CFF2 -- Compact Font Format (CFF) Version 2
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/cff2
+ */
+#define HB_OT_TAG_cff2 HB_TAG('C','F','F','2')
+
+typedef CFFIndex<HBUINT32>  CFF2Index;
+template <typename Type> struct CFF2IndexOf : CFFIndexOf<HBUINT32, Type> {};
+
+typedef CFF2Index         CFF2CharStrings;
+typedef FDArray<HBUINT32> CFF2FDArray;
+typedef Subrs<HBUINT32>   CFF2Subrs;
+
+typedef FDSelect3_4<HBUINT32, HBUINT16> FDSelect4;
+typedef FDSelect3_4_Range<HBUINT32, HBUINT16> FDSelect4_Range;
+
+struct CFF2FDSelect
+{
+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+
+    return_trace (likely (c->check_struct (this) && (format == 0 || format == 3 || format == 4) &&
+                          (format == 0)?
+                          u.format0.sanitize (c, fdcount):
+                            ((format == 3)?
+                            u.format3.sanitize (c, fdcount):
+                            u.format4.sanitize (c, fdcount))));
+  }
+
+  bool serialize (hb_serialize_context_t *c, const CFF2FDSelect &src, unsigned int num_glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size (num_glyphs);
+    CFF2FDSelect *dest = c->allocate_size<CFF2FDSelect> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  unsigned int calculate_serialized_size (unsigned int num_glyphs) const
+  { return get_size (num_glyphs); }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    unsigned int size = format.static_size;
+    if (format == 0)
+      size += u.format0.get_size (num_glyphs);
+    else if (format == 3)
+      size += u.format3.get_size ();
+    else
+      size += u.format4.get_size ();
+    return size;
+  }
+
+  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+  {
+    if (this == &Null(CFF2FDSelect))
+      return 0;
+    if (format == 0)
+      return u.format0.get_fd (glyph);
+    else if (format == 3)
+      return u.format3.get_fd (glyph);
+    else
+      return u.format4.get_fd (glyph);
+  }
+
+  HBUINT8       format;
+  union {
+    FDSelect0   format0;
+    FDSelect3   format3;
+    FDSelect4   format4;
+  } u;
+
+  DEFINE_SIZE_MIN (2);
+};
+
+struct CFF2VariationStore
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)) && c->check_range (&varStore, size) && varStore.sanitize (c));
+  }
+
+  bool serialize (hb_serialize_context_t *c, const CFF2VariationStore *varStore)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size_ = varStore->get_size ();
+    CFF2VariationStore *dest = c->allocate_size<CFF2VariationStore> (size_);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, varStore, size_);
+    return_trace (true);
+  }
+
+  unsigned int get_size () const { return HBUINT16::static_size + size; }
+
+  HBUINT16      size;
+  VariationStore  varStore;
+
+  DEFINE_SIZE_MIN (2 + VariationStore::min_size);
+};
+
+struct cff2_top_dict_values_t : top_dict_values_t<>
+{
+  void init ()
+  {
+    top_dict_values_t<>::init ();
+    vstoreOffset = 0;
+    FDSelectOffset = 0;
+  }
+  void fini () { top_dict_values_t<>::fini (); }
+
+  unsigned int calculate_serialized_size () const
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < get_count (); i++)
+    {
+      op_code_t op = get_value (i).op;
+      switch (op)
+      {
+        case OpCode_vstore:
+        case OpCode_FDSelect:
+          size += OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
+          break;
+        default:
+          size += top_dict_values_t<>::calculate_serialized_op_size (get_value (i));
+          break;
+      }
+    }
+    return size;
+  }
+
+  unsigned int  vstoreOffset;
+  unsigned int  FDSelectOffset;
+};
+
+struct cff2_top_dict_opset_t : top_dict_opset_t<>
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff2_top_dict_values_t& dictval)
+  {
+    switch (op) {
+      case OpCode_FontMatrix:
+        {
+          dict_val_t val;
+          val.init ();
+          dictval.add_op (op, env.str_ref);
+          env.clear_args ();
+        }
+        break;
+
+      case OpCode_vstore:
+        dictval.vstoreOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+      case OpCode_FDSelect:
+        dictval.FDSelectOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      default:
+        SUPER::process_op (op, env, dictval);
+        /* Record this operand below if stack is empty, otherwise done */
+        if (!env.argStack.is_empty ()) return;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+
+  typedef top_dict_opset_t<> SUPER;
+};
+
+struct cff2_font_dict_values_t : dict_values_t<op_str_t>
+{
+  void init ()
+  {
+    dict_values_t<op_str_t>::init ();
+    privateDictInfo.init ();
+  }
+  void fini () { dict_values_t<op_str_t>::fini (); }
+
+  table_info_t    privateDictInfo;
+};
+
+struct cff2_font_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff2_font_dict_values_t& dictval)
+  {
+    switch (op) {
+      case OpCode_Private:
+        dictval.privateDictInfo.offset = env.argStack.pop_uint ();
+        dictval.privateDictInfo.size = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      default:
+        SUPER::process_op (op, env);
+        if (!env.argStack.is_empty ())
+          return;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+
+  private:
+  typedef dict_opset_t SUPER;
+};
+
+template <typename VAL>
+struct cff2_private_dict_values_base_t : dict_values_t<VAL>
+{
+  void init ()
+  {
+    dict_values_t<VAL>::init ();
+    subrsOffset = 0;
+    localSubrs = &Null(CFF2Subrs);
+    ivs = 0;
+  }
+  void fini () { dict_values_t<VAL>::fini (); }
+
+  unsigned int calculate_serialized_size () const
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < dict_values_t<VAL>::get_count; i++)
+      if (dict_values_t<VAL>::get_value (i).op == OpCode_Subrs)
+        size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
+      else
+        size += dict_values_t<VAL>::get_value (i).str.length;
+    return size;
+  }
+
+  unsigned int      subrsOffset;
+  const CFF2Subrs   *localSubrs;
+  unsigned int      ivs;
+};
+
+typedef cff2_private_dict_values_base_t<op_str_t> cff2_private_dict_values_subset_t;
+typedef cff2_private_dict_values_base_t<num_dict_val_t> cff2_private_dict_values_t;
+
+struct cff2_priv_dict_interp_env_t : num_interp_env_t
+{
+  void init (const byte_str_t &str)
+  {
+    num_interp_env_t::init (str);
+    ivs = 0;
+    seen_vsindex = false;
+  }
+
+  void process_vsindex ()
+  {
+    if (likely (!seen_vsindex))
+    {
+      set_ivs (argStack.pop_uint ());
+    }
+    seen_vsindex = true;
+  }
+
+  unsigned int get_ivs () const { return ivs; }
+  void   set_ivs (unsigned int ivs_) { ivs = ivs_; }
+
+  protected:
+  unsigned int  ivs;
+  bool    seen_vsindex;
+};
+
+struct cff2_private_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, cff2_priv_dict_interp_env_t& env, cff2_private_dict_values_t& dictval)
+  {
+    num_dict_val_t val;
+    val.init ();
+
+    switch (op) {
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_ExpansionFactor:
+      case OpCode_LanguageGroup:
+        val.single_val = env.argStack.pop_num ();
+        env.clear_args ();
+        break;
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+        env.clear_args ();
+        break;
+      case OpCode_Subrs:
+        dictval.subrsOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+      case OpCode_vsindexdict:
+        env.process_vsindex ();
+        dictval.ivs = env.get_ivs ();
+        env.clear_args ();
+        break;
+      case OpCode_blenddict:
+        break;
+
+      default:
+        dict_opset_t::process_op (op, env);
+        if (!env.argStack.is_empty ()) return;
+        break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref, val);
+  }
+};
+
+struct cff2_private_dict_opset_subset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, cff2_priv_dict_interp_env_t& env, cff2_private_dict_values_subset_t& dictval)
+  {
+    switch (op) {
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+      case OpCode_LanguageGroup:
+      case OpCode_ExpansionFactor:
+        env.clear_args ();
+        break;
+
+      case OpCode_blenddict:
+        env.clear_args ();
+        return;
+
+      case OpCode_Subrs:
+        dictval.subrsOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      default:
+        SUPER::process_op (op, env);
+        if (!env.argStack.is_empty ()) return;
+        break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+
+  private:
+  typedef dict_opset_t SUPER;
+};
+
+typedef dict_interpreter_t<cff2_top_dict_opset_t, cff2_top_dict_values_t> cff2_top_dict_interpreter_t;
+typedef dict_interpreter_t<cff2_font_dict_opset_t, cff2_font_dict_values_t> cff2_font_dict_interpreter_t;
+
+} /* namespace CFF */
+
+namespace OT {
+
+using namespace CFF;
+
+struct cff2
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_cff2;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  likely (version.major == 2));
+  }
+
+  template <typename PRIVOPSET, typename PRIVDICTVAL>
+  struct accelerator_templ_t
+  {
+    void init (hb_face_t *face)
+    {
+      topDict.init ();
+      fontDicts.init ();
+      privateDicts.init ();
+
+      this->blob = sc.reference_table<cff2> (face);
+
+      /* setup for run-time santization */
+      sc.init (this->blob);
+      sc.start_processing ();
+
+      const OT::cff2 *cff2 = this->blob->template as<OT::cff2> ();
+
+      if (cff2 == &Null(OT::cff2))
+      { fini (); return; }
+
+      { /* parse top dict */
+        byte_str_t topDictStr (cff2 + cff2->topDict, cff2->topDictSize);
+        if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
+        cff2_top_dict_interpreter_t top_interp;
+        top_interp.env.init (topDictStr);
+        topDict.init ();
+        if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
+      }
+
+      globalSubrs = &StructAtOffset<CFF2Subrs> (cff2, cff2->topDict + cff2->topDictSize);
+      varStore = &StructAtOffsetOrNull<CFF2VariationStore> (cff2, topDict.vstoreOffset);
+      charStrings = &StructAtOffsetOrNull<CFF2CharStrings> (cff2, topDict.charStringsOffset);
+      fdArray = &StructAtOffsetOrNull<CFF2FDArray> (cff2, topDict.FDArrayOffset);
+      fdSelect = &StructAtOffsetOrNull<CFF2FDSelect> (cff2, topDict.FDSelectOffset);
+
+      if (((varStore != &Null(CFF2VariationStore)) && unlikely (!varStore->sanitize (&sc))) ||
+          (charStrings == &Null(CFF2CharStrings)) || unlikely (!charStrings->sanitize (&sc)) ||
+          (globalSubrs == &Null(CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) ||
+          (fdArray == &Null(CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) ||
+          (((fdSelect != &Null(CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count)))))
+      { fini (); return; }
+
+      num_glyphs = charStrings->count;
+      if (num_glyphs != sc.get_num_glyphs ())
+      { fini (); return; }
+
+      fdCount = fdArray->count;
+      privateDicts.resize (fdCount);
+
+      /* parse font dicts and gather private dicts */
+      for (unsigned int i = 0; i < fdCount; i++)
+      {
+        const byte_str_t fontDictStr = (*fdArray)[i];
+        if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
+        cff2_font_dict_values_t  *font;
+        cff2_font_dict_interpreter_t font_interp;
+        font_interp.env.init (fontDictStr);
+        font = fontDicts.push ();
+        if (unlikely (font == &Crap(cff2_font_dict_values_t))) { fini (); return; }
+        font->init ();
+        if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
+
+        const byte_str_t privDictStr (StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset), font->privateDictInfo.size);
+        if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
+        dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t>  priv_interp;
+        priv_interp.env.init(privDictStr);
+        privateDicts[i].init ();
+        if (unlikely (!priv_interp.interpret (privateDicts[i]))) { fini (); return; }
+
+        privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset);
+        if (privateDicts[i].localSubrs != &Null(CFF2Subrs) &&
+          unlikely (!privateDicts[i].localSubrs->sanitize (&sc)))
+        { fini (); return; }
+      }
+    }
+
+    void fini ()
+    {
+      sc.end_processing ();
+      topDict.fini ();
+      fontDicts.fini_deep ();
+      privateDicts.fini_deep ();
+      hb_blob_destroy (blob);
+      blob = nullptr;
+    }
+
+    bool is_valid () const { return blob != nullptr; }
+
+    protected:
+    hb_blob_t                   *blob;
+    hb_sanitize_context_t       sc;
+
+    public:
+    cff2_top_dict_values_t      topDict;
+    const CFF2Subrs             *globalSubrs;
+    const CFF2VariationStore    *varStore;
+    const CFF2CharStrings       *charStrings;
+    const CFF2FDArray           *fdArray;
+    const CFF2FDSelect          *fdSelect;
+    unsigned int                fdCount;
+
+    hb_vector_t<cff2_font_dict_values_t>     fontDicts;
+    hb_vector_t<PRIVDICTVAL>  privateDicts;
+
+    unsigned int              num_glyphs;
+  };
+
+  struct accelerator_t : accelerator_templ_t<cff2_private_dict_opset_t, cff2_private_dict_values_t>
+  {
+    HB_INTERNAL bool get_extents (hb_font_t *font,
+                                  hb_codepoint_t glyph,
+                                  hb_glyph_extents_t *extents) const;
+  };
+
+  typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t;
+
+  bool subset (hb_subset_plan_t *plan) const
+  {
+    hb_blob_t *cff2_prime = nullptr;
+
+    bool success = true;
+    if (hb_subset_cff2 (plan, &cff2_prime)) {
+      success = success && plan->add_table (HB_OT_TAG_cff2, cff2_prime);
+      hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
+      success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
+      hb_blob_destroy (head_blob);
+    } else {
+      success = false;
+    }
+    hb_blob_destroy (cff2_prime);
+
+    return success;
+  }
+
+  public:
+  FixedVersion<HBUINT8>         version;        /* Version of CFF2 table. set to 0x0200u */
+  NNOffsetTo<TopDict, HBUINT8>  topDict;        /* headerSize = Offset to Top DICT. */
+  HBUINT16                      topDictSize;    /* Top DICT size */
+
+  public:
+  DEFINE_SIZE_STATIC (5);
+};
+
+struct cff2_accelerator_t : cff2::accelerator_t {};
+} /* namespace OT */
+
+#endif /* HB_OT_CFF2_TABLE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cmap-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cmap-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,9 +27,8 @@
 #ifndef HB_OT_CMAP_TABLE_HH
 #define HB_OT_CMAP_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-set-private.hh"
-#include "hb-subset-plan.hh"
+#include "hb-open-type.hh"
+#include "hb-set.hh"
 
 /*
  * cmap -- Character to Glyph Index Mapping
@@ -37,13 +36,12 @@
  */
 #define HB_OT_TAG_cmap HB_TAG('c','m','a','p')
 
-
 namespace OT {
 
 
 struct CmapSubtableFormat0
 {
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
   {
     hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0;
     if (!gid)
@@ -51,8 +49,14 @@
     *glyph = gid;
     return true;
   }
+  void collect_unicodes (hb_set_t *out) const
+  {
+    for (unsigned int i = 0; i < 256; i++)
+      if (glyphIdArray[i])
+        out->add (i);
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -88,23 +92,23 @@
     this->format.set (4);
     this->length.set (get_sub_table_size (segments));
 
-    this->segCountX2.set (segments.len * 2);
-    this->entrySelector.set (MAX (1u, _hb_bit_storage (segments.len)) - 1);
+    this->segCountX2.set (segments.length * 2);
+    this->entrySelector.set (MAX (1u, hb_bit_storage (segments.length)) - 1);
     this->searchRange.set (2 * (1u << this->entrySelector));
-    this->rangeShift.set (segments.len * 2 > this->searchRange
-                          ? 2 * segments.len - this->searchRange
+    this->rangeShift.set (segments.length * 2 > this->searchRange
+                          ? 2 * segments.length - this->searchRange
                           : 0);
 
-    HBUINT16 *end_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.len);
+    HBUINT16 *end_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
     c->allocate_size<HBUINT16> (HBUINT16::static_size); // 2 bytes of padding.
-    HBUINT16 *start_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.len);
-    HBINT16 *id_delta = c->allocate_size<HBINT16> (HBUINT16::static_size * segments.len);
-    HBUINT16 *id_range_offset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.len);
+    HBUINT16 *start_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
+    HBINT16 *id_delta = c->allocate_size<HBINT16> (HBUINT16::static_size * segments.length);
+    HBUINT16 *id_range_offset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
 
     if (id_range_offset == nullptr)
       return_trace (false);
 
-    for (unsigned int i = 0; i < segments.len; i++)
+    for (unsigned int i = 0; i < segments.length; i++)
     {
       end_count[i].set (segments[i].end_code);
       start_count[i].set (segments[i].start_code);
@@ -150,10 +154,10 @@
     return_trace (true);
   }
 
-  static inline size_t get_sub_table_size (const hb_vector_t<segment_plan> &segments)
+  static size_t get_sub_table_size (const hb_vector_t<segment_plan> &segments)
   {
     size_t segment_size = 0;
-    for (unsigned int i = 0; i < segments.len; i++)
+    for (unsigned int i = 0; i < segments.length; i++)
     {
       // Parallel array entries
       segment_size +=
@@ -172,8 +176,8 @@
         + segment_size;
   }
 
-  static inline bool create_sub_table_plan (const hb_subset_plan_t *plan,
-                                            hb_vector_t<segment_plan> *segments)
+  static bool create_sub_table_plan (const hb_subset_plan_t *plan,
+                                     hb_vector_t<segment_plan> *segments)
   {
     segment_plan *segment = nullptr;
     hb_codepoint_t last_gid = 0;
@@ -187,13 +191,11 @@
         return false;
       }
 
-      if (cp > 0xFFFF) {
-        // We are now outside of unicode BMP, stop adding to this cmap.
-        break;
-      }
+      /* Stop adding to cmap if we are now outside of unicode BMP. */
+      if (cp > 0xFFFF) break;
 
-      if (!segment
-          || cp != segment->end_code + 1u)
+      if (!segment ||
+          cp != segment->end_code + 1u)
       {
         segment = segments->push ();
         segment->start_code.set (cp);
@@ -224,29 +226,32 @@
 
   struct accelerator_t
   {
-    inline void init (const CmapSubtableFormat4 *subtable)
+    accelerator_t () {}
+    accelerator_t (const CmapSubtableFormat4 *subtable) { init (subtable); }
+    ~accelerator_t () { fini (); }
+
+    void init (const CmapSubtableFormat4 *subtable)
     {
       segCount = subtable->segCountX2 / 2;
-      endCount = subtable->values;
+      endCount = subtable->values.arrayZ;
       startCount = endCount + segCount + 1;
       idDelta = startCount + segCount;
       idRangeOffset = idDelta + segCount;
       glyphIdArray = idRangeOffset + segCount;
       glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2;
     }
-
-    static inline bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
-    {
-      const accelerator_t *thiz = (const accelerator_t *) obj;
+    void fini () {}
 
+    bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+    {
       /* Custom two-array bsearch. */
-      int min = 0, max = (int) thiz->segCount - 1;
-      const HBUINT16 *startCount = thiz->startCount;
-      const HBUINT16 *endCount = thiz->endCount;
+      int min = 0, max = (int) this->segCount - 1;
+      const HBUINT16 *startCount = this->startCount;
+      const HBUINT16 *endCount = this->endCount;
       unsigned int i;
       while (min <= max)
       {
-        int mid = (min + max) / 2;
+        int mid = ((unsigned int) min + (unsigned int) max) / 2;
         if (codepoint < startCount[mid])
           max = mid - 1;
         else if (codepoint > endCount[mid])
@@ -261,33 +266,55 @@
 
     found:
       hb_codepoint_t gid;
-      unsigned int rangeOffset = thiz->idRangeOffset[i];
+      unsigned int rangeOffset = this->idRangeOffset[i];
       if (rangeOffset == 0)
-        gid = codepoint + thiz->idDelta[i];
+        gid = codepoint + this->idDelta[i];
       else
       {
         /* Somebody has been smoking... */
-        unsigned int index = rangeOffset / 2 + (codepoint - thiz->startCount[i]) + i - thiz->segCount;
-        if (unlikely (index >= thiz->glyphIdArrayLength))
+        unsigned int index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount;
+        if (unlikely (index >= this->glyphIdArrayLength))
           return false;
-        gid = thiz->glyphIdArray[index];
+        gid = this->glyphIdArray[index];
         if (unlikely (!gid))
           return false;
-        gid += thiz->idDelta[i];
+        gid += this->idDelta[i];
       }
-
-      *glyph = gid & 0xFFFFu;
+      gid &= 0xFFFFu;
+      if (!gid)
+        return false;
+      *glyph = gid;
       return true;
     }
-
-    static inline void get_all_codepoints_func (const void *obj, hb_set_t *out)
+    static bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
+    {
+      return ((const accelerator_t *) obj)->get_glyph (codepoint, glyph);
+    }
+    void collect_unicodes (hb_set_t *out) const
     {
-      const accelerator_t *thiz = (const accelerator_t *) obj;
-      for (unsigned int i = 0; i < thiz->segCount; i++)
+      unsigned int count = this->segCount;
+      if (count && this->startCount[count - 1] == 0xFFFFu)
+        count--; /* Skip sentinel segment. */
+      for (unsigned int i = 0; i < count; i++)
       {
-        if (thiz->startCount[i] != 0xFFFFu
-            || thiz->endCount[i] != 0xFFFFu) // Skip the last segment (0xFFFF)
-          hb_set_add_range (out, thiz->startCount[i], thiz->endCount[i]);
+        unsigned int rangeOffset = this->idRangeOffset[i];
+        if (rangeOffset == 0)
+          out->add_range (this->startCount[i], this->endCount[i]);
+        else
+        {
+          for (hb_codepoint_t codepoint = this->startCount[i];
+               codepoint <= this->endCount[i];
+               codepoint++)
+          {
+            unsigned int index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount;
+            if (unlikely (index >= this->glyphIdArrayLength))
+              break;
+            hb_codepoint_t gid = this->glyphIdArray[index];
+            if (unlikely (!gid))
+              continue;
+            out->add (codepoint);
+          }
+        }
       }
     }
 
@@ -300,14 +327,18 @@
     unsigned int glyphIdArrayLength;
   };
 
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
   {
-    accelerator_t accel;
-    accel.init (this);
+    accelerator_t accel (this);
     return accel.get_glyph_func (&accel, codepoint, glyph);
   }
+  void collect_unicodes (hb_set_t *out) const
+  {
+    accelerator_t accel (this);
+    accel.collect_unicodes (out);
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
@@ -340,7 +371,8 @@
   HBUINT16      entrySelector;  /* log2(searchRange/2) */
   HBUINT16      rangeShift;     /* 2 x segCount - searchRange */
 
-  HBUINT16      values[VAR];
+  UnsizedArrayOf<HBUINT16>
+                values;
 #if 0
   HBUINT16      endCount[segCount];     /* End characterCode for each segment,
                                          * last=0xFFFFu. */
@@ -348,7 +380,8 @@
   HBUINT16      startCount[segCount];   /* Start character code for each segment. */
   HBINT16               idDelta[segCount];      /* Delta for all character codes in segment. */
   HBUINT16      idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
-  HBUINT16      glyphIdArray[VAR];      /* Glyph index array (arbitrary length) */
+  UnsizedArrayOf<HBUINT16>
+                glyphIdArray;   /* Glyph index array (arbitrary length) */
 #endif
 
   public:
@@ -370,7 +403,7 @@
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -380,15 +413,16 @@
   HBUINT32              startCharCode;  /* First character code in this group. */
   HBUINT32              endCharCode;    /* Last character code in this group. */
   HBUINT32              glyphID;        /* Glyph index; interpretation depends on
-                                 * subtable format. */
+                                         * subtable format. */
   public:
   DEFINE_SIZE_STATIC (12);
 };
+DECLARE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup);
 
 template <typename UINT>
 struct CmapSubtableTrimmed
 {
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
   {
     /* Rely on our implicit array bound-checking. */
     hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
@@ -397,8 +431,16 @@
     *glyph = gid;
     return true;
   }
+  void collect_unicodes (hb_set_t *out) const
+  {
+    hb_codepoint_t start = startCharCode;
+    unsigned int count = glyphIdArray.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (glyphIdArray[i])
+        out->add (start + i);
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && glyphIdArray.sanitize (c));
@@ -424,37 +466,36 @@
 {
   friend struct cmap;
 
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
   {
-    int i = groups.bsearch (codepoint);
-    if (i == -1)
+    hb_codepoint_t gid = T::group_get_glyph (groups.bsearch (codepoint), codepoint);
+    if (!gid)
       return false;
-    *glyph = T::group_get_glyph (groups[i], codepoint);
+    *glyph = gid;
     return true;
   }
 
-  inline void get_all_codepoints (hb_set_t *out) const
+  void collect_unicodes (hb_set_t *out) const
   {
     for (unsigned int i = 0; i < this->groups.len; i++) {
-      hb_set_add_range (out,
-                        this->groups[i].startCharCode,
-                        this->groups[i].endCharCode);
+      out->add_range (this->groups[i].startCharCode,
+                      MIN ((hb_codepoint_t) this->groups[i].endCharCode,
+                           (hb_codepoint_t) HB_UNICODE_MAX));
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && groups.sanitize (c));
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         const hb_vector_t<CmapSubtableLongGroup> &group_data)
+  bool serialize (hb_serialize_context_t *c,
+                  const hb_vector_t<CmapSubtableLongGroup> &group_data)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    Supplier<CmapSubtableLongGroup> supplier (group_data.arrayZ, group_data.len);
-    if (unlikely (!groups.serialize (c, supplier, group_data.len))) return_trace (false);
+    if (unlikely (!groups.serialize (c, group_data.as_array ()))) return_trace (false);
     return true;
   }
 
@@ -471,9 +512,10 @@
 
 struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
 {
-  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
-                                                hb_codepoint_t u)
-  { return group.glyphID + (u - group.startCharCode); }
+  static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
+                                         hb_codepoint_t u)
+  { return likely (group.startCharCode <= group.endCharCode) ?
+           group.glyphID + (u - group.startCharCode) : 0; }
 
 
   bool serialize (hb_serialize_context_t *c,
@@ -488,13 +530,13 @@
     return CmapSubtableLongSegmented<CmapSubtableFormat12>::serialize (c, groups);
   }
 
-  static inline size_t get_sub_table_size (const hb_vector_t<CmapSubtableLongGroup> &groups)
+  static size_t get_sub_table_size (const hb_vector_t<CmapSubtableLongGroup> &groups)
   {
-    return 16 + 12 * groups.len;
+    return 16 + 12 * groups.length;
   }
 
-  static inline bool create_sub_table_plan (const hb_subset_plan_t *plan,
-                                            hb_vector_t<CmapSubtableLongGroup> *groups)
+  static bool create_sub_table_plan (const hb_subset_plan_t *plan,
+                                     hb_vector_t<CmapSubtableLongGroup> *groups)
   {
     CmapSubtableLongGroup *group = nullptr;
 
@@ -513,14 +555,12 @@
         group->startCharCode.set (cp);
         group->endCharCode.set (cp);
         group->glyphID.set (new_gid);
-      } else
-      {
-        group->endCharCode.set (cp);
       }
+      else group->endCharCode.set (cp);
     }
 
     DEBUG_MSG(SUBSET, nullptr, "cmap");
-    for (unsigned int i = 0; i < groups->len; i++) {
+    for (unsigned int i = 0; i < groups->length; i++) {
       CmapSubtableLongGroup& group = (*groups)[i];
       DEBUG_MSG(SUBSET, nullptr, "  %d: U+%04X-U+%04X, gid %d-%d", i, (uint32_t) group.startCharCode, (uint32_t) group.endCharCode, (uint32_t) group.glyphID, (uint32_t) group.glyphID + ((uint32_t) group.endCharCode - (uint32_t) group.startCharCode));
     }
@@ -529,9 +569,9 @@
   }
 
  private:
-  static inline bool _is_gid_consecutive (CmapSubtableLongGroup *group,
-                                          hb_codepoint_t cp,
-                                          hb_codepoint_t new_gid)
+  static bool _is_gid_consecutive (CmapSubtableLongGroup *group,
+                                   hb_codepoint_t cp,
+                                   hb_codepoint_t new_gid)
   {
     return (cp - 1 == group->endCharCode) &&
         new_gid == group->glyphID + (cp - group->startCharCode);
@@ -541,8 +581,8 @@
 
 struct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
 {
-  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
-                                                hb_codepoint_t u HB_UNUSED)
+  static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
+                                         hb_codepoint_t u HB_UNUSED)
   { return group.glyphID; }
 };
 
@@ -555,36 +595,52 @@
 
 struct UnicodeValueRange
 {
-  inline int cmp (const hb_codepoint_t &codepoint) const
+  int cmp (const hb_codepoint_t &codepoint) const
   {
     if (codepoint < startUnicodeValue) return -1;
     if (codepoint > startUnicodeValue + additionalCount) return +1;
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   HBUINT24      startUnicodeValue;      /* First value in this range. */
-  HBUINT8               additionalCount;        /* Number of additional values in this
+  HBUINT8       additionalCount;        /* Number of additional values in this
                                          * range. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
-typedef SortedArrayOf<UnicodeValueRange, HBUINT32> DefaultUVS;
+struct DefaultUVS : SortedArrayOf<UnicodeValueRange, HBUINT32>
+{
+  void collect_unicodes (hb_set_t *out) const
+  {
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      hb_codepoint_t first = arrayZ[i].startUnicodeValue;
+      hb_codepoint_t last = MIN ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
+                                 (hb_codepoint_t) HB_UNICODE_MAX);
+      out->add_range (first, last);
+    }
+  }
+
+  public:
+  DEFINE_SIZE_ARRAY (4, *this);
+};
 
 struct UVSMapping
 {
-  inline int cmp (const hb_codepoint_t &codepoint) const
+  int cmp (const hb_codepoint_t &codepoint) const
   {
     return unicodeValue.cmp (codepoint);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -596,35 +652,48 @@
   DEFINE_SIZE_STATIC (5);
 };
 
-typedef SortedArrayOf<UVSMapping, HBUINT32> NonDefaultUVS;
+struct NonDefaultUVS : SortedArrayOf<UVSMapping, HBUINT32>
+{
+  void collect_unicodes (hb_set_t *out) const
+  {
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+      out->add (arrayZ[i].glyphID);
+  }
+
+  public:
+  DEFINE_SIZE_ARRAY (4, *this);
+};
 
 struct VariationSelectorRecord
 {
-  inline glyph_variant_t get_glyph (hb_codepoint_t codepoint,
-                                    hb_codepoint_t *glyph,
-                                    const void *base) const
+  glyph_variant_t get_glyph (hb_codepoint_t codepoint,
+                             hb_codepoint_t *glyph,
+                             const void *base) const
   {
-    int i;
-    const DefaultUVS &defaults = base+defaultUVS;
-    i = defaults.bsearch (codepoint);
-    if (i != -1)
+    if ((base+defaultUVS).bfind (codepoint))
       return GLYPH_VARIANT_USE_DEFAULT;
-    const NonDefaultUVS &nonDefaults = base+nonDefaultUVS;
-    i = nonDefaults.bsearch (codepoint);
-    if (i != -1)
+    const UVSMapping &nonDefault = (base+nonDefaultUVS).bsearch (codepoint);
+    if (nonDefault.glyphID)
     {
-      *glyph = nonDefaults[i].glyphID;
+      *glyph = nonDefault.glyphID;
        return GLYPH_VARIANT_FOUND;
     }
     return GLYPH_VARIANT_NOT_FOUND;
   }
 
-  inline int cmp (const hb_codepoint_t &variation_selector) const
+  void collect_unicodes (hb_set_t *out, const void *base) const
+  {
+    (base+defaultUVS).collect_unicodes (out);
+    (base+nonDefaultUVS).collect_unicodes (out);
+  }
+
+  int cmp (const hb_codepoint_t &variation_selector) const
   {
     return varSelector.cmp (variation_selector);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -634,23 +703,35 @@
 
   HBUINT24      varSelector;    /* Variation selector. */
   LOffsetTo<DefaultUVS>
-                defaultUVS;     /* Offset to Default UVS Table. May be 0. */
+                defaultUVS;     /* Offset to Default UVS Table.  May be 0. */
   LOffsetTo<NonDefaultUVS>
-                nonDefaultUVS;  /* Offset to Non-Default UVS Table. May be 0. */
+                nonDefaultUVS;  /* Offset to Non-Default UVS Table.  May be 0. */
   public:
   DEFINE_SIZE_STATIC (11);
 };
 
 struct CmapSubtableFormat14
 {
-  inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
-                                            hb_codepoint_t variation_selector,
-                                            hb_codepoint_t *glyph) const
+  glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
+                                     hb_codepoint_t variation_selector,
+                                     hb_codepoint_t *glyph) const
   {
-    return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this);
+    return record.bsearch (variation_selector).get_glyph (codepoint, glyph, this);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  void collect_variation_selectors (hb_set_t *out) const
+  {
+    unsigned int count = record.len;
+    for (unsigned int i = 0; i < count; i++)
+      out->add (record.arrayZ[i].varSelector);
+  }
+  void collect_variation_unicodes (hb_codepoint_t variation_selector,
+                                   hb_set_t *out) const
+  {
+    record.bsearch (variation_selector).collect_unicodes (out, this);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -671,8 +752,8 @@
 {
   /* Note: We intentionally do NOT implement subtable formats 2 and 8. */
 
-  inline bool get_glyph (hb_codepoint_t codepoint,
-                         hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint,
+                  hb_codepoint_t *glyph) const
   {
     switch (u.format) {
     case  0: return u.format0 .get_glyph (codepoint, glyph);
@@ -685,8 +766,21 @@
     default: return false;
     }
   }
+  void collect_unicodes (hb_set_t *out) const
+  {
+    switch (u.format) {
+    case  0: u.format0 .collect_unicodes (out); return;
+    case  4: u.format4 .collect_unicodes (out); return;
+    case  6: u.format6 .collect_unicodes (out); return;
+    case 10: u.format10.collect_unicodes (out); return;
+    case 12: u.format12.collect_unicodes (out); return;
+    case 13: u.format13.collect_unicodes (out); return;
+    case 14:
+    default: return;
+    }
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
@@ -720,7 +814,7 @@
 
 struct EncodingRecord
 {
-  inline int cmp (const EncodingRecord &other) const
+  int cmp (const EncodingRecord &other) const
   {
     int ret;
     ret = platformID.cmp (other.platformID);
@@ -730,7 +824,7 @@
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -747,22 +841,11 @@
 
 struct cmap
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_cmap;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
 
-  struct subset_plan {
-    subset_plan(void)
-    {
-      format4_segments.init();
-      format12_groups.init();
-    }
-
-    ~subset_plan(void)
-    {
-      format4_segments.fini();
-      format12_groups.fini();
-    }
-
-    inline size_t final_size() const
+  struct subset_plan
+  {
+    size_t final_size () const
     {
       return 4 // header
           +  8 * 3 // 3 EncodingRecord
@@ -770,67 +853,57 @@
           +  CmapSubtableFormat12::get_sub_table_size (this->format12_groups);
     }
 
-    // Format 4
     hb_vector_t<CmapSubtableFormat4::segment_plan> format4_segments;
-    // Format 12
     hb_vector_t<CmapSubtableLongGroup> format12_groups;
   };
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool _create_plan (const hb_subset_plan_t *plan,
+                     subset_plan *cmap_plan) const
   {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  likely (version == 0) &&
-                  encodingRecord.sanitize (c, this));
-  }
-
-  inline bool _create_plan (const hb_subset_plan_t *plan,
-                            subset_plan *cmap_plan) const
-  {
-    if (unlikely( !CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments)))
+    if (unlikely (!CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments)))
       return false;
 
     return CmapSubtableFormat12::create_sub_table_plan (plan, &cmap_plan->format12_groups);
   }
 
-  inline bool _subset (const hb_subset_plan_t *plan,
-                       const subset_plan &cmap_subset_plan,
-                       size_t dest_sz,
-                       void *dest) const
+  bool _subset (const hb_subset_plan_t *plan,
+                const subset_plan &cmap_subset_plan,
+                size_t dest_sz,
+                void *dest) const
   {
     hb_serialize_context_t c (dest, dest_sz);
 
-    OT::cmap *cmap = c.start_serialize<OT::cmap> ();
-    if (unlikely (!c.extend_min (*cmap)))
+    cmap *table = c.start_serialize<cmap> ();
+    if (unlikely (!c.extend_min (*table)))
     {
       return false;
     }
 
-    cmap->version.set (0);
+    table->version.set (0);
 
-    if (unlikely (!cmap->encodingRecord.serialize (&c, /* numTables */ 3)))
+    if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ 3)))
       return false;
 
     // TODO(grieger): Convert the below to a for loop
 
     // Format 4, Plat 0 Encoding Record
-    EncodingRecord &format4_plat0_rec = cmap->encodingRecord[0];
+    EncodingRecord &format4_plat0_rec = table->encodingRecord[0];
     format4_plat0_rec.platformID.set (0); // Unicode
     format4_plat0_rec.encodingID.set (3);
 
     // Format 4, Plat 3 Encoding Record
-    EncodingRecord &format4_plat3_rec = cmap->encodingRecord[1];
+    EncodingRecord &format4_plat3_rec = table->encodingRecord[1];
     format4_plat3_rec.platformID.set (3); // Windows
     format4_plat3_rec.encodingID.set (1); // Unicode BMP
 
     // Format 12 Encoding Record
-    EncodingRecord &format12_rec = cmap->encodingRecord[2];
+    EncodingRecord &format12_rec = table->encodingRecord[2];
     format12_rec.platformID.set (3); // Windows
     format12_rec.encodingID.set (10); // Unicode UCS-4
 
     // Write out format 4 sub table
     {
-      CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, cmap);
+      CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, table);
       format4_plat3_rec.subtable.set (format4_plat0_rec.subtable);
       subtable.u.format.set (4);
 
@@ -841,7 +914,7 @@
 
     // Write out format 12 sub table.
     {
-      CmapSubtable &subtable = format12_rec.subtable.serialize (&c, cmap);
+      CmapSubtable &subtable = format12_rec.subtable.serialize (&c, table);
       subtable.u.format.set (12);
 
       CmapSubtableFormat12 &format12 = subtable.u.format12;
@@ -854,7 +927,7 @@
     return true;
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
     subset_plan cmap_subset_plan;
 
@@ -865,7 +938,7 @@
     }
 
     // We now know how big our blob needs to be
-    size_t dest_sz = cmap_subset_plan.final_size();
+    size_t dest_sz = cmap_subset_plan.final_size ();
     void *dest = malloc (dest_sz);
     if (unlikely (!dest)) {
       DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for cmap subset output", (unsigned long) dest_sz);
@@ -880,7 +953,7 @@
     }
 
     // all done, write the blob into dest
-    hb_blob_t *cmap_prime = hb_blob_create ((const char *)dest,
+    hb_blob_t *cmap_prime = hb_blob_create ((const char *) dest,
                                             dest_sz,
                                             HB_MEMORY_MODE_READONLY,
                                             dest,
@@ -890,137 +963,149 @@
     return result;
   }
 
+  const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
+  {
+    if (symbol) *symbol = false;
+
+    const CmapSubtable *subtable;
+
+    /* 32-bit subtables. */
+    if ((subtable = this->find_subtable (3, 10))) return subtable;
+    if ((subtable = this->find_subtable (0, 6))) return subtable;
+    if ((subtable = this->find_subtable (0, 4))) return subtable;
+
+    /* 16-bit subtables. */
+    if ((subtable = this->find_subtable (3, 1))) return subtable;
+    if ((subtable = this->find_subtable (0, 3))) return subtable;
+    if ((subtable = this->find_subtable (0, 2))) return subtable;
+    if ((subtable = this->find_subtable (0, 1))) return subtable;
+    if ((subtable = this->find_subtable (0, 0))) return subtable;
+
+    /* Symbol subtable. */
+    if ((subtable = this->find_subtable (3, 0)))
+    {
+      if (symbol) *symbol = true;
+      return subtable;
+    }
+
+    /* Meh. */
+    return &Null (CmapSubtable);
+  }
+
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
     {
-      this->blob = OT::Sanitizer<OT::cmap>().sanitize (face->reference_table (HB_OT_TAG_cmap));
-      const OT::cmap *cmap = this->blob->as<OT::cmap> ();
-      const OT::CmapSubtable *subtable = nullptr;
-      const OT::CmapSubtableFormat14 *subtable_uvs = nullptr;
-
-      bool symbol = false;
-      /* 32-bit subtables. */
-      if (!subtable) subtable = cmap->find_subtable (3, 10);
-      if (!subtable) subtable = cmap->find_subtable (0, 6);
-      if (!subtable) subtable = cmap->find_subtable (0, 4);
-      /* 16-bit subtables. */
-      if (!subtable) subtable = cmap->find_subtable (3, 1);
-      if (!subtable) subtable = cmap->find_subtable (0, 3);
-      if (!subtable) subtable = cmap->find_subtable (0, 2);
-      if (!subtable) subtable = cmap->find_subtable (0, 1);
-      if (!subtable) subtable = cmap->find_subtable (0, 0);
-      if (!subtable)
+      this->table = hb_sanitize_context_t ().reference_table<cmap> (face);
+      bool symbol;
+      this->subtable = table->find_best_subtable (&symbol);
+      this->subtable_uvs = &Null (CmapSubtableFormat14);
       {
-        subtable = cmap->find_subtable (3, 0);
-        if (subtable) symbol = true;
-      }
-      /* Meh. */
-      if (!subtable) subtable = &Null(OT::CmapSubtable);
-
-      /* UVS subtable. */
-      if (!subtable_uvs)
-      {
-        const OT::CmapSubtable *st = cmap->find_subtable (0, 5);
+        const CmapSubtable *st = table->find_subtable (0, 5);
         if (st && st->u.format == 14)
           subtable_uvs = &st->u.format14;
       }
-      /* Meh. */
-      if (!subtable_uvs) subtable_uvs = &Null(OT::CmapSubtableFormat14);
-
-      this->uvs_table = subtable_uvs;
 
       this->get_glyph_data = subtable;
       if (unlikely (symbol))
       {
-        this->get_glyph_func = get_glyph_from_symbol<OT::CmapSubtable>;
-        this->get_all_codepoints_func = null_get_all_codepoints_func;
+        this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable>;
       } else {
         switch (subtable->u.format) {
         /* Accelerate format 4 and format 12. */
         default:
-          this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;
-          this->get_all_codepoints_func = null_get_all_codepoints_func;
+          this->get_glyph_funcZ = get_glyph_from<CmapSubtable>;
           break;
         case 12:
-          this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>;
-          this->get_all_codepoints_func = get_all_codepoints_from<OT::CmapSubtableFormat12>;
+          this->get_glyph_funcZ = get_glyph_from<CmapSubtableFormat12>;
           break;
         case  4:
           {
             this->format4_accel.init (&subtable->u.format4);
             this->get_glyph_data = &this->format4_accel;
-            this->get_glyph_func = this->format4_accel.get_glyph_func;
-            this->get_all_codepoints_func = this->format4_accel.get_all_codepoints_func;
+            this->get_glyph_funcZ = this->format4_accel.get_glyph_func;
           }
           break;
         }
       }
     }
 
-    inline void fini (void)
-    {
-      hb_blob_destroy (this->blob);
-    }
+    void fini () { this->table.destroy (); }
 
-    inline bool get_nominal_glyph (hb_codepoint_t  unicode,
+    bool get_nominal_glyph (hb_codepoint_t  unicode,
                                    hb_codepoint_t *glyph) const
     {
-      return this->get_glyph_func (this->get_glyph_data, unicode, glyph);
+      if (unlikely (!this->get_glyph_funcZ)) return false;
+      return this->get_glyph_funcZ (this->get_glyph_data, unicode, glyph);
+    }
+    unsigned int get_nominal_glyphs (unsigned int count,
+                                     const hb_codepoint_t *first_unicode,
+                                     unsigned int unicode_stride,
+                                     hb_codepoint_t *first_glyph,
+                                     unsigned int glyph_stride) const
+    {
+      if (unlikely (!this->get_glyph_funcZ)) return 0;
+
+      hb_cmap_get_glyph_func_t get_glyph_funcZ = this->get_glyph_funcZ;
+      const void *get_glyph_data = this->get_glyph_data;
+
+      unsigned int done;
+      for (done = 0;
+           done < count && get_glyph_funcZ (get_glyph_data, *first_unicode, first_glyph);
+           done++)
+      {
+        first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
+        first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+      }
+      return done;
     }
 
-    inline bool get_variation_glyph (hb_codepoint_t  unicode,
-                                     hb_codepoint_t  variation_selector,
-                                     hb_codepoint_t *glyph) const
+    bool get_variation_glyph (hb_codepoint_t  unicode,
+                              hb_codepoint_t  variation_selector,
+                              hb_codepoint_t *glyph) const
     {
-      switch (this->uvs_table->get_glyph_variant (unicode,
-                                                  variation_selector,
-                                                  glyph))
+      switch (this->subtable_uvs->get_glyph_variant (unicode,
+                                                     variation_selector,
+                                                     glyph))
       {
-        case OT::GLYPH_VARIANT_NOT_FOUND:               return false;
-        case OT::GLYPH_VARIANT_FOUND:           return true;
-        case OT::GLYPH_VARIANT_USE_DEFAULT:     break;
+        case GLYPH_VARIANT_NOT_FOUND:   return false;
+        case GLYPH_VARIANT_FOUND:       return true;
+        case GLYPH_VARIANT_USE_DEFAULT: break;
       }
 
       return get_nominal_glyph (unicode, glyph);
     }
 
-    inline void get_all_codepoints (hb_set_t *out) const
+    void collect_unicodes (hb_set_t *out) const
+    {
+      subtable->collect_unicodes (out);
+    }
+    void collect_variation_selectors (hb_set_t *out) const
     {
-      this->get_all_codepoints_func (get_glyph_data, out);
+      subtable_uvs->collect_variation_selectors (out);
+    }
+    void collect_variation_unicodes (hb_codepoint_t variation_selector,
+                                     hb_set_t *out) const
+    {
+      subtable_uvs->collect_variation_unicodes (variation_selector, out);
     }
 
     protected:
     typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
                                               hb_codepoint_t codepoint,
                                               hb_codepoint_t *glyph);
-    typedef void (*hb_cmap_get_all_codepoints_func_t) (const void *obj,
-                                                       hb_set_t *out);
-
-    static inline void null_get_all_codepoints_func (const void *obj, hb_set_t *out)
-    {
-      // NOOP
-    }
 
     template <typename Type>
-    static inline bool get_glyph_from (const void *obj,
-                                       hb_codepoint_t codepoint,
-                                       hb_codepoint_t *glyph)
+    static bool get_glyph_from (const void *obj,
+                                hb_codepoint_t codepoint,
+                                hb_codepoint_t *glyph)
     {
       const Type *typed_obj = (const Type *) obj;
       return typed_obj->get_glyph (codepoint, glyph);
     }
 
     template <typename Type>
-    static inline void get_all_codepoints_from (const void *obj,
-                                                hb_set_t *out)
-    {
-      const Type *typed_obj = (const Type *) obj;
-      typed_obj->get_all_codepoints (out);
-    }
-
-    template <typename Type>
-    static inline bool get_glyph_from_symbol (const void *obj,
+    static bool get_glyph_from_symbol (const void *obj,
                                               hb_codepoint_t codepoint,
                                               hb_codepoint_t *glyph)
     {
@@ -1042,33 +1127,41 @@
     }
 
     private:
-    hb_cmap_get_glyph_func_t get_glyph_func;
-    const void *get_glyph_data;
-    hb_cmap_get_all_codepoints_func_t get_all_codepoints_func;
+    hb_nonnull_ptr_t<const CmapSubtable> subtable;
+    hb_nonnull_ptr_t<const CmapSubtableFormat14> subtable_uvs;
 
-    OT::CmapSubtableFormat4::accelerator_t format4_accel;
+    hb_cmap_get_glyph_func_t get_glyph_funcZ;
+    const void *get_glyph_data;
 
-    const OT::CmapSubtableFormat14 *uvs_table;
-    hb_blob_t *blob;
+    CmapSubtableFormat4::accelerator_t format4_accel;
+
+    hb_blob_ptr_t<cmap> table;
   };
 
   protected:
 
-  inline const CmapSubtable *find_subtable (unsigned int platform_id,
-                                            unsigned int encoding_id) const
+  const CmapSubtable *find_subtable (unsigned int platform_id,
+                                     unsigned int encoding_id) const
   {
     EncodingRecord key;
     key.platformID.set (platform_id);
     key.encodingID.set (encoding_id);
 
-    /* Note: We can use bsearch, but since it has no performance
-     * implications, we use lsearch and as such accept fonts with
-     * unsorted subtable list. */
-    int result = encodingRecord./*bsearch*/lsearch (key);
-    if (result == -1 || !encodingRecord[result].subtable)
+    const EncodingRecord &result = encodingRecord.bsearch (key);
+    if (!result.subtable)
       return nullptr;
 
-    return &(this+encodingRecord[result].subtable);
+    return &(this+result.subtable);
+  }
+
+  public:
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  likely (version == 0) &&
+                  encodingRecord.sanitize (c, this));
   }
 
   protected:
@@ -1079,6 +1172,7 @@
   DEFINE_SIZE_ARRAY (4, encodingRecord);
 };
 
+struct cmap_accelerator_t : cmap::accelerator_t {};
 
 } /* namespace OT */
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-cbdt-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-cbdt-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,7 +27,7 @@
 #ifndef HB_OT_COLOR_CBDT_TABLE_HH
 #define HB_OT_COLOR_CBDT_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * CBLC -- Color Bitmap Location
@@ -45,18 +45,18 @@
 
 struct SmallGlyphMetrics
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  inline void get_extents (hb_glyph_extents_t *extents) const
+  void get_extents (hb_glyph_extents_t *extents) const
   {
     extents->x_bearing = bearingX;
     extents->y_bearing = bearingY;
     extents->width = width;
-    extents->height = -height;
+    extents->height = - (hb_position_t) height;
   }
 
   HBUINT8       height;
@@ -79,7 +79,7 @@
 
 struct SBitLineMetrics
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -108,7 +108,7 @@
 
 struct IndexSubtableHeader
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -124,11 +124,11 @@
 template <typename OffsetType>
 struct IndexSubtableFormat1Or3
 {
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  c->check_array (offsetArrayZ, offsetArrayZ[0].static_size, glyph_count + 1));
+                  offsetArrayZ.sanitize (c, glyph_count + 1));
   }
 
   bool get_image_data (unsigned int idx,
@@ -144,7 +144,8 @@
   }
 
   IndexSubtableHeader   header;
-  Offset<OffsetType>    offsetArrayZ[VAR];
+  UnsizedArrayOf<Offset<OffsetType> >
+                        offsetArrayZ;
   public:
   DEFINE_SIZE_ARRAY(8, offsetArrayZ);
 };
@@ -154,7 +155,7 @@
 
 struct IndexSubtable
 {
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
   {
     TRACE_SANITIZE (this);
     if (!u.header.sanitize (c)) return_trace (false);
@@ -165,7 +166,7 @@
     }
   }
 
-  inline bool get_extents (hb_glyph_extents_t *extents) const
+  bool get_extents (hb_glyph_extents_t *extents HB_UNUSED) const
   {
     switch (u.header.indexFormat) {
     case 2: case 5: /* TODO */
@@ -200,29 +201,28 @@
 
 struct IndexSubtableRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                   firstGlyphIndex <= lastGlyphIndex &&
-                  offsetToSubtable.sanitize (c, this, lastGlyphIndex - firstGlyphIndex + 1));
+                  offsetToSubtable.sanitize (c, base, lastGlyphIndex - firstGlyphIndex + 1));
   }
 
-  inline bool get_extents (hb_glyph_extents_t *extents) const
+  bool get_extents (hb_glyph_extents_t *extents,
+                    const void *base) const
   {
-    return (this+offsetToSubtable).get_extents (extents);
+    return (base+offsetToSubtable).get_extents (extents);
   }
 
-  bool get_image_data (unsigned int gid,
+  bool get_image_data (unsigned int  gid,
+                       const void   *base,
                        unsigned int *offset,
                        unsigned int *length,
                        unsigned int *format) const
   {
-    if (gid < firstGlyphIndex || gid > lastGlyphIndex)
-    {
-      return false;
-    }
-    return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
+    if (gid < firstGlyphIndex || gid > lastGlyphIndex) return false;
+    return (base+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
                                                    offset, length, format);
   }
 
@@ -237,15 +237,10 @@
 {
   friend struct CBDT;
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, count)))
-      return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!indexSubtablesZ[i].sanitize (c, this)))
-        return_trace (false);
-    return_trace (true);
+    return_trace (indexSubtablesZ.sanitize (c, count, this));
   }
 
   public:
@@ -255,17 +250,14 @@
     {
       unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex;
       unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex;
-      if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) {
+      if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex)
         return &indexSubtablesZ[i];
-      }
     }
     return nullptr;
   }
 
   protected:
-  IndexSubtableRecord   indexSubtablesZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY(0, indexSubtablesZ);
+  UnsizedArrayOf<IndexSubtableRecord>   indexSubtablesZ;
 };
 
 struct BitmapSizeTable
@@ -273,23 +265,25 @@
   friend struct CBLC;
   friend struct CBDT;
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                   indexSubtableArrayOffset.sanitize (c, base, numberOfIndexSubtables) &&
-                  c->check_range (&(base+indexSubtableArrayOffset), indexTablesSize) &&
                   horizontal.sanitize (c) &&
                   vertical.sanitize (c));
   }
 
-  const IndexSubtableRecord *find_table (hb_codepoint_t glyph, const void *base) const
+  const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
+                                         const void *base,
+                                         const void **out_base) const
   {
+    *out_base = &(base+indexSubtableArrayOffset);
     return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables);
   }
 
   protected:
-  LOffsetTo<IndexSubtableArray>
+  LNNOffsetTo<IndexSubtableArray>
                         indexSubtableArrayOffset;
   HBUINT32              indexTablesSize;
   HBUINT32              numberOfIndexSubtables;
@@ -338,9 +332,9 @@
 {
   friend struct CBDT;
 
-  static const hb_tag_t tableTag = HB_OT_TAG_CBLC;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_CBLC;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -349,25 +343,30 @@
   }
 
   protected:
-  const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
-                                         unsigned int *x_ppem, unsigned int *y_ppem) const
+  const BitmapSizeTable &choose_strike (hb_font_t *font) const
   {
-    /* TODO: Make it possible to select strike. */
+    unsigned count = sizeTables.len;
+    if (unlikely (!count))
+      return Null(BitmapSizeTable);
 
-    unsigned int count = sizeTables.len;
-    for (uint32_t i = 0; i < count; ++i)
+    unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem);
+    if (!requested_ppem)
+      requested_ppem = 1<<30; /* Choose largest strike. */
+    unsigned int best_i = 0;
+    unsigned int best_ppem = MAX (sizeTables[0].ppemX, sizeTables[0].ppemY);
+
+    for (unsigned int i = 1; i < count; i++)
     {
-      unsigned int startGlyphIndex = sizeTables.arrayZ[i].startGlyphIndex;
-      unsigned int endGlyphIndex = sizeTables.arrayZ[i].endGlyphIndex;
-      if (startGlyphIndex <= glyph && glyph <= endGlyphIndex)
+      unsigned int ppem = MAX (sizeTables[i].ppemX, sizeTables[i].ppemY);
+      if ((requested_ppem <= ppem && ppem < best_ppem) ||
+          (requested_ppem > best_ppem && ppem > best_ppem))
       {
-        *x_ppem = sizeTables[i].ppemX;
-        *y_ppem = sizeTables[i].ppemY;
-        return sizeTables[i].find_table (glyph, this);
+        best_i = i;
+        best_ppem = ppem;
       }
     }
 
-    return nullptr;
+    return sizeTables[best_i];
   }
 
   protected:
@@ -379,60 +378,42 @@
 
 struct CBDT
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  likely (version.major == 2 || version.major == 3));
-  }
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_CBDT;
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
     {
-      upem = hb_face_get_upem (face);
-
-      cblc_blob = Sanitizer<CBLC>().sanitize (face->reference_table (HB_OT_TAG_CBLC));
-      cbdt_blob = Sanitizer<CBDT>().sanitize (face->reference_table (HB_OT_TAG_CBDT));
-      cbdt_len = hb_blob_get_length (cbdt_blob);
+      cblc = hb_sanitize_context_t().reference_table<CBLC> (face);
+      cbdt = hb_sanitize_context_t().reference_table<CBDT> (face);
 
-      if (hb_blob_get_length (cblc_blob) == 0) {
-        cblc = nullptr;
-        cbdt = nullptr;
-        return;  /* Not a bitmap font. */
-      }
-      cblc = cblc_blob->as<CBLC> ();
-      cbdt = cbdt_blob->as<CBDT> ();
-
+      upem = hb_face_get_upem (face);
     }
 
-    inline void fini (void)
+    void fini ()
     {
-      hb_blob_destroy (this->cblc_blob);
-      hb_blob_destroy (this->cbdt_blob);
+      this->cblc.destroy ();
+      this->cbdt.destroy ();
     }
 
-    inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+    bool get_extents (hb_font_t *font, hb_codepoint_t glyph,
+                      hb_glyph_extents_t *extents) const
     {
-      unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */
-
-      if (!cblc)
-        return false;  // Not a color bitmap font.
-
-      const IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem);
-      if (!subtable_record || !x_ppem || !y_ppem)
+      const void *base;
+      const BitmapSizeTable &strike = this->cblc->choose_strike (font);
+      const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base);
+      if (!subtable_record || !strike.ppemX || !strike.ppemY)
         return false;
 
-      if (subtable_record->get_extents (extents))
+      if (subtable_record->get_extents (extents, base))
         return true;
 
       unsigned int image_offset = 0, image_length = 0, image_format = 0;
-      if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format))
+      if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format))
         return false;
 
       {
+        unsigned int cbdt_len = cbdt.get_length ();
         if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
           return false;
 
@@ -441,98 +422,114 @@
           case 17: {
             if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
               return false;
-
             const GlyphBitmapDataFormat17& glyphFormat17 =
                 StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
             glyphFormat17.glyphMetrics.get_extents (extents);
+            break;
           }
-          break;
+          case 18: {
+            if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
+              return false;
+            const GlyphBitmapDataFormat18& glyphFormat18 =
+                StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
+            glyphFormat18.glyphMetrics.get_extents (extents);
+            break;
+          }
           default:
             // TODO: Support other image formats.
             return false;
         }
       }
 
-      /* Convert to the font units. */
-      extents->x_bearing *= upem / (float) x_ppem;
-      extents->y_bearing *= upem / (float) y_ppem;
-      extents->width *= upem / (float) x_ppem;
-      extents->height *= upem / (float) y_ppem;
+      /* Convert to font units. */
+      double x_scale = upem / (double) strike.ppemX;
+      double y_scale = upem / (double) strike.ppemY;
+      extents->x_bearing = round (extents->x_bearing * x_scale);
+      extents->y_bearing = round (extents->y_bearing * y_scale);
+      extents->width = round (extents->width * x_scale);
+      extents->height = round (extents->height * y_scale);
 
       return true;
     }
 
-    inline void dump (void (*callback) (const uint8_t* data, unsigned int length,
-        unsigned int group, unsigned int gid)) const
+    hb_blob_t* reference_png (hb_font_t      *font,
+                                     hb_codepoint_t  glyph) const
     {
-      if (!cblc)
-        return;  // Not a color bitmap font.
+      const void *base;
+      const BitmapSizeTable &strike = this->cblc->choose_strike (font);
+      const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base);
+      if (!subtable_record || !strike.ppemX || !strike.ppemY)
+        return hb_blob_get_empty ();
 
-      for (unsigned int i = 0; i < cblc->sizeTables.len; ++i)
+      unsigned int image_offset = 0, image_length = 0, image_format = 0;
+      if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format))
+        return hb_blob_get_empty ();
+
       {
-        const BitmapSizeTable &sizeTable = cblc->sizeTables[i];
-        const IndexSubtableArray &subtable_array = cblc+sizeTable.indexSubtableArrayOffset;
-        for (unsigned int j = 0; j < sizeTable.numberOfIndexSubtables; ++j)
-        {
-          const IndexSubtableRecord &subtable_record = subtable_array.indexSubtablesZ[j];
-          for (unsigned int gid = subtable_record.firstGlyphIndex;
-                gid <= subtable_record.lastGlyphIndex; ++gid)
-          {
-            unsigned int image_offset = 0, image_length = 0, image_format = 0;
-
-            if (!subtable_record.get_image_data (gid,
-                  &image_offset, &image_length, &image_format))
-              continue;
+        unsigned int cbdt_len = cbdt.get_length ();
+        if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
+          return hb_blob_get_empty ();
 
-            switch (image_format)
-            {
-            case 17: {
-              const GlyphBitmapDataFormat17& glyphFormat17 =
-                StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
-              callback ((const uint8_t *) &glyphFormat17.data.arrayZ,
-                glyphFormat17.data.len, i, gid);
-            }
-            break;
-            case 18: {
-              const GlyphBitmapDataFormat18& glyphFormat18 =
-                StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
-              callback ((const uint8_t *) &glyphFormat18.data.arrayZ,
-                glyphFormat18.data.len, i, gid);
-            }
-            break;
-            case 19: {
-              const GlyphBitmapDataFormat19& glyphFormat19 =
-                StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset);
-              callback ((const uint8_t *) &glyphFormat19.data.arrayZ,
-                glyphFormat19.data.len, i, gid);
-            }
-            break;
-            default:
-              continue;
-            }
+        switch (image_format)
+        {
+          case 17: {
+            if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
+              return hb_blob_get_empty ();
+            const GlyphBitmapDataFormat17& glyphFormat17 =
+              StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
+            return hb_blob_create_sub_blob (cbdt.get_blob (),
+                                            image_offset + GlyphBitmapDataFormat17::min_size,
+                                            glyphFormat17.data.len);
+          }
+          case 18: {
+            if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
+              return hb_blob_get_empty ();
+            const GlyphBitmapDataFormat18& glyphFormat18 =
+              StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
+            return hb_blob_create_sub_blob (cbdt.get_blob (),
+                                            image_offset + GlyphBitmapDataFormat18::min_size,
+                                            glyphFormat18.data.len);
+          }
+          case 19: {
+            if (unlikely (image_length < GlyphBitmapDataFormat19::min_size))
+              return hb_blob_get_empty ();
+            const GlyphBitmapDataFormat19& glyphFormat19 =
+              StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset);
+            return hb_blob_create_sub_blob (cbdt.get_blob (),
+                                            image_offset + GlyphBitmapDataFormat19::min_size,
+                                            glyphFormat19.data.len);
           }
         }
       }
+
+      return hb_blob_get_empty ();
     }
 
+    bool has_data () const { return cbdt.get_length (); }
+
     private:
-    hb_blob_t *cblc_blob;
-    hb_blob_t *cbdt_blob;
-    const CBLC *cblc;
-    const CBDT *cbdt;
+    hb_blob_ptr_t<CBLC> cblc;
+    hb_blob_ptr_t<CBDT> cbdt;
 
-    unsigned int cbdt_len;
     unsigned int upem;
   };
 
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  likely (version.major == 2 || version.major == 3));
+  }
 
   protected:
-  FixedVersion<>        version;
-  HBUINT8               dataZ[VAR];
+  FixedVersion<>                version;
+  UnsizedArrayOf<HBUINT8>       dataZ;
   public:
   DEFINE_SIZE_ARRAY(4, dataZ);
 };
 
+struct CBDT_accelerator_t : CBDT::accelerator_t {};
+
 } /* namespace OT */
 
 #endif /* HB_OT_COLOR_CBDT_TABLE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-colr-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-colr-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -25,7 +25,7 @@
 #ifndef HB_OT_COLOR_COLR_TABLE_HH
 #define HB_OT_COLOR_COLR_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * COLR -- Color
@@ -39,55 +39,82 @@
 
 struct LayerRecord
 {
-  friend struct COLR;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  protected:
-  GlyphID       glyphid;        /* Glyph ID of layer glyph */
-  HBUINT16      colorIdx;       /* Index value to use with a selected color palette */
+  public:
+  GlyphID       glyphId;        /* Glyph ID of layer glyph */
+  Index         colorIdx;       /* Index value to use with a
+                                 * selected color palette.
+                                 * An index value of 0xFFFF
+                                 * is a special case indicating
+                                 * that the text foreground
+                                 * color (defined by a
+                                 * higher-level client) should
+                                 * be used and shall not be
+                                 * treated as actual index
+                                 * into CPAL ColorRecord array. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 struct BaseGlyphRecord
 {
-  friend struct COLR;
+  int cmp (hb_codepoint_t g) const
+  { return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this)));
   }
 
-  inline int cmp (hb_codepoint_t g) const {
-    return g < glyphid ? -1 : g > glyphid ? 1 : 0;
-  }
-
-  protected:
-  GlyphID       glyphid;        /* Glyph ID of reference glyph */
-  HBUINT16      firstLayerIdx;  /* Index to the layer record */
-  HBUINT16      numLayers;      /* Number of color layers associated with this glyph */
+  public:
+  GlyphID       glyphId;        /* Glyph ID of reference glyph */
+  HBUINT16      firstLayerIdx;  /* Index (from beginning of
+                                 * the Layer Records) to the
+                                 * layer record. There will be
+                                 * numLayers consecutive entries
+                                 * for this base glyph. */
+  HBUINT16      numLayers;      /* Number of color layers
+                                 * associated with this glyph */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
-static int compare_bgr (const void *pa, const void *pb)
-{
-  const hb_codepoint_t *a = (const hb_codepoint_t *) pa;
-  const BaseGlyphRecord *b = (const BaseGlyphRecord *) pb;
-  return b->cmp (*a);
-}
-
 struct COLR
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_COLR;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
+
+  bool has_data () const { return numBaseGlyphs; }
+
+  unsigned int get_glyph_layers (hb_codepoint_t       glyph,
+                                 unsigned int         start_offset,
+                                 unsigned int        *count, /* IN/OUT.  May be NULL. */
+                                 hb_ot_color_layer_t *layers /* OUT.     May be NULL. */) const
+  {
+    const BaseGlyphRecord &record = (this+baseGlyphsZ).bsearch (numBaseGlyphs, glyph);
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+    hb_array_t<const LayerRecord> all_layers ((this+layersZ).arrayZ, numLayers);
+    hb_array_t<const LayerRecord> glyph_layers = all_layers.sub_array (record.firstLayerIdx,
+                                                                       record.numLayers);
+    if (count)
+    {
+      hb_array_t<const LayerRecord> segment_layers = glyph_layers.sub_array (start_offset, *count);
+      *count = segment_layers.length;
+      for (unsigned int i = 0; i < segment_layers.length; i++)
+      {
+        layers[i].glyph = segment_layers.arrayZ[i].glyphId;
+        layers[i].color_index = segment_layers.arrayZ[i].colorIdx;
+      }
+    }
+    return glyph_layers.length;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
@@ -95,45 +122,14 @@
                           (this+layersZ).sanitize (c, numLayers)));
   }
 
-  inline bool get_base_glyph_record (hb_codepoint_t glyph_id,
-                                     unsigned int *first_layer /* OUT */,
-                                     unsigned int *num_layers /* OUT */) const
-  {
-    const BaseGlyphRecord* record;
-    record = (BaseGlyphRecord *) bsearch (&glyph_id, &(this+baseGlyphsZ), numBaseGlyphs,
-                                          sizeof (BaseGlyphRecord), compare_bgr);
-    if (unlikely (!record))
-      return false;
-
-    *first_layer = record->firstLayerIdx;
-    *num_layers = record->numLayers;
-    return true;
-  }
-
-  inline bool get_layer_record (unsigned int record,
-                                hb_codepoint_t *glyph_id /* OUT */,
-                                unsigned int *palette_index /* OUT */) const
-  {
-    if (unlikely (record >= numLayers))
-    {
-      *glyph_id = 0;
-      *palette_index = 0xFFFF;
-      return false;
-    }
-    const LayerRecord &layer = (this+layersZ)[record];
-    *glyph_id = layer.glyphid;
-    *palette_index = layer.colorIdx;
-    return true;
-  }
-
   protected:
-  HBUINT16      version;        /* Table version number */
-  HBUINT16      numBaseGlyphs;  /* Number of Base Glyph Records */
-  LOffsetTo<UnsizedArrayOf<BaseGlyphRecord> >
+  HBUINT16      version;        /* Table version number (starts at 0). */
+  HBUINT16      numBaseGlyphs;  /* Number of Base Glyph Records. */
+  LNNOffsetTo<SortedUnsizedArrayOf<BaseGlyphRecord> >
                 baseGlyphsZ;    /* Offset to Base Glyph records. */
-  LOffsetTo<UnsizedArrayOf<LayerRecord> >
-                layersZ;        /* Offset to Layer Records */
-  HBUINT16      numLayers;      /* Number of Layer Records */
+  LNNOffsetTo<UnsizedArrayOf<LayerRecord> >
+                layersZ;        /* Offset to Layer Records. */
+  HBUINT16      numLayers;      /* Number of Layer Records. */
   public:
   DEFINE_SIZE_STATIC (14);
 };
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-cpal-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-cpal-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -28,54 +28,9 @@
 #ifndef HB_OT_COLOR_CPAL_TABLE_HH
 #define HB_OT_COLOR_CPAL_TABLE_HH
 
-#include "hb-open-type-private.hh"
-
-
-/*
- * Following parts to be moved to a public header.
- */
-
-/**
- * hb_ot_color_t:
- * ARGB data type for holding color values.
- *
- * Since: REPLACEME
- */
-typedef uint32_t hb_ot_color_t;
-
-
-/**
- * hb_ot_color_palette_flags_t:
- * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special to note about a color palette.
- * @HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND: flag indicating that the color palette is suitable for rendering text on light background.
- * @HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND: flag indicating that the color palette is suitable for rendering text on dark background.
- *
- * Since: REPLACEME
- */
-typedef enum { /*< flags >*/
-  HB_OT_COLOR_PALETTE_FLAG_DEFAULT = 0x00000000u,
-  HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND = 0x00000001u,
-  HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND = 0x00000002u,
-} hb_ot_color_palette_flags_t;
-
-// HB_EXTERN unsigned int
-// hb_ot_color_get_palette_count (hb_face_t *face);
-
-// HB_EXTERN unsigned int
-// hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette);
-
-// HB_EXTERN hb_ot_color_palette_flags_t
-// hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette);
-
-// HB_EXTERN unsigned int
-// hb_ot_color_get_palette_colors (hb_face_t       *face,
-//                              unsigned int     palette, /* default=0 */
-//                              unsigned int     start_offset,
-//                              unsigned int    *color_count /* IN/OUT */,
-//                              hb_ot_color_t   *colors /* OUT */);
-
-
-
+#include "hb-open-type.hh"
+#include "hb-ot-color.h"
+#include "hb-ot-name.h"
 
 
 /*
@@ -92,43 +47,57 @@
 {
   friend struct CPAL;
 
-  inline bool
-  sanitize (hb_sanitize_context_t *c, const void *base, unsigned int palettes) const
+  private:
+  hb_ot_color_palette_flags_t get_palette_flags (const void *base,
+                                                 unsigned int palette_index,
+                                                 unsigned int palette_count) const
+  {
+    if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
+    return (hb_ot_color_palette_flags_t) (uint32_t)
+           (base+paletteFlagsZ).as_array (palette_count)[palette_index];
+  }
+
+  hb_ot_name_id_t get_palette_name_id (const void *base,
+                                       unsigned int palette_index,
+                                       unsigned int palette_count) const
+  {
+    if (!paletteLabelsZ) return HB_OT_NAME_ID_INVALID;
+    return (base+paletteLabelsZ).as_array (palette_count)[palette_index];
+  }
+
+  hb_ot_name_id_t get_color_name_id (const void *base,
+                                     unsigned int color_index,
+                                     unsigned int color_count) const
+  {
+    if (!colorLabelsZ) return HB_OT_NAME_ID_INVALID;
+    return (base+colorLabelsZ).as_array (color_count)[color_index];
+  }
+
+  public:
+  bool sanitize (hb_sanitize_context_t *c,
+                 const void *base,
+                 unsigned int palette_count,
+                 unsigned int color_count) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  (base+paletteFlagsZ).sanitize (c, palettes) &&
-                  (base+paletteLabelZ).sanitize (c, palettes) &&
-                  (base+paletteEntryLabelZ).sanitize (c, palettes));
-  }
-
-  private:
-  inline hb_ot_color_palette_flags_t
-  get_palette_flags (const void *base, unsigned int palette) const
-  {
-    // range checked at the CPAL caller
-    return (hb_ot_color_palette_flags_t) (uint32_t) (base+paletteFlagsZ)[palette];
-  }
-
-  inline unsigned int
-  get_palette_name_id (const void *base, unsigned int palette) const
-  {
-    // range checked at the CPAL caller
-    return (base+paletteLabelZ)[palette];
+                  (!paletteFlagsZ  || (base+paletteFlagsZ).sanitize (c, palette_count)) &&
+                  (!paletteLabelsZ || (base+paletteLabelsZ).sanitize (c, palette_count)) &&
+                  (!colorLabelsZ   || (base+colorLabelsZ).sanitize (c, color_count)));
   }
 
   protected:
-  LOffsetTo<UnsizedArrayOf<HBUINT32> >
+  LNNOffsetTo<UnsizedArrayOf<HBUINT32> >
                 paletteFlagsZ;          /* Offset from the beginning of CPAL table to
                                          * the Palette Type Array. Set to 0 if no array
                                          * is provided. */
-  LOffsetTo<UnsizedArrayOf<HBUINT16> >
-                paletteLabelZ;          /* Offset from the beginning of CPAL table to
-                                         * the Palette Labels Array. Set to 0 if no
+  LNNOffsetTo<UnsizedArrayOf<NameID> >
+                paletteLabelsZ;         /* Offset from the beginning of CPAL table to
+                                         * the palette labels array. Set to 0 if no
                                          * array is provided. */
-  LOffsetTo<UnsizedArrayOf<HBUINT16> >
-                paletteEntryLabelZ;     /* Offset from the beginning of CPAL table to
-                                         * the Palette Entry Label Array. Set to 0
+  LNNOffsetTo<UnsizedArrayOf<NameID> >
+                colorLabelsZ;           /* Offset from the beginning of CPAL table to
+                                         * the color labels array. Set to 0
                                          * if no array is provided. */
   public:
   DEFINE_SIZE_STATIC (12);
@@ -138,76 +107,76 @@
 
 struct CPAL
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_CPAL;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_CPAL;
+
+  bool has_data () const { return numPalettes; }
+
+  unsigned int get_size () const
+  { return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!(c->check_struct (this) &&   // it checks colorRecordIndices also
-                                                // see #get_size
-                    (this+colorRecordsZ).sanitize (c, numColorRecords))))
-      return_trace (false);
+  unsigned int get_palette_count () const { return numPalettes; }
+  unsigned int get_color_count () const   { return numColors; }
+
+  hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const
+  { return v1 ().get_palette_flags (this, palette_index, numPalettes); }
+
+  hb_ot_name_id_t get_palette_name_id (unsigned int palette_index) const
+  { return v1 ().get_palette_name_id (this, palette_index, numPalettes); }
+
+  hb_ot_name_id_t get_color_name_id (unsigned int color_index) const
+  { return v1 ().get_color_name_id (this, color_index, numColors); }
 
-    // Check for indices sanity so no need for doing it runtime
-    for (unsigned int i = 0; i < numPalettes; ++i)
-      if (unlikely (colorRecordIndicesZ[i] + numPaletteEntries > numColorRecords))
-        return_trace (false);
-
-    // If version is zero, we are done here; otherwise we need to check tail also
-    if (version == 0)
-      return_trace (true);
-
-    const CPALV1Tail &v1 = StructAfter<CPALV1Tail> (*this);
-    return_trace (likely (v1.sanitize (c, this, numPalettes)));
-  }
-
-  inline unsigned int get_size (void) const
+  unsigned int get_palette_colors (unsigned int  palette_index,
+                                   unsigned int  start_offset,
+                                   unsigned int *color_count, /* IN/OUT.  May be NULL. */
+                                   hb_color_t   *colors       /* OUT.     May be NULL. */) const
   {
-    return min_size + numPalettes * sizeof (HBUINT16);
+    if (unlikely (palette_index >= numPalettes))
+    {
+      if (color_count) *color_count = 0;
+      return 0;
+    }
+    unsigned int start_index = colorRecordIndicesZ[palette_index];
+    hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords);
+    hb_array_t<const BGRAColor> palette_colors = all_colors.sub_array (start_index,
+                                                                       numColors);
+    if (color_count)
+    {
+      hb_array_t<const BGRAColor> segment_colors = palette_colors.sub_array (start_offset, *color_count);
+      /* Always return numColors colors per palette even if it has out-of-bounds start index. */
+      unsigned int count = MIN<unsigned int> (MAX<int> (numColors - start_offset, 0), *color_count);
+      *color_count = count;
+      for (unsigned int i = 0; i < count; i++)
+        colors[i] = segment_colors[i]; /* Bound-checked read. */
+    }
+    return numColors;
   }
 
-  inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette) const
+  private:
+  const CPALV1Tail& v1 () const
   {
-    if (unlikely (version == 0 || palette >= numPalettes))
-      return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
-
-    const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
-    return cpal1.get_palette_flags (this, palette);
+    if (version == 0) return Null(CPALV1Tail);
+    return StructAfter<CPALV1Tail> (*this);
   }
 
-  inline unsigned int get_palette_name_id (unsigned int palette) const
-  {
-    if (unlikely (version == 0 || palette >= numPalettes))
-      return 0xFFFF;
-
-    const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
-    return cpal1.get_palette_name_id (this, palette);
-  }
-
-  inline unsigned int get_palette_count () const
+  public:
+  bool sanitize (hb_sanitize_context_t *c) const
   {
-    return numPalettes;
-  }
-
-  inline hb_ot_color_t
-  get_color_record_argb (unsigned int color_index, unsigned int palette) const
-  {
-    if (unlikely (color_index >= numPaletteEntries || palette >= numPalettes))
-      return 0;
-
-    // No need for more range check as it is already done on #sanitize
-    const UnsizedArrayOf<BGRAColor>& color_records = this+colorRecordsZ;
-    return color_records[colorRecordIndicesZ[palette] + color_index];
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  (this+colorRecordsZ).sanitize (c, numColorRecords) &&
+                  colorRecordIndicesZ.sanitize (c, numPalettes) &&
+                  (version == 0 || v1 ().sanitize (c, this, numPalettes, numColors)));
   }
 
   protected:
   HBUINT16      version;                /* Table version number */
   /* Version 0 */
-  HBUINT16      numPaletteEntries;      /* Number of palette entries in each palette. */
+  HBUINT16      numColors;              /* Number of colors in each palette. */
   HBUINT16      numPalettes;            /* Number of palettes in the table. */
   HBUINT16      numColorRecords;        /* Total number of color records, combined for
                                          * all palettes. */
-  LOffsetTo<UnsizedArrayOf<BGRAColor> >
+  LNNOffsetTo<UnsizedArrayOf<BGRAColor> >
                 colorRecordsZ;          /* Offset from the beginning of CPAL table to
                                          * the first ColorRecord. */
   UnsizedArrayOf<HBUINT16>
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-sbix-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-sbix-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -25,7 +25,7 @@
 #ifndef HB_OT_COLOR_SBIX_TABLE_HH
 #define HB_OT_COLOR_SBIX_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * sbix -- Standard Bitmap Graphics
@@ -62,19 +62,65 @@
 
 struct SBIXStrike
 {
-  friend struct sbix;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  imageOffsetsZ.sanitize_shallow (c, c->num_glyphs + 1));
+                  imageOffsetsZ.sanitize_shallow (c, c->get_num_glyphs () + 1));
   }
 
-  protected:
+  hb_blob_t *get_glyph_blob (unsigned int  glyph_id,
+                             hb_blob_t    *sbix_blob,
+                             hb_tag_t      file_type,
+                             int          *x_offset,
+                             int          *y_offset,
+                             unsigned int  num_glyphs,
+                             unsigned int *strike_ppem) const
+  {
+    if (unlikely (!ppem)) return hb_blob_get_empty (); /* To get Null() object out of the way. */
+
+    unsigned int retry_count = 8;
+    unsigned int sbix_len = sbix_blob->length;
+    unsigned int strike_offset = (const char *) this - (const char *) sbix_blob->data;
+    assert (strike_offset < sbix_len);
+
+  retry:
+    if (unlikely (glyph_id >= num_glyphs ||
+                  imageOffsetsZ[glyph_id + 1] <= imageOffsetsZ[glyph_id] ||
+                  imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] <= SBIXGlyph::min_size ||
+                  (unsigned int) imageOffsetsZ[glyph_id + 1] > sbix_len - strike_offset))
+      return hb_blob_get_empty ();
+
+    unsigned int glyph_offset = strike_offset + (unsigned int) imageOffsetsZ[glyph_id] + SBIXGlyph::min_size;
+    unsigned int glyph_length = imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] - SBIXGlyph::min_size;
+
+    const SBIXGlyph *glyph = &(this+imageOffsetsZ[glyph_id]);
+
+    if (glyph->graphicType == HB_TAG ('d','u','p','e'))
+    {
+      if (glyph_length >= 2)
+      {
+        glyph_id = *((HBUINT16 *) &glyph->data);
+        if (retry_count--)
+          goto retry;
+      }
+      return hb_blob_get_empty ();
+    }
+
+    if (unlikely (file_type != glyph->graphicType))
+      return hb_blob_get_empty ();
+
+    if (strike_ppem) *strike_ppem = ppem;
+    if (x_offset) *x_offset = glyph->xOffset;
+    if (y_offset) *y_offset = glyph->yOffset;
+    return hb_blob_create_sub_blob (sbix_blob, glyph_offset, glyph_length);
+  }
+
+  public:
   HBUINT16      ppem;           /* The PPEM size for which this strike was designed. */
   HBUINT16      resolution;     /* The device pixel density (in PPI) for which this
                                  * strike was designed. (E.g., 96 PPI, 192 PPI.) */
+  protected:
   UnsizedArrayOf<LOffsetTo<SBIXGlyph> >
                 imageOffsetsZ;  /* Offset from the beginning of the strike data header
                                  * to bitmap data for an individual glyph ID. */
@@ -84,70 +130,157 @@
 
 struct sbix
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_sbix;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_sbix;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) && strikes.sanitize (c, this)));
-  }
+  bool has_data () const { return version; }
+
+  const SBIXStrike &get_strike (unsigned int i) const { return this+strikes[i]; }
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
     {
-      num_glyphs = hb_face_get_glyph_count (face);
+      table = hb_sanitize_context_t().reference_table<sbix> (face);
+      num_glyphs = face->get_num_glyphs ();
+    }
+    void fini () { table.destroy (); }
 
-      OT::Sanitizer<OT::sbix> sanitizer;
-      sanitizer.set_num_glyphs (num_glyphs);
-      sbix_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_sbix));
-      sbix_len = hb_blob_get_length (sbix_blob);
-      sbix_table = sbix_blob->as<OT::sbix> ();
+    bool has_data () const { return table->has_data (); }
 
+    bool get_extents (hb_font_t          *font,
+                      hb_codepoint_t      glyph,
+                      hb_glyph_extents_t *extents) const
+    {
+      /* We only support PNG right now, and following function checks type. */
+      return get_png_extents (font, glyph, extents);
     }
 
-    inline void fini (void)
-    {
-      hb_blob_destroy (sbix_blob);
-    }
-
-    inline void dump (void (*callback) (const uint8_t* data, unsigned int length,
-                                        unsigned int group, unsigned int gid)) const
+    hb_blob_t *reference_png (hb_font_t      *font,
+                              hb_codepoint_t  glyph_id,
+                              int            *x_offset,
+                              int            *y_offset,
+                              unsigned int   *available_ppem) const
     {
-      for (unsigned group = 0; group < sbix_table->strikes.len; ++group)
-      {
-        const SBIXStrike &strike = sbix_table->strikes[group](sbix_table);
-        for (unsigned int glyph = 0; glyph < num_glyphs; ++glyph)
-          if (strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] > 0)
-          {
-            const SBIXGlyph &sbixGlyph = strike.imageOffsetsZ[glyph]((const void *) &strike);
-            callback ((const uint8_t*) &sbixGlyph.data,
-                      strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] - 8,
-                      group, glyph);
-          }
-      }
+      return choose_strike (font).get_glyph_blob (glyph_id, table.get_blob (),
+                                                  HB_TAG ('p','n','g',' '),
+                                                  x_offset, y_offset,
+                                                  num_glyphs, available_ppem);
     }
 
     private:
-    hb_blob_t *sbix_blob;
-    const sbix *sbix_table;
+
+    const SBIXStrike &choose_strike (hb_font_t *font) const
+    {
+      unsigned count = table->strikes.len;
+      if (unlikely (!count))
+        return Null(SBIXStrike);
+
+      unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem);
+      if (!requested_ppem)
+        requested_ppem = 1<<30; /* Choose largest strike. */
+      /* TODO Add DPI sensitivity as well? */
+      unsigned int best_i = 0;
+      unsigned int best_ppem = table->get_strike (0).ppem;
+
+      for (unsigned int i = 1; i < count; i++)
+      {
+        unsigned int ppem = (table->get_strike (i)).ppem;
+        if ((requested_ppem <= ppem && ppem < best_ppem) ||
+            (requested_ppem > best_ppem && ppem > best_ppem))
+        {
+          best_i = i;
+          best_ppem = ppem;
+        }
+      }
+
+      return table->get_strike (best_i);
+    }
+
+    struct PNGHeader
+    {
+      HBUINT8   signature[8];
+      struct
+      {
+        struct
+        {
+          HBUINT32      length;
+          Tag           type;
+        }               header;
+        HBUINT32        width;
+        HBUINT32        height;
+        HBUINT8         bitDepth;
+        HBUINT8         colorType;
+        HBUINT8         compressionMethod;
+        HBUINT8         filterMethod;
+        HBUINT8         interlaceMethod;
+      } IHDR;
 
-    unsigned int sbix_len;
+      public:
+      DEFINE_SIZE_STATIC (29);
+    };
+
+    bool get_png_extents (hb_font_t          *font,
+                          hb_codepoint_t      glyph,
+                          hb_glyph_extents_t *extents) const
+    {
+      /* Following code is safe to call even without data.
+       * But faster to short-circuit. */
+      if (!has_data ())
+        return false;
+
+      int x_offset = 0, y_offset = 0;
+      unsigned int strike_ppem = 0;
+      hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
+
+      const PNGHeader &png = *blob->as<PNGHeader>();
+
+      extents->x_bearing = x_offset;
+      extents->y_bearing = y_offset;
+      extents->width     = png.IHDR.width;
+      extents->height    = png.IHDR.height;
+
+      /* Convert to font units. */
+      if (strike_ppem)
+      {
+        double scale = font->face->get_upem () / (double) strike_ppem;
+        extents->x_bearing = round (extents->x_bearing * scale);
+        extents->y_bearing = round (extents->y_bearing * scale);
+        extents->width = round (extents->width * scale);
+        extents->height = round (extents->height * scale);
+      }
+
+      hb_blob_destroy (blob);
+
+      return strike_ppem;
+    }
+
+    private:
+    hb_blob_ptr_t<sbix> table;
+
     unsigned int num_glyphs;
+  };
 
-  };
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          version >= 1 &&
+                          strikes.sanitize (c, this)));
+  }
 
   protected:
   HBUINT16      version;        /* Table version number — set to 1 */
   HBUINT16      flags;          /* Bit 0: Set to 1. Bit 1: Draw outlines.
                                  * Bits 2 to 15: reserved (set to 0). */
-  LArrayOf<LOffsetTo<SBIXStrike> >
+  LOffsetLArrayOf<SBIXStrike>
                 strikes;        /* Offsets from the beginning of the 'sbix'
                                  * table to data for each individual bitmap strike. */
   public:
   DEFINE_SIZE_ARRAY (8, strikes);
 };
 
+struct sbix_accelerator_t : sbix::accelerator_t {};
+
 } /* namespace OT */
 
 #endif /* HB_OT_COLOR_SBIX_TABLE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-svg-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-svg-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -25,7 +25,7 @@
 #ifndef HB_OT_COLOR_SVG_TABLE_HH
 #define HB_OT_COLOR_SVG_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * SVG -- SVG (Scalable Vector Graphics)
@@ -40,13 +40,21 @@
 
 struct SVGDocumentIndexEntry
 {
-  friend struct SVG;
+  int cmp (hb_codepoint_t g) const
+  { return g < startGlyphID ? -1 : g > endGlyphID ? 1 : 0; }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void* base) const
+  hb_blob_t *reference_blob (hb_blob_t *svg_blob, unsigned int index_offset) const
+  {
+    return hb_blob_create_sub_blob (svg_blob,
+                                    index_offset + (unsigned int) svgDoc,
+                                    svgDocLength);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  (base+svgDoc).sanitize (c, svgDocLength));
+                  svgDoc.sanitize (c, base, svgDocLength));
   }
 
   protected:
@@ -54,91 +62,62 @@
                                  * this index entry. */
   HBUINT16      endGlyphID;     /* The last glyph ID in the range described by
                                  * this index entry. Must be >= startGlyphID. */
-  LOffsetTo<UnsizedArrayOf<HBUINT8> >
+  LNNOffsetTo<UnsizedArrayOf<HBUINT8> >
                 svgDoc;         /* Offset from the beginning of the SVG Document Index
                                  * to an SVG document. Must be non-zero. */
-  HBUINT32 svgDocLength;        /* Length of the SVG document.
+  HBUINT32      svgDocLength;   /* Length of the SVG document.
                                  * Must be non-zero. */
   public:
   DEFINE_SIZE_STATIC (12);
 };
 
-struct SVGDocumentIndex
-{
-  friend struct SVG;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  entries.sanitize (c, this));
-  }
-
-  protected:
-  ArrayOf<SVGDocumentIndexEntry>
-                entries;        /* Array of SVG Document Index Entries. */
-  public:
-  DEFINE_SIZE_ARRAY (2, entries);
-};
-
 struct SVG
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_SVG;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_SVG;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-                          (this+svgDocIndex).sanitize (c)));
-  }
+  bool has_data () const { return svgDocEntries; }
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
+    { table = hb_sanitize_context_t().reference_table<SVG> (face); }
+    void fini () { table.destroy (); }
+
+    hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const
     {
-      OT::Sanitizer<OT::SVG> sanitizer;
-      svg_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_SVG));
-      svg_len = hb_blob_get_length (svg_blob);
-      svg = svg_blob->as<OT::SVG> ();
-
-    }
-
-    inline void fini (void)
-    {
-      hb_blob_destroy (svg_blob);
+      return table->get_glyph_entry (glyph_id).reference_blob (table.get_blob (),
+                                                               table->svgDocEntries);
     }
 
-    inline void
-    dump (void (*callback) (const uint8_t* data, unsigned int length,
-                            unsigned int start_glyph, unsigned int end_glyph)) const
-    {
-      const SVGDocumentIndex &index = svg+svg->svgDocIndex;
-      const ArrayOf<SVGDocumentIndexEntry> &entries = index.entries;
-      for (unsigned int i = 0; i < entries.len; ++i)
-      {
-        const SVGDocumentIndexEntry &entry = entries[i];
-        callback ((const uint8_t*) &entry.svgDoc (&index), entry.svgDocLength,
-                                                  entry.startGlyphID, entry.endGlyphID);
-      }
-    }
+    bool has_data () const { return table->has_data (); }
 
     private:
-    hb_blob_t *svg_blob;
-    const SVG *svg;
+    hb_blob_ptr_t<SVG> table;
+  };
+
+  const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const
+  { return (this+svgDocEntries).bsearch (glyph_id); }
 
-    unsigned int svg_len;
-  };
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          (this+svgDocEntries).sanitize_shallow (c)));
+  }
 
   protected:
   HBUINT16      version;        /* Table version (starting at 0). */
-  LOffsetTo<SVGDocumentIndex>
-                svgDocIndex;    /* Offset (relative to the start of the SVG table) to the
+  LOffsetTo<SortedArrayOf<SVGDocumentIndexEntry> >
+                svgDocEntries;  /* Offset (relative to the start of the SVG table) to the
                                  * SVG Documents Index. Must be non-zero. */
+                                /* Array of SVG Document Index Entries. */
   HBUINT32      reserved;       /* Set to 0. */
   public:
   DEFINE_SIZE_STATIC (10);
 };
 
+struct SVG_accelerator_t : SVG::accelerator_t {};
+
 } /* namespace OT */
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,299 @@
+/*
+ * Copyright © 2016  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): Sascha Brawer, Behdad Esfahbod
+ */
+
+#include "hb-open-type.hh"
+#include "hb-ot-color-cbdt-table.hh"
+#include "hb-ot-color-colr-table.hh"
+#include "hb-ot-color-cpal-table.hh"
+#include "hb-ot-color-sbix-table.hh"
+#include "hb-ot-color-svg-table.hh"
+#include "hb-ot-face.hh"
+#include "hb-ot.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "hb-ot-layout.hh"
+
+
+/**
+ * SECTION:hb-ot-color
+ * @title: hb-ot-color
+ * @short_description: OpenType Color Fonts
+ * @include: hb-ot.h
+ *
+ * Functions for fetching color-font information from OpenType font faces.
+ **/
+
+
+/*
+ * CPAL
+ */
+
+
+/**
+ * hb_ot_color_has_palettes:
+ * @face: a font face.
+ *
+ * Returns: whether CPAL table is available.
+ *
+ * Since: 2.1.0
+ */
+hb_bool_t
+hb_ot_color_has_palettes (hb_face_t *face)
+{
+  return face->table.CPAL->has_data ();
+}
+
+/**
+ * hb_ot_color_palette_get_count:
+ * @face: a font face.
+ *
+ * Returns: the number of color palettes in @face, or zero if @face has
+ * no colors.
+ *
+ * Since: 2.1.0
+ */
+unsigned int
+hb_ot_color_palette_get_count (hb_face_t *face)
+{
+  return face->table.CPAL->get_palette_count ();
+}
+
+/**
+ * hb_ot_color_palette_get_name_id:
+ * @face:    a font face.
+ * @palette_index: the index of the color palette whose name is being requested.
+ *
+ * Retrieves the name id of a color palette. For example, a color font can
+ * have themed palettes like "Spring", "Summer", "Fall", and "Winter".
+ *
+ * Returns: an identifier within @face's `name` table.
+ * If the requested palette has no name the result is #HB_OT_NAME_ID_INVALID.
+ *
+ * Since: 2.1.0
+ */
+hb_ot_name_id_t
+hb_ot_color_palette_get_name_id (hb_face_t *face,
+                                 unsigned int palette_index)
+{
+  return face->table.CPAL->get_palette_name_id (palette_index);
+}
+
+/**
+ * hb_ot_color_palette_color_get_name_id:
+ * @face:        a font face.
+ * @color_index: palette entry index.
+ *
+ * Returns: Name ID associated with a palette entry, e.g. eye color
+ *
+ * Since: 2.1.0
+ */
+hb_ot_name_id_t
+hb_ot_color_palette_color_get_name_id (hb_face_t *face,
+                                       unsigned int color_index)
+{
+  return face->table.CPAL->get_color_name_id (color_index);
+}
+
+/**
+ * hb_ot_color_palette_get_flags:
+ * @face:          a font face
+ * @palette_index: the index of the color palette whose flags are being requested
+ *
+ * Returns: the flags for the requested color palette.
+ *
+ * Since: 2.1.0
+ */
+hb_ot_color_palette_flags_t
+hb_ot_color_palette_get_flags (hb_face_t *face,
+                               unsigned int palette_index)
+{
+  return face->table.CPAL->get_palette_flags (palette_index);
+}
+
+/**
+ * hb_ot_color_palette_get_colors:
+ * @face:         a font face.
+ * @palette_index:the index of the color palette whose colors
+ *                are being requested.
+ * @start_offset: the index of the first color being requested.
+ * @color_count:  (inout) (optional): on input, how many colors
+ *                can be maximally stored into the @colors array;
+ *                on output, how many colors were actually stored.
+ * @colors: (array length=color_count) (out) (optional):
+ *                an array of #hb_color_t records. After calling
+ *                this function, @colors will be filled with
+ *                the palette colors. If @colors is NULL, the function
+ *                will just return the number of total colors
+ *                without storing any actual colors; this can be used
+ *                for allocating a buffer of suitable size before calling
+ *                hb_ot_color_palette_get_colors() a second time.
+ *
+ * Retrieves the colors in a color palette.
+ *
+ * Returns: the total number of colors in the palette.
+ *
+ * Since: 2.1.0
+ */
+unsigned int
+hb_ot_color_palette_get_colors (hb_face_t     *face,
+                                unsigned int   palette_index,
+                                unsigned int   start_offset,
+                                unsigned int  *colors_count  /* IN/OUT.  May be NULL. */,
+                                hb_color_t    *colors        /* OUT.     May be NULL. */)
+{
+  return face->table.CPAL->get_palette_colors (palette_index, start_offset, colors_count, colors);
+}
+
+
+/*
+ * COLR
+ */
+
+/**
+ * hb_ot_color_has_layers:
+ * @face: a font face.
+ *
+ * Returns: whether COLR table is available.
+ *
+ * Since: 2.1.0
+ */
+hb_bool_t
+hb_ot_color_has_layers (hb_face_t *face)
+{
+  return face->table.COLR->has_data ();
+}
+
+/**
+ * hb_ot_color_glyph_get_layers:
+ * @face:         a font face.
+ * @glyph:        a layered color glyph id.
+ * @start_offset: starting offset of layers.
+ * @count:  (inout) (optional): gets number of layers available to be written on buffer
+ *                              and returns number of written layers.
+ * @layers: (array length=count) (out) (optional): layers buffer to buffer.
+ *
+ * Returns: Total number of layers a layered color glyph have.
+ *
+ * Since: 2.1.0
+ */
+unsigned int
+hb_ot_color_glyph_get_layers (hb_face_t           *face,
+                              hb_codepoint_t       glyph,
+                              unsigned int         start_offset,
+                              unsigned int        *count, /* IN/OUT.  May be NULL. */
+                              hb_ot_color_layer_t *layers /* OUT.     May be NULL. */)
+{
+  return face->table.COLR->get_glyph_layers (glyph, start_offset, count, layers);
+}
+
+
+/*
+ * SVG
+ */
+
+/**
+ * hb_ot_color_has_svg:
+ * @face: a font face.
+ *
+ * Check whether @face has SVG glyph images.
+ *
+ * Returns true if available, false otherwise.
+ *
+ * Since: 2.1.0
+ */
+hb_bool_t
+hb_ot_color_has_svg (hb_face_t *face)
+{
+  return face->table.SVG->has_data ();
+}
+
+/**
+ * hb_ot_color_glyph_reference_svg:
+ * @face:  a font face.
+ * @glyph: a svg glyph index.
+ *
+ * Get SVG document for a glyph. The blob may be either plain text or gzip-encoded.
+ *
+ * Returns: (transfer full): respective svg blob of the glyph, if available.
+ *
+ * Since: 2.1.0
+ */
+hb_blob_t *
+hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph)
+{
+  return face->table.SVG->reference_blob_for_glyph (glyph);
+}
+
+
+/*
+ * PNG: CBDT or sbix
+ */
+
+/**
+ * hb_ot_color_has_png:
+ * @face: a font face.
+ *
+ * Check whether @face has PNG glyph images (either CBDT or sbix tables).
+ *
+ * Returns true if available, false otherwise.
+ *
+ * Since: 2.1.0
+ */
+hb_bool_t
+hb_ot_color_has_png (hb_face_t *face)
+{
+  return face->table.CBDT->has_data () || face->table.sbix->has_data ();
+}
+
+/**
+ * hb_ot_color_glyph_reference_png:
+ * @font:  a font object, not face. upem should be set on
+ *         that font object if one wants to get optimal png blob, otherwise
+ *         return the biggest one
+ * @glyph: a glyph index.
+ *
+ * Get PNG image for a glyph.
+ *
+ * Returns: (transfer full): respective PNG blob of the glyph, if available.
+ *
+ * Since: 2.1.0
+ */
+hb_blob_t *
+hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t  glyph)
+{
+  hb_blob_t *blob = hb_blob_get_empty ();
+
+  if (font->face->table.sbix->has_data ())
+    blob = font->face->table.sbix->reference_png (font, glyph, nullptr, nullptr, nullptr);
+
+  if (!blob->length && font->face->table.CBDT->has_data ())
+    blob = font->face->table.CBDT->reference_png (font, glyph);
+
+  return blob;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color.h	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2016  Google, Inc.
+ * Copyright © 2018  Khaled Hosny
+ * 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): Sascha Brawer, Behdad Esfahbod
+ */
+
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
+#ifndef HB_OT_COLOR_H
+#define HB_OT_COLOR_H
+
+#include "hb.h"
+#include "hb-ot-name.h"
+
+HB_BEGIN_DECLS
+
+
+/*
+ * Color palettes.
+ */
+
+HB_EXTERN hb_bool_t
+hb_ot_color_has_palettes (hb_face_t *face);
+
+HB_EXTERN unsigned int
+hb_ot_color_palette_get_count (hb_face_t *face);
+
+HB_EXTERN hb_ot_name_id_t
+hb_ot_color_palette_get_name_id (hb_face_t *face,
+                                 unsigned int palette_index);
+
+HB_EXTERN hb_ot_name_id_t
+hb_ot_color_palette_color_get_name_id (hb_face_t *face,
+                                       unsigned int color_index);
+
+/**
+ * hb_ot_color_palette_flags_t:
+ * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special
+ *   to note about a color palette.
+ * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND: flag indicating that the color
+ *   palette is appropriate to use when displaying the font on a light background such as white.
+ * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: flag indicating that the color
+ *   palette is appropriate to use when displaying the font on a dark background such as black.
+ *
+ * Since: 2.1.0
+ */
+typedef enum { /*< flags >*/
+  HB_OT_COLOR_PALETTE_FLAG_DEFAULT                      = 0x00000000u,
+  HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND = 0x00000001u,
+  HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND  = 0x00000002u
+} hb_ot_color_palette_flags_t;
+
+HB_EXTERN hb_ot_color_palette_flags_t
+hb_ot_color_palette_get_flags (hb_face_t *face,
+                               unsigned int palette_index);
+
+HB_EXTERN unsigned int
+hb_ot_color_palette_get_colors (hb_face_t    *face,
+                                unsigned int  palette_index,
+                                unsigned int  start_offset,
+                                unsigned int *color_count,  /* IN/OUT.  May be NULL. */
+                                hb_color_t   *colors        /* OUT.     May be NULL. */);
+
+
+/*
+ * Color layers.
+ */
+
+HB_EXTERN hb_bool_t
+hb_ot_color_has_layers (hb_face_t *face);
+
+/**
+ * hb_ot_color_layer_t:
+ *
+ * Pairs of glyph and color index.
+ *
+ * Since: 2.1.0
+ **/
+typedef struct hb_ot_color_layer_t
+{
+  hb_codepoint_t glyph;
+  unsigned int   color_index;
+} hb_ot_color_layer_t;
+
+HB_EXTERN unsigned int
+hb_ot_color_glyph_get_layers (hb_face_t           *face,
+                              hb_codepoint_t       glyph,
+                              unsigned int         start_offset,
+                              unsigned int        *count, /* IN/OUT.  May be NULL. */
+                              hb_ot_color_layer_t *layers /* OUT.     May be NULL. */);
+
+/*
+ * SVG
+ */
+
+HB_EXTERN hb_bool_t
+hb_ot_color_has_svg (hb_face_t *face);
+
+HB_EXTERN hb_blob_t *
+hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph);
+
+/*
+ * PNG: CBDT or sbix
+ */
+
+HB_EXTERN hb_bool_t
+hb_ot_color_has_png (hb_face_t *face);
+
+HB_EXTERN hb_blob_t *
+hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t glyph);
+
+
+HB_END_DECLS
+
+#endif /* HB_OT_COLOR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-deprecated.h	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,107 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
+#ifndef HB_OT_DEPRECATED_H
+#define HB_OT_DEPRECATED_H
+
+#include "hb.h"
+#include "hb-ot-name.h"
+
+
+HB_BEGIN_DECLS
+
+#ifndef HB_DISABLE_DEPRECATED
+
+
+/* Like hb_ot_layout_table_find_script, but takes zero-terminated array of scripts to test */
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_table_select_script) hb_bool_t
+hb_ot_layout_table_choose_script (hb_face_t      *face,
+                                  hb_tag_t        table_tag,
+                                  const hb_tag_t *script_tags,
+                                  unsigned int   *script_index,
+                                  hb_tag_t       *chosen_script);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_script_select_language) hb_bool_t
+hb_ot_layout_script_find_language (hb_face_t    *face,
+                                   hb_tag_t      table_tag,
+                                   unsigned int  script_index,
+                                   hb_tag_t      language_tag,
+                                   unsigned int *language_index);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language) void
+hb_ot_tags_from_script (hb_script_t  script,
+                        hb_tag_t    *script_tag_1,
+                        hb_tag_t    *script_tag_2);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language) hb_tag_t
+hb_ot_tag_from_language (hb_language_t language);
+
+
+/**
+ * HB_OT_VAR_NO_AXIS_INDEX:
+ *
+ * Since: 1.4.2
+ * Deprecated: 2.2.0
+ */
+#define HB_OT_VAR_NO_AXIS_INDEX         0xFFFFFFFFu
+
+/**
+ * hb_ot_var_axis_t:
+ *
+ * Since: 1.4.2
+ * Deprecated: 2.2.0
+ */
+typedef struct hb_ot_var_axis_t
+{
+  hb_tag_t tag;
+  hb_ot_name_id_t name_id;
+  float min_value;
+  float default_value;
+  float max_value;
+} hb_ot_var_axis_t;
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_get_axis_infos) unsigned int
+hb_ot_var_get_axes (hb_face_t        *face,
+                    unsigned int      start_offset,
+                    unsigned int     *axes_count /* IN/OUT */,
+                    hb_ot_var_axis_t *axes_array /* OUT */);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_find_axis_info) hb_bool_t
+hb_ot_var_find_axis (hb_face_t        *face,
+                     hb_tag_t          axis_tag,
+                     unsigned int     *axis_index,
+                     hb_ot_var_axis_t *axis_info);
+
+
+#endif
+
+HB_END_DECLS
+
+#endif /* HB_OT_DEPRECATED_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-face.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,61 @@
+/*
+ * 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
+ */
+
+#include "hb-ot-face.hh"
+
+#include "hb-ot-cmap-table.hh"
+#include "hb-ot-glyf-table.hh"
+#include "hb-ot-cff1-table.hh"
+#include "hb-ot-cff2-table.hh"
+#include "hb-ot-hmtx-table.hh"
+#include "hb-ot-kern-table.hh"
+#include "hb-ot-name-table.hh"
+#include "hb-ot-post-table.hh"
+#include "hb-ot-color-cbdt-table.hh"
+#include "hb-ot-color-sbix-table.hh"
+#include "hb-ot-color-svg-table.hh"
+#include "hb-ot-layout-gdef-table.hh"
+#include "hb-ot-layout-gsub-table.hh"
+#include "hb-ot-layout-gpos-table.hh"
+
+
+void hb_ot_face_t::init0 (hb_face_t *face)
+{
+  this->face = face;
+#define HB_OT_TABLE(Namespace, Type) Type.init0 ();
+#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
+  HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+}
+void hb_ot_face_t::fini ()
+{
+#define HB_OT_TABLE(Namespace, Type) Type.fini ();
+#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
+  HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-face.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,120 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2012,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
+ */
+
+#ifndef HB_OT_FACE_HH
+#define HB_OT_FACE_HH
+
+#include "hb.hh"
+
+#include "hb-machinery.hh"
+
+
+/*
+ * hb_ot_face_t
+ */
+
+#define HB_OT_TABLES \
+    /* OpenType fundamentals. */ \
+    HB_OT_TABLE(OT, head) \
+    HB_OT_ACCELERATOR(OT, cmap) \
+    HB_OT_ACCELERATOR(OT, hmtx) \
+    HB_OT_ACCELERATOR(OT, vmtx) \
+    HB_OT_ACCELERATOR(OT, post) \
+    HB_OT_TABLE(OT, kern) \
+    HB_OT_ACCELERATOR(OT, glyf) \
+    HB_OT_ACCELERATOR(OT, cff1) \
+    HB_OT_ACCELERATOR(OT, cff2) \
+    HB_OT_TABLE(OT, VORG) \
+    HB_OT_ACCELERATOR(OT, name) \
+    HB_OT_TABLE(OT, OS2) \
+    HB_OT_TABLE(OT, STAT) \
+    /* OpenType shaping. */ \
+    HB_OT_ACCELERATOR(OT, GDEF) \
+    HB_OT_ACCELERATOR(OT, GSUB) \
+    HB_OT_ACCELERATOR(OT, GPOS) \
+    HB_OT_TABLE(OT, BASE) \
+    HB_OT_TABLE(OT, JSTF) \
+    /* AAT shaping. */ \
+    HB_OT_TABLE(AAT, mort) \
+    HB_OT_TABLE(AAT, morx) \
+    HB_OT_TABLE(AAT, kerx) \
+    HB_OT_TABLE(AAT, ankr) \
+    HB_OT_TABLE(AAT, trak) \
+    HB_OT_TABLE(AAT, lcar) \
+    HB_OT_TABLE(AAT, ltag) \
+    HB_OT_TABLE(AAT, feat) \
+    /* OpenType variations. */ \
+    HB_OT_TABLE(OT, fvar) \
+    HB_OT_TABLE(OT, avar) \
+    HB_OT_TABLE(OT, MVAR) \
+    /* OpenType math. */ \
+    HB_OT_TABLE(OT, MATH) \
+    /* OpenType color fonts. */ \
+    HB_OT_TABLE(OT, COLR) \
+    HB_OT_TABLE(OT, CPAL) \
+    HB_OT_ACCELERATOR(OT, CBDT) \
+    HB_OT_ACCELERATOR(OT, sbix) \
+    HB_OT_ACCELERATOR(OT, SVG) \
+    /* */
+
+/* Declare tables. */
+#define HB_OT_TABLE(Namespace, Type) namespace Namespace { struct Type; }
+#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type##_accelerator_t)
+HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+
+struct hb_ot_face_t
+{
+  HB_INTERNAL void init0 (hb_face_t *face);
+  HB_INTERNAL void fini ();
+
+#define HB_OT_TABLE_ORDER(Namespace, Type) \
+    HB_PASTE (ORDER_, HB_PASTE (Namespace, HB_PASTE (_, Type)))
+  enum order_t
+  {
+    ORDER_ZERO,
+#define HB_OT_TABLE(Namespace, Type) HB_OT_TABLE_ORDER (Namespace, Type),
+#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
+    HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+  };
+
+  hb_face_t *face; /* MUST be JUST before the lazy loaders. */
+#define HB_OT_TABLE(Namespace, Type) \
+  hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
+#define HB_OT_ACCELERATOR(Namespace, Type) \
+  hb_face_lazy_loader_t<Namespace::Type##_accelerator_t, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
+  HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+};
+
+
+#endif /* HB_OT_FACE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-font.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-font.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,67 +24,38 @@
  * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 #include "hb-ot.h"
 
-#include "hb-font-private.hh"
+#include "hb-font.hh"
+#include "hb-machinery.hh"
+#include "hb-ot-face.hh"
 
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-glyf-table.hh"
+#include "hb-ot-cff1-table.hh"
+#include "hb-ot-cff2-table.hh"
 #include "hb-ot-hmtx-table.hh"
 #include "hb-ot-kern-table.hh"
+#include "hb-ot-os2-table.hh"
 #include "hb-ot-post-table.hh"
-
+#include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-vorg-table.hh"
 #include "hb-ot-color-cbdt-table.hh"
-
-
-struct hb_ot_font_t
-{
-  OT::cmap::accelerator_t cmap;
-  OT::hmtx::accelerator_t h_metrics;
-  OT::vmtx::accelerator_t v_metrics;
-  OT::hb_lazy_loader_t<OT::glyf::accelerator_t> glyf;
-  OT::hb_lazy_loader_t<OT::CBDT::accelerator_t> cbdt;
-  OT::hb_lazy_loader_t<OT::post::accelerator_t> post;
-  OT::hb_lazy_loader_t<OT::kern::accelerator_t> kern;
-};
+#include "hb-ot-color-sbix-table.hh"
 
 
-static hb_ot_font_t *
-_hb_ot_font_create (hb_face_t *face)
-{
-  hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
-
-  if (unlikely (!ot_font))
-    return nullptr;
-
-  ot_font->cmap.init (face);
-  ot_font->h_metrics.init (face);
-  ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
-  ot_font->glyf.init (face);
-  ot_font->cbdt.init (face);
-  ot_font->post.init (face);
-  ot_font->kern.init (face);
-
-  return ot_font;
-}
-
-static void
-_hb_ot_font_destroy (void *data)
-{
-  hb_ot_font_t *ot_font = (hb_ot_font_t *) data;
-
-  ot_font->cmap.fini ();
-  ot_font->h_metrics.fini ();
-  ot_font->v_metrics.fini ();
-  ot_font->glyf.fini ();
-  ot_font->cbdt.fini ();
-  ot_font->post.fini ();
-  ot_font->kern.fini ();
-
-  free (ot_font);
-}
+/**
+ * SECTION:hb-ot-font
+ * @title: hb-ot-font
+ * @short_description: OpenType font implementation
+ * @include: hb-ot.h
+ *
+ * Functions for using OpenType fonts with hb_shape().  Not that fonts returned
+ * by hb_font_create() default to using these functions, so most clients would
+ * never need to call these functions directly.
+ **/
 
 
 static hb_bool_t
@@ -93,10 +64,25 @@
                          hb_codepoint_t unicode,
                          hb_codepoint_t *glyph,
                          void *user_data HB_UNUSED)
-
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->cmap.get_nominal_glyph (unicode, glyph);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->cmap->get_nominal_glyph (unicode, glyph);
+}
+
+static unsigned int
+hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
+                          void *font_data,
+                          unsigned int count,
+                          const hb_codepoint_t *first_unicode,
+                          unsigned int unicode_stride,
+                          hb_codepoint_t *first_glyph,
+                          unsigned int glyph_stride,
+                          void *user_data HB_UNUSED)
+{
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->cmap->get_nominal_glyphs (count,
+                                            first_unicode, unicode_stride,
+                                            first_glyph, glyph_stride);
 }
 
 static hb_bool_t
@@ -107,39 +93,83 @@
                            hb_codepoint_t *glyph,
                            void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->cmap.get_variation_glyph (unicode, variation_selector, glyph);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph);
 }
 
-static hb_position_t
-hb_ot_get_glyph_h_advance (hb_font_t *font,
-                           void *font_data,
-                           hb_codepoint_t glyph,
-                           void *user_data HB_UNUSED)
+static void
+hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
+                            unsigned count,
+                            const hb_codepoint_t *first_glyph,
+                            unsigned glyph_stride,
+                            hb_position_t *first_advance,
+                            unsigned advance_stride,
+                            void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return font->em_scale_x (ot_font->h_metrics.get_advance (glyph, font));
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
+
+  for (unsigned int i = 0; i < count; i++)
+  {
+    *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font));
+    first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
 }
 
-static hb_position_t
-hb_ot_get_glyph_v_advance (hb_font_t *font,
-                           void *font_data,
-                           hb_codepoint_t glyph,
-                           void *user_data HB_UNUSED)
+static void
+hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
+                            unsigned count,
+                            const hb_codepoint_t *first_glyph,
+                            unsigned glyph_stride,
+                            hb_position_t *first_advance,
+                            unsigned advance_stride,
+                            void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph, font));
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+
+  for (unsigned int i = 0; i < count; i++)
+  {
+    *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font));
+    first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
 }
 
-static hb_position_t
-hb_ot_get_glyph_h_kerning (hb_font_t *font,
-                           void *font_data,
-                           hb_codepoint_t left_glyph,
-                           hb_codepoint_t right_glyph,
-                           void *user_data HB_UNUSED)
+static hb_bool_t
+hb_ot_get_glyph_v_origin (hb_font_t *font,
+                          void *font_data,
+                          hb_codepoint_t glyph,
+                          hb_position_t *x,
+                          hb_position_t *y,
+                          void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return font->em_scale_x (ot_font->kern->get_h_kerning (left_glyph, right_glyph));
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+
+  *x = font->get_glyph_h_advance (glyph) / 2;
+
+  const OT::VORG &VORG = *ot_face->VORG;
+  if (VORG.has_data ())
+  {
+    *y = font->em_scale_y (VORG.get_y_origin (glyph));
+    return true;
+  }
+
+  hb_glyph_extents_t extents = {0};
+  if (ot_face->glyf->get_extents (glyph, &extents))
+  {
+    const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+    hb_position_t tsb = vmtx.get_side_bearing (glyph);
+    *y = font->em_scale_y (extents.y_bearing + tsb);
+    return true;
+  }
+
+  hb_font_extents_t font_extents;
+  font->get_h_extents_with_fallback (&font_extents);
+  *y = font_extents.ascender;
+
+  return true;
 }
 
 static hb_bool_t
@@ -149,10 +179,16 @@
                          hb_glyph_extents_t *extents,
                          void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  bool ret = ot_font->glyf->get_extents (glyph, extents);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  bool ret = ot_face->sbix->get_extents (font, glyph, extents);
+  if (!ret)
+    ret = ot_face->glyf->get_extents (glyph, extents);
   if (!ret)
-    ret = ot_font->cbdt->get_extents (glyph, extents);
+    ret = ot_face->cff1->get_extents (glyph, extents);
+  if (!ret)
+    ret = ot_face->cff2->get_extents (font, glyph, extents);
+  if (!ret)
+    ret = ot_face->CBDT->get_extents (font, glyph, extents);
   // TODO Hook up side-bearings variations.
   extents->x_bearing = font->em_scale_x (extents->x_bearing);
   extents->y_bearing = font->em_scale_y (extents->y_bearing);
@@ -168,8 +204,8 @@
                       char *name, unsigned int size,
                       void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->post->get_glyph_name (glyph, name, size);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->post->get_glyph_name (glyph, name, size);
 }
 
 static hb_bool_t
@@ -179,8 +215,8 @@
                            hb_codepoint_t *glyph,
                            void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->post->get_glyph_from_name (name, len, glyph);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->post->get_glyph_from_name (name, len, glyph);
 }
 
 static hb_bool_t
@@ -189,12 +225,13 @@
                           hb_font_extents_t *metrics,
                           void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender);
-  metrics->descender = font->em_scale_y (ot_font->h_metrics.descender);
-  metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
+  metrics->ascender = font->em_scale_y (hmtx.ascender);
+  metrics->descender = font->em_scale_y (hmtx.descender);
+  metrics->line_gap = font->em_scale_y (hmtx.line_gap);
   // TODO Hook up variations.
-  return ot_font->h_metrics.has_font_extents;
+  return hmtx.has_font_extents;
 }
 
 static hb_bool_t
@@ -203,49 +240,34 @@
                           hb_font_extents_t *metrics,
                           void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender);
-  metrics->descender = font->em_scale_x (ot_font->v_metrics.descender);
-  metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+  metrics->ascender = font->em_scale_x (vmtx.ascender);
+  metrics->descender = font->em_scale_x (vmtx.descender);
+  metrics->line_gap = font->em_scale_x (vmtx.line_gap);
   // TODO Hook up variations.
-  return ot_font->v_metrics.has_font_extents;
+  return vmtx.has_font_extents;
 }
 
-static hb_font_funcs_t *static_ot_funcs = nullptr;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_ot_funcs (void)
-{
-retry:
-  hb_font_funcs_t *ot_funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs);
-  if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, ot_funcs, nullptr))
-    goto retry;
-
-  hb_font_funcs_destroy (ot_funcs);
-}
+#if HB_USE_ATEXIT
+static void free_static_ot_funcs ();
 #endif
 
-static hb_font_funcs_t *
-_hb_ot_get_font_funcs (void)
+static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
 {
-retry:
-  hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs);
-
-  if (unlikely (!funcs))
+  static hb_font_funcs_t *create ()
   {
-    funcs = hb_font_funcs_create ();
+    hb_font_funcs_t *funcs = hb_font_funcs_create ();
 
     hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
     hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
+    hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr);
     hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, nullptr, nullptr);
-    hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, nullptr, nullptr);
+    hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
+    hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, nullptr, nullptr);
+    hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
     hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
     //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
     hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
@@ -253,17 +275,26 @@
 
     hb_font_funcs_make_immutable (funcs);
 
-    if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, nullptr, funcs)) {
-      hb_font_funcs_destroy (funcs);
-      goto retry;
-    }
+#if HB_USE_ATEXIT
+    atexit (free_static_ot_funcs);
+#endif
+
+    return funcs;
+  }
+} static_ot_funcs;
 
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_ot_funcs); /* First person registers atexit() callback. */
+#if HB_USE_ATEXIT
+static
+void free_static_ot_funcs ()
+{
+  static_ot_funcs.free_instance ();
+}
 #endif
-  };
 
-  return funcs;
+static hb_font_funcs_t *
+_hb_ot_get_font_funcs ()
+{
+  return static_ot_funcs.get_unconst ();
 }
 
 
@@ -275,12 +306,8 @@
 void
 hb_ot_font_set_funcs (hb_font_t *font)
 {
-  hb_ot_font_t *ot_font = _hb_ot_font_create (font->face);
-  if (unlikely (!ot_font))
-    return;
-
   hb_font_set_funcs (font,
                      _hb_ot_get_font_funcs (),
-                     ot_font,
-                     _hb_ot_font_destroy);
+                     &font->face->table,
+                     nullptr);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-gasp-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,84 @@
+/*
+ * 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_OT_GASP_TABLE_HH
+#define HB_OT_GASP_TABLE_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-hhea-table.hh"
+#include "hb-ot-os2-table.hh"
+#include "hb-ot-var-hvar-table.hh"
+
+/*
+ * gasp -- Grid-fitting and Scan-conversion Procedure
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/gasp
+ */
+#define HB_OT_TAG_gasp HB_TAG('g','a','s','p')
+
+
+namespace OT {
+
+struct GaspRange
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT16      rangeMaxPPEM;   /* Upper limit of range, in PPEM */
+  HBUINT16      rangeGaspBehavior;
+                                /* Flags describing desired rasterizer behavior. */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct gasp
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_gasp;
+
+  const GaspRange &get_gasp_range (unsigned int i) const
+  { return gaspRanges[i]; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  gaspRanges.sanitize (c));
+  }
+
+  protected:
+  HBUINT16      version;        /* Version number (set to 1) */
+  ArrayOf<GaspRange>
+                gaspRanges;     /* Number of records to follow
+                                 * Sorted by ppem */
+  public:
+  DEFINE_SIZE_ARRAY (4, gaspRanges);
+};
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_GASP_TABLE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-glyf-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-glyf-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,11 +27,9 @@
 #ifndef HB_OT_GLYF_TABLE_HH
 #define HB_OT_GLYF_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 #include "hb-ot-head-table.hh"
 #include "hb-subset-glyf.hh"
-#include "hb-subset-plan.hh"
-#include "hb-subset-private.hh"
 
 namespace OT {
 
@@ -47,17 +45,20 @@
 {
   friend struct glyf;
 
-  static const hb_tag_t tableTag = HB_OT_TAG_loca;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_loca;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
   {
     TRACE_SANITIZE (this);
     return_trace (true);
   }
 
   protected:
-  HBUINT8               dataZ[VAR];             /* Location data. */
-  DEFINE_SIZE_ARRAY (0, dataZ);
+  UnsizedArrayOf<HBUINT8>       dataZ;          /* Location data. */
+  public:
+  DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
+                        * check the size externally, allow Null() object of it by
+                        * defining it MIN() instead. */
 };
 
 
@@ -70,9 +71,9 @@
 
 struct glyf
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_glyf;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
   {
     TRACE_SANITIZE (this);
     /* We don't check for anything specific here.  The users of the
@@ -80,7 +81,7 @@
     return_trace (true);
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
     hb_blob_t *glyf_prime = nullptr;
     hb_blob_t *loca_prime = nullptr;
@@ -103,14 +104,14 @@
   static bool
   _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
   {
-    hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_head));
+    hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<head> (plan->source);
     hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
     hb_blob_destroy (head_blob);
 
     if (unlikely (!head_prime_blob))
       return false;
 
-    OT::head *head_prime = (OT::head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
+    head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
     head_prime->indexToLocFormat.set (use_short_loca ? 0 : 1);
     bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
 
@@ -150,28 +151,23 @@
     };
 
     HBUINT16 flags;
-    HBUINT16 glyphIndex;
+    GlyphID  glyphIndex;
 
-    inline unsigned int get_size (void) const
+    unsigned int get_size () const
     {
       unsigned int size = min_size;
-      if (flags & ARG_1_AND_2_ARE_WORDS) {
-        // arg1 and 2 are int16
-        size += 4;
-      } else {
-        // arg1 and 2 are int8
-        size += 2;
-      }
-      if (flags & WE_HAVE_A_SCALE) {
-        // One x 16 bit (scale)
-        size += 2;
-      } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
-        // Two x 16 bit (xscale, yscale)
-        size += 4;
-      } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
-        // Four x 16 bit (xscale, scale01, scale10, yscale)
-        size += 8;
-      }
+      // arg1 and 2 are int16
+      if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
+      // arg1 and 2 are int8
+      else size += 2;
+
+      // One x 16 bit (scale)
+      if (flags & WE_HAVE_A_SCALE) size += 2;
+      // Two x 16 bit (xscale, yscale)
+      else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4;
+      // Four x 16 bit (xscale, scale01, scale10, yscale)
+      else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8;
+
       return size;
     }
 
@@ -181,7 +177,7 @@
       const char *glyph_end;
       const CompositeGlyphHeader *current;
 
-      inline bool move_to_next ()
+      bool move_to_next ()
       {
         if (current->flags & CompositeGlyphHeader::MORE_COMPONENTS)
         {
@@ -195,17 +191,17 @@
         return false;
       }
 
-      inline bool in_range (const CompositeGlyphHeader *composite) const
+      bool in_range (const CompositeGlyphHeader *composite) const
       {
         return (const char *) composite >= glyph_start
           && ((const char *) composite + CompositeGlyphHeader::min_size) <= glyph_end
-          && ((const char *) composite + composite->get_size()) <= glyph_end;
+          && ((const char *) composite + composite->get_size ()) <= glyph_end;
       }
     };
 
-    static inline bool get_iterator (const char * glyph_data,
-                                     unsigned int length,
-                                     CompositeGlyphHeader::Iterator *iterator /* OUT */)
+    static bool get_iterator (const char * glyph_data,
+                              unsigned int length,
+                              CompositeGlyphHeader::Iterator *iterator /* OUT */)
     {
       if (length < GlyphHeader::static_size)
         return false; /* Empty glyph; zero extents. */
@@ -232,34 +228,26 @@
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
     {
       memset (this, 0, sizeof (accelerator_t));
 
-      hb_blob_t *head_blob = Sanitizer<head>().sanitize (face->reference_table (HB_OT_TAG_head));
-      const head *head_table = head_blob->as<head> ();
-      if (head_table == &Null(head) || (unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
-      {
-        /* head table is not present, or in an unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
-        hb_blob_destroy (head_blob);
+      const OT::head &head = *face->table.head;
+      if (head.indexToLocFormat > 1 || head.glyphDataFormat != 0)
+        /* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
         return;
-      }
-      short_offset = 0 == head_table->indexToLocFormat;
-      hb_blob_destroy (head_blob);
+      short_offset = 0 == head.indexToLocFormat;
 
-      loca_blob = Sanitizer<loca>().sanitize (face->reference_table (HB_OT_TAG_loca));
-      loca_table = loca_blob->as<loca> ();
-      glyf_blob = Sanitizer<glyf>().sanitize (face->reference_table (HB_OT_TAG_glyf));
-      glyf_table = glyf_blob->as<glyf> ();
+      loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
+      glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
 
-      num_glyphs = MAX (1u, hb_blob_get_length (loca_blob) / (short_offset ? 2 : 4)) - 1;
-      glyf_len = hb_blob_get_length (glyf_blob);
+      num_glyphs = MAX (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
     }
 
-    inline void fini (void)
+    void fini ()
     {
-      hb_blob_destroy (loca_blob);
-      hb_blob_destroy (glyf_blob);
+      loca_table.destroy ();
+      glyf_table.destroy ();
     }
 
     /*
@@ -267,35 +255,37 @@
      * If true is returned a pointer to the composite glyph will be written into
      * composite.
      */
-    inline bool get_composite (hb_codepoint_t glyph,
-                               CompositeGlyphHeader::Iterator *composite /* OUT */) const
+    bool get_composite (hb_codepoint_t glyph,
+                        CompositeGlyphHeader::Iterator *composite /* OUT */) const
     {
-      if (this->glyf_table == &Null(glyf) || !num_glyphs)
+      if (unlikely (!num_glyphs))
         return false;
 
       unsigned int start_offset, end_offset;
       if (!get_offsets (glyph, &start_offset, &end_offset))
         return false; /* glyph not found */
 
-      return CompositeGlyphHeader::get_iterator ((const char*) this->glyf_table + start_offset,
+      return CompositeGlyphHeader::get_iterator ((const char *) this->glyf_table + start_offset,
                                                  end_offset - start_offset,
                                                  composite);
     }
 
     enum simple_glyph_flag_t {
+      FLAG_ON_CURVE = 0x01,
       FLAG_X_SHORT = 0x02,
       FLAG_Y_SHORT = 0x04,
       FLAG_REPEAT = 0x08,
       FLAG_X_SAME = 0x10,
-      FLAG_Y_SAME = 0x20
+      FLAG_Y_SAME = 0x20,
+      FLAG_RESERVED1 = 0x40,
+      FLAG_RESERVED2 = 0x80
     };
 
     /* based on FontTools _g_l_y_f.py::trim */
-    inline bool remove_padding(unsigned int start_offset,
-                               unsigned int *end_offset) const
+    bool remove_padding (unsigned int start_offset,
+                                unsigned int *end_offset) const
     {
-      if (*end_offset - start_offset < GlyphHeader::static_size)
-        return true;
+      if (*end_offset - start_offset < GlyphHeader::static_size) return true;
 
       const char *glyph = ((const char *) glyf_table) + start_offset;
       const char * const glyph_end = glyph + (*end_offset - start_offset);
@@ -312,8 +302,8 @@
         glyph += GlyphHeader::static_size + 2 * num_contours;
 
         if (unlikely (glyph + 2 >= glyph_end)) return false;
-        uint16_t nCoordinates = (uint16_t) StructAtOffset<HBUINT16>(glyph - 2, 0) + 1;
-        uint16_t nInstructions = (uint16_t) StructAtOffset<HBUINT16>(glyph, 0);
+        uint16_t nCoordinates = (uint16_t) StructAtOffset<HBUINT16> (glyph - 2, 0) + 1;
+        uint16_t nInstructions = (uint16_t) StructAtOffset<HBUINT16> (glyph, 0);
 
         glyph += 2 + nInstructions;
         if (unlikely (glyph + 2 >= glyph_end)) return false;
@@ -339,15 +329,11 @@
 
           unsigned int xBytes, yBytes;
           xBytes = yBytes = 0;
-          if (flag & FLAG_X_SHORT)
-            xBytes = 1;
-          else if ((flag & FLAG_X_SAME) == 0)
-            xBytes = 2;
+          if (flag & FLAG_X_SHORT) xBytes = 1;
+          else if ((flag & FLAG_X_SAME) == 0) xBytes = 2;
 
-          if (flag & FLAG_Y_SHORT)
-            yBytes = 1;
-          else if ((flag & FLAG_Y_SAME) == 0)
-            yBytes = 2;
+          if (flag & FLAG_Y_SHORT) yBytes = 1;
+          else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2;
 
           coordBytes += (xBytes + yBytes) * repeat;
           coordsWithFlags += repeat;
@@ -368,37 +354,37 @@
       return true;
     }
 
-    inline bool get_offsets (hb_codepoint_t  glyph,
-                             unsigned int   *start_offset /* OUT */,
-                             unsigned int   *end_offset   /* OUT */) const
+    bool get_offsets (hb_codepoint_t  glyph,
+                      unsigned int   *start_offset /* OUT */,
+                      unsigned int   *end_offset   /* OUT */) const
     {
       if (unlikely (glyph >= num_glyphs))
         return false;
 
       if (short_offset)
       {
-        const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ;
+        const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
         *start_offset = 2 * offsets[glyph];
         *end_offset   = 2 * offsets[glyph + 1];
       }
       else
       {
-        const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ;
+        const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
 
         *start_offset = offsets[glyph];
         *end_offset   = offsets[glyph + 1];
       }
 
-      if (*start_offset > *end_offset || *end_offset > glyf_len)
+      if (*start_offset > *end_offset || *end_offset > glyf_table.get_length ())
         return false;
 
       return true;
     }
 
-    inline bool get_instruction_offsets(unsigned int start_offset,
-                                        unsigned int end_offset,
-                                        unsigned int *instruction_start /* OUT */,
-                                        unsigned int *instruction_end /* OUT */) const
+    bool get_instruction_offsets (unsigned int start_offset,
+                                  unsigned int end_offset,
+                                  unsigned int *instruction_start /* OUT */,
+                                  unsigned int *instruction_end /* OUT */) const
     {
       if (end_offset - start_offset < GlyphHeader::static_size)
       {
@@ -417,10 +403,10 @@
         const CompositeGlyphHeader *last;
         do {
           last = composite_it.current;
-        } while (composite_it.move_to_next());
+        } while (composite_it.move_to_next ());
 
-        if ( (uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
-          *instruction_start = ((char *) last - (char *) glyf_table->dataZ) + last->get_size();
+        if ((uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
+          *instruction_start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) + last->get_size ();
         else
           *instruction_start = end_offset;
         *instruction_end = end_offset;
@@ -454,8 +440,7 @@
       return true;
     }
 
-    inline bool get_extents (hb_codepoint_t glyph,
-                             hb_glyph_extents_t *extents) const
+    bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
     {
       unsigned int start_offset, end_offset;
       if (!get_offsets (glyph, &start_offset, &end_offset))
@@ -477,18 +462,19 @@
     private:
     bool short_offset;
     unsigned int num_glyphs;
-    const loca *loca_table;
-    const glyf *glyf_table;
-    hb_blob_t *loca_blob;
-    hb_blob_t *glyf_blob;
-    unsigned int glyf_len;
+    hb_blob_ptr_t<loca> loca_table;
+    hb_blob_ptr_t<glyf> glyf_table;
   };
 
   protected:
-  HBUINT8               dataZ[VAR];             /* Glyphs data. */
+  UnsizedArrayOf<HBUINT8>       dataZ;          /* Glyphs data. */
+  public:
+  DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
+                        * check the size externally, allow Null() object of it by
+                        * defining it MIN() instead. */
+};
 
-  DEFINE_SIZE_ARRAY (0, dataZ);
-};
+struct glyf_accelerator_t : glyf::accelerator_t {};
 
 } /* namespace OT */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hdmx-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,214 @@
+/*
+ * 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): Garret Rieger
+ */
+
+#ifndef HB_OT_HDMX_TABLE_HH
+#define HB_OT_HDMX_TABLE_HH
+
+#include "hb-open-type.hh"
+
+/*
+ * hdmx -- Horizontal Device Metrics
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/hdmx
+ */
+#define HB_OT_TAG_hdmx HB_TAG('h','d','m','x')
+
+
+namespace OT {
+
+
+struct DeviceRecord
+{
+  struct SubsetView
+  {
+    const DeviceRecord *source_device_record;
+    unsigned int sizeDeviceRecord;
+    hb_subset_plan_t *subset_plan;
+
+    void init (const DeviceRecord *source_device_record,
+               unsigned int sizeDeviceRecord,
+               hb_subset_plan_t   *subset_plan)
+    {
+      this->source_device_record = source_device_record;
+      this->sizeDeviceRecord = sizeDeviceRecord;
+      this->subset_plan = subset_plan;
+    }
+
+    unsigned int len () const
+    { return this->subset_plan->glyphs.length; }
+
+    const HBUINT8* operator [] (unsigned int i) const
+    {
+      if (unlikely (i >= len ())) return nullptr;
+      hb_codepoint_t gid = this->subset_plan->glyphs [i];
+
+      if (gid >= sizeDeviceRecord - DeviceRecord::min_size)
+        return nullptr;
+      return &(this->source_device_record->widthsZ[gid]);
+    }
+  };
+
+  static unsigned int get_size (unsigned int count)
+  { return hb_ceil_to_4 (min_size + count * HBUINT8::static_size); }
+
+  bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view)
+  {
+    TRACE_SERIALIZE (this);
+
+    unsigned int size = get_size (subset_view.len ());
+    if (unlikely (!c->allocate_size<DeviceRecord> (size)))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Couldn't allocate enough space for DeviceRecord: %d.",
+                 size);
+      return_trace (false);
+    }
+
+    this->pixelSize.set (subset_view.source_device_record->pixelSize);
+    this->maxWidth.set (subset_view.source_device_record->maxWidth);
+
+    for (unsigned int i = 0; i < subset_view.len (); i++)
+    {
+      const HBUINT8 *width = subset_view[i];
+      if (!width)
+      {
+        DEBUG_MSG(SUBSET, nullptr, "HDMX width for new gid %d is missing.", i);
+        return_trace (false);
+      }
+      widthsZ[i].set (*width);
+    }
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int sizeDeviceRecord) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          c->check_range (this, sizeDeviceRecord)));
+  }
+
+  HBUINT8                       pixelSize;      /* Pixel size for following widths (as ppem). */
+  HBUINT8                       maxWidth;       /* Maximum width. */
+  UnsizedArrayOf<HBUINT8>       widthsZ;        /* Array of widths (numGlyphs is from the 'maxp' table). */
+  public:
+  DEFINE_SIZE_ARRAY (2, widthsZ);
+};
+
+
+struct hdmx
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_hdmx;
+
+  unsigned int get_size () const
+  { return min_size + numRecords * sizeDeviceRecord; }
+
+  const DeviceRecord& operator [] (unsigned int i) const
+  {
+    /* XXX Null(DeviceRecord) is NOT safe as it's num-glyphs lengthed.
+     * https://github.com/harfbuzz/harfbuzz/issues/1300 */
+    if (unlikely (i >= numRecords)) return Null (DeviceRecord);
+    return StructAtOffset<DeviceRecord> (&this->firstDeviceRecord, i * sizeDeviceRecord);
+  }
+
+  bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan)
+  {
+    TRACE_SERIALIZE (this);
+
+    if (unlikely (!c->extend_min ((*this))))  return_trace (false);
+
+    this->version.set (source_hdmx->version);
+    this->numRecords.set (source_hdmx->numRecords);
+    this->sizeDeviceRecord.set (DeviceRecord::get_size (plan->glyphs.length));
+
+    for (unsigned int i = 0; i < source_hdmx->numRecords; i++)
+    {
+      DeviceRecord::SubsetView subset_view;
+      subset_view.init (&(*source_hdmx)[i], source_hdmx->sizeDeviceRecord, plan);
+
+      if (!c->start_embed<DeviceRecord> ()->serialize (c, subset_view))
+        return_trace (false);
+    }
+
+    return_trace (true);
+  }
+
+  static size_t get_subsetted_size (const hdmx *source_hdmx, hb_subset_plan_t *plan)
+  {
+    return min_size + source_hdmx->numRecords * DeviceRecord::get_size (plan->glyphs.length);
+  }
+
+  bool subset (hb_subset_plan_t *plan) const
+  {
+    size_t dest_size = get_subsetted_size (this, plan);
+    hdmx *dest = (hdmx *) malloc (dest_size);
+    if (unlikely (!dest))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for hdmx subset output.", (unsigned long) dest_size);
+      return false;
+    }
+
+    hb_serialize_context_t c (dest, dest_size);
+    hdmx *hdmx_prime = c.start_serialize<hdmx> ();
+    if (!hdmx_prime || !hdmx_prime->serialize (&c, this, plan))
+    {
+      free (dest);
+      DEBUG_MSG(SUBSET, nullptr, "Failed to serialize write new hdmx.");
+      return false;
+    }
+    c.end_serialize ();
+
+    hb_blob_t *hdmx_prime_blob = hb_blob_create ((const char *) dest,
+                                                 dest_size,
+                                                 HB_MEMORY_MODE_READONLY,
+                                                 dest,
+                                                 free);
+    bool result = plan->add_table (HB_OT_TAG_hdmx, hdmx_prime_blob);
+    hb_blob_destroy (hdmx_prime_blob);
+
+    return result;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  !hb_unsigned_mul_overflows (numRecords, sizeDeviceRecord) &&
+                  sizeDeviceRecord >= DeviceRecord::min_size &&
+                  c->check_range (this, get_size ()));
+  }
+
+  protected:
+  HBUINT16              version;                /* Table version number (0) */
+  HBUINT16              numRecords;             /* Number of device records. */
+  HBUINT32              sizeDeviceRecord;       /* Size of a device record, 32-bit aligned. */
+  DeviceRecord          firstDeviceRecord;      /* Array of device records. */
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_HDMX_TABLE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-head-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-head-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -29,7 +29,7 @@
 #ifndef HB_OT_HEAD_TABLE_HH
 #define HB_OT_HEAD_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * head -- Font Header
@@ -45,16 +45,29 @@
 {
   friend struct OffsetTable;
 
-  static const hb_tag_t tableTag        = HB_OT_TAG_head;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_head;
 
-  inline unsigned int get_upem (void) const
+  unsigned int get_upem () const
   {
     unsigned int upem = unitsPerEm;
     /* If no valid head table found, assume 1000, which matches typical Type1 usage. */
     return 16 <= upem && upem <= 16384 ? upem : 1000;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  enum mac_style_flag_t {
+    BOLD        = 1u<<0,
+    ITALIC      = 1u<<1,
+    UNDERLINE   = 1u<<2,
+    OUTLINE     = 1u<<3,
+    SHADOW      = 1u<<4,
+    CONDENSED   = 1u<<5
+  };
+
+  bool is_bold () const      { return macStyle & BOLD; }
+  bool is_italic () const    { return macStyle & ITALIC; }
+  bool is_condensed () const { return macStyle & CONDENSED; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -141,8 +154,8 @@
                                          * -1: Only strongly right to left;
                                          * -2: Like -1 but also contains neutrals. */
   public:
-  HBINT16       indexToLocFormat;       /* 0 for short offsets, 1 for long. */
-  HBINT16       glyphDataFormat;        /* 0 for current format. */
+  HBUINT16      indexToLocFormat;       /* 0 for short offsets, 1 for long. */
+  HBUINT16      glyphDataFormat;        /* 0 for current format. */
 
   DEFINE_SIZE_STATIC (54);
 };
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hhea-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hhea-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,7 +27,7 @@
 #ifndef HB_OT_HHEA_TABLE_HH
 #define HB_OT_HHEA_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * hhea -- Horizontal Header
@@ -45,7 +45,7 @@
 template <typename T>
 struct _hea
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && likely (version.major == 1));
@@ -86,10 +86,10 @@
 };
 
 struct hhea : _hea<hhea> {
-  static const hb_tag_t tableTag        = HB_OT_TAG_hhea;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_hhea;
 };
 struct vhea : _hea<vhea> {
-  static const hb_tag_t tableTag        = HB_OT_TAG_vhea;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_vhea;
 };
 
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hmtx-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hmtx-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,11 +27,10 @@
 #ifndef HB_OT_HMTX_TABLE_HH
 #define HB_OT_HMTX_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 #include "hb-ot-hhea-table.hh"
 #include "hb-ot-os2-table.hh"
 #include "hb-ot-var-hvar-table.hh"
-#include "hb-subset-plan.hh"
 
 /*
  * hmtx -- Horizontal Metrics
@@ -49,7 +48,7 @@
 struct LongMetric
 {
   UFWORD        advance; /* Advance width/height. */
-  FWORD         lsb; /* Leading (left/top) side bearing. */
+  FWORD         sb; /* Leading (left/top) side bearing. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
@@ -57,7 +56,7 @@
 template <typename T, typename H>
 struct hmtxvmtx
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
   {
     TRACE_SANITIZE (this);
     /* We don't check for anything specific here.  The users of the
@@ -66,11 +65,11 @@
   }
 
 
-  inline bool subset_update_header (hb_subset_plan_t *plan,
+  bool subset_update_header (hb_subset_plan_t *plan,
                                     unsigned int num_hmetrics) const
   {
-    hb_blob_t *src_blob = OT::Sanitizer<H> ().sanitize (plan->source->reference_table (H::tableTag));
-    hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail(src_blob);
+    hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (plan->source, H::tableTag);
+    hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob);
     hb_blob_destroy (src_blob);
 
     if (unlikely (!dest_blob)) {
@@ -87,7 +86,7 @@
     return result;
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
     typename T::accelerator_t _mtx;
     _mtx.init (plan->source);
@@ -95,33 +94,33 @@
     /* All the trailing glyphs with the same advance can use one LongMetric
      * and just keep LSB */
     hb_vector_t<hb_codepoint_t> &gids = plan->glyphs;
-    unsigned int num_advances = gids.len;
+    unsigned int num_advances = gids.length;
     unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]);
-    while (num_advances > 1
-        && last_advance == _mtx.get_advance (gids[num_advances - 2]))
+    while (num_advances > 1 &&
+           last_advance == _mtx.get_advance (gids[num_advances - 2]))
     {
       num_advances--;
     }
 
     /* alloc the new table */
     size_t dest_sz = num_advances * 4
-                  + (gids.len - num_advances) * 2;
+                  + (gids.length - num_advances) * 2;
     void *dest = (void *) malloc (dest_sz);
     if (unlikely (!dest))
     {
       return false;
     }
     DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in src has %d advances, %d lsbs", HB_UNTAG(T::tableTag), _mtx.num_advances, _mtx.num_metrics - _mtx.num_advances);
-    DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes", HB_UNTAG(T::tableTag), num_advances, gids.len - num_advances, (unsigned int) dest_sz);
+    DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes", HB_UNTAG(T::tableTag), num_advances, gids.length - num_advances, (unsigned int) dest_sz);
 
-    const char *source_table = hb_blob_get_data (_mtx.blob, nullptr);
+    const char *source_table = hb_blob_get_data (_mtx.table.get_blob (), nullptr);
     // Copy everything over
     LongMetric * old_metrics = (LongMetric *) source_table;
     FWORD *lsbs = (FWORD *) (old_metrics + _mtx.num_advances);
     char * dest_pos = (char *) dest;
 
     bool failed = false;
-    for (unsigned int i = 0; i < gids.len; i++)
+    for (unsigned int i = 0; i < gids.length; i++)
     {
       /* the last metric or the one for gids[i] */
       LongMetric *src_metric = old_metrics + MIN ((hb_codepoint_t) _mtx.num_advances - 1, gids[i]);
@@ -135,8 +134,8 @@
         }
         else
         {
-          /* dest just lsb */
-          *((FWORD *) dest_pos) = src_metric->lsb;
+          /* dest just sb */
+          *((FWORD *) dest_pos) = src_metric->sb;
         }
       }
       else
@@ -148,18 +147,18 @@
           failed = true;
           break;
         }
-        FWORD src_lsb = *(lsbs + gids[i] - _mtx.num_advances);
+        FWORD src_sb = *(lsbs + gids[i] - _mtx.num_advances);
         if (i < num_advances)
         {
           /* dest needs a full LongMetric */
           LongMetric *metric = (LongMetric *)dest_pos;
           metric->advance = src_metric->advance;
-          metric->lsb = src_lsb;
+          metric->sb = src_sb;
         }
         else
         {
-          /* dest just needs an lsb */
-          *((FWORD *) dest_pos) = src_lsb;
+          /* dest just needs an sb */
+          *((FWORD *) dest_pos) = src_sb;
         }
       }
       dest_pos += (i < num_advances ? 4 : 2);
@@ -187,34 +186,27 @@
   {
     friend struct hmtxvmtx;
 
-    inline void init (hb_face_t *face,
+    void init (hb_face_t *face,
                       unsigned int default_advance_ = 0)
     {
       default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
 
       bool got_font_extents = false;
-      if (T::os2Tag)
+      if (T::os2Tag != HB_TAG_NONE && face->table.OS2->is_typo_metrics ())
       {
-        hb_blob_t *os2_blob = Sanitizer<os2> ().sanitize (face->reference_table (T::os2Tag));
-        const os2 *os2_table = os2_blob->as<os2> ();
-#define USE_TYPO_METRICS (1u<<7)
-        if (0 != (os2_table->fsSelection & USE_TYPO_METRICS))
-        {
-          ascender = os2_table->sTypoAscender;
-          descender = os2_table->sTypoDescender;
-          line_gap = os2_table->sTypoLineGap;
-          got_font_extents = (ascender | descender) != 0;
-        }
-        hb_blob_destroy (os2_blob);
+        ascender = abs (face->table.OS2->sTypoAscender);
+        descender = -abs (face->table.OS2->sTypoDescender);
+        line_gap = face->table.OS2->sTypoLineGap;
+        got_font_extents = (ascender | descender) != 0;
       }
 
-      hb_blob_t *_hea_blob = Sanitizer<H> ().sanitize (face->reference_table (H::tableTag));
+      hb_blob_t *_hea_blob = hb_sanitize_context_t().reference_table<H> (face);
       const H *_hea_table = _hea_blob->as<H> ();
       num_advances = _hea_table->numberOfLongMetrics;
       if (!got_font_extents)
       {
-        ascender = _hea_table->ascender;
-        descender = _hea_table->descender;
+        ascender = abs (_hea_table->ascender);
+        descender = -abs (_hea_table->descender);
         line_gap = _hea_table->lineGap;
         got_font_extents = (ascender | descender) != 0;
       }
@@ -222,10 +214,10 @@
 
       has_font_extents = got_font_extents;
 
-      blob = Sanitizer<hmtxvmtx> ().sanitize (face->reference_table (T::tableTag));
+      table = hb_sanitize_context_t().reference_table<hmtxvmtx> (face, T::tableTag);
 
       /* Cap num_metrics() and num_advances() based on table length. */
-      unsigned int len = hb_blob_get_length (blob);
+      unsigned int len = table.get_length ();
       if (unlikely (num_advances * 4 > len))
         num_advances = len / 4;
       num_metrics = num_advances + (len - 4 * num_advances) / 2;
@@ -235,22 +227,33 @@
       if (unlikely (!num_advances))
       {
         num_metrics = num_advances = 0;
-        hb_blob_destroy (blob);
-        blob = hb_blob_get_empty ();
+        table.destroy ();
+        table = hb_blob_get_empty ();
       }
-      table = blob->as<hmtxvmtx> ();
+
+      var_table = hb_sanitize_context_t().reference_table<HVARVVAR> (face, T::variationsTag);
+    }
 
-      var_blob = Sanitizer<HVARVVAR> ().sanitize (face->reference_table (T::variationsTag));
-      var_table = var_blob->as<HVARVVAR> ();
+    void fini ()
+    {
+      table.destroy ();
+      var_table.destroy ();
     }
 
-    inline void fini (void)
+    /* TODO Add variations version. */
+    unsigned int get_side_bearing (hb_codepoint_t glyph) const
     {
-      hb_blob_destroy (blob);
-      hb_blob_destroy (var_blob);
+      if (glyph < num_advances)
+        return table->longMetricZ[glyph].sb;
+
+      if (unlikely (glyph >= num_metrics))
+        return 0;
+
+      const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances];
+      return bearings[glyph - num_advances];
     }
 
-    inline unsigned int get_advance (hb_codepoint_t  glyph) const
+    unsigned int get_advance (hb_codepoint_t glyph) const
     {
       if (unlikely (glyph >= num_metrics))
       {
@@ -263,14 +266,14 @@
           return default_advance;
       }
 
-      return table->longMetric[MIN (glyph, (uint32_t) num_advances - 1)].advance;
+      return table->longMetricZ[MIN (glyph, (uint32_t) num_advances - 1)].advance;
     }
 
-    inline unsigned int get_advance (hb_codepoint_t  glyph,
-                                     hb_font_t      *font) const
+    unsigned int get_advance (hb_codepoint_t  glyph,
+                              hb_font_t      *font) const
     {
       unsigned int advance = get_advance (glyph);
-      if (likely(glyph < num_metrics))
+      if (likely (glyph < num_metrics))
       {
         advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?!
       }
@@ -279,9 +282,9 @@
 
     public:
     bool has_font_extents;
-    unsigned short ascender;
-    unsigned short descender;
-    unsigned short line_gap;
+    int ascender;
+    int descender;
+    int line_gap;
 
     protected:
     unsigned int num_metrics;
@@ -289,14 +292,12 @@
     unsigned int default_advance;
 
     private:
-    const hmtxvmtx *table;
-    hb_blob_t *blob;
-    const HVARVVAR *var_table;
-    hb_blob_t *var_blob;
+    hb_blob_ptr_t<hmtxvmtx> table;
+    hb_blob_ptr_t<HVARVVAR> var_table;
   };
 
   protected:
-  LongMetric    longMetric[VAR];        /* Paired advance width and leading
+  UnsizedArrayOf<LongMetric>longMetricZ;/* Paired advance width and leading
                                          * bearing values for each glyph. The
                                          * value numOfHMetrics comes from
                                          * the 'hhea' table. If the font is
@@ -304,7 +305,7 @@
                                          * be in the array, but that entry is
                                          * required. The last entry applies to
                                          * all subsequent glyphs. */
-/*FWORD         leadingBearingX[VAR];*/ /* Here the advance is assumed
+/*UnsizedArrayOf<FWORD> leadingBearingX;*//* Here the advance is assumed
                                          * to be the same as the advance
                                          * for the last entry above. The
                                          * number of entries in this array is
@@ -318,20 +319,23 @@
                                          * font to vary the side bearing
                                          * values for each glyph. */
   public:
-  DEFINE_SIZE_ARRAY (0, longMetric);
+  DEFINE_SIZE_ARRAY (0, longMetricZ);
 };
 
 struct hmtx : hmtxvmtx<hmtx, hhea> {
-  static const hb_tag_t tableTag        = HB_OT_TAG_hmtx;
-  static const hb_tag_t variationsTag   = HB_OT_TAG_HVAR;
-  static const hb_tag_t os2Tag          = HB_OT_TAG_os2;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx;
+  static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR;
+  static constexpr hb_tag_t os2Tag = HB_OT_TAG_OS2;
 };
 struct vmtx : hmtxvmtx<vmtx, vhea> {
-  static const hb_tag_t tableTag        = HB_OT_TAG_vmtx;
-  static const hb_tag_t variationsTag   = HB_OT_TAG_VVAR;
-  static const hb_tag_t os2Tag          = HB_TAG_NONE;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx;
+  static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR;
+  static constexpr hb_tag_t os2Tag = HB_TAG_NONE;
 };
 
+struct hmtx_accelerator_t : hmtx::accelerator_t {};
+struct vmtx_accelerator_t : vmtx::accelerator_t {};
+
 } /* namespace OT */
 
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-kern-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-kern-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,7 +27,8 @@
 #ifndef HB_OT_KERN_TABLE_HH
 #define HB_OT_KERN_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-aat-layout-kerx-table.hh"
+
 
 /*
  * kern -- Kerning
@@ -40,354 +41,297 @@
 namespace OT {
 
 
-struct hb_glyph_pair_t
+template <typename KernSubTableHeader>
+struct KernSubTableFormat3
 {
-  hb_codepoint_t left;
-  hb_codepoint_t right;
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+  {
+    hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount);
+    hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (kernValue).as_array (glyphCount);
+    hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (leftClass).as_array (glyphCount);
+    hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8> > (rightClass).as_array (leftClassCount * rightClassCount);
+
+    unsigned int leftC = leftClass[left];
+    unsigned int rightC = rightClass[right];
+    if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount))
+      return 0;
+    unsigned int i = leftC * rightClassCount + rightC;
+    return kernValue[kernIndex[i]];
+  }
+
+  bool apply (AAT::hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    if (!c->plan->requested_kerning)
+      return false;
+
+    if (header.coverage & header.Backwards)
+      return false;
+
+    hb_kern_machine_t<KernSubTableFormat3> machine (*this, 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 (c->check_struct (this) &&
+                  c->check_range (kernValueZ,
+                                  kernValueCount * sizeof (FWORD) +
+                                  glyphCount * 2 +
+                                  leftClassCount * rightClassCount));
+  }
+
+  protected:
+  KernSubTableHeader    header;
+  HBUINT16              glyphCount;     /* The number of glyphs in this font. */
+  HBUINT8               kernValueCount; /* The number of kerning values. */
+  HBUINT8               leftClassCount; /* The number of left-hand classes. */
+  HBUINT8               rightClassCount;/* The number of right-hand classes. */
+  HBUINT8               flags;          /* Set to zero (reserved for future use). */
+  UnsizedArrayOf<FWORD> kernValueZ;     /* The kerning values.
+                                         * Length kernValueCount. */
+#if 0
+  UnsizedArrayOf<HBUINT8>leftClass;     /* The left-hand classes.
+                                         * Length glyphCount. */
+  UnsizedArrayOf<HBUINT8>rightClass;    /* The right-hand classes.
+                                         * Length glyphCount. */
+  UnsizedArrayOf<HBUINT8>kernIndex;     /* The indices into the kernValue array.
+                                         * Length leftClassCount * rightClassCount */
+#endif
+  public:
+  DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ);
 };
 
-struct KernPair
+template <typename KernSubTableHeader>
+struct KernSubTable
 {
-  inline int get_kerning (void) const
-  { return value; }
+  unsigned int get_size () const { return u.header.length; }
+  unsigned int get_type () const { return u.header.format; }
 
-  inline int cmp (const hb_glyph_pair_t &o) const
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
   {
-    int ret = left.cmp (o.left);
-    if (ret) return ret;
-    return right.cmp (o.right);
+    switch (get_type ()) {
+    /* This method hooks up to hb_font_t's get_h_kerning.  Only support Format0. */
+    case 0: return u.format0.get_kerning (left, right);
+    default:return 0;
+    }
+  }
+
+  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 (u.header.apple ? c->dispatch (u.format1) : c->default_return_value ());
+    case 2:     return_trace (c->dispatch (u.format2));
+    case 3:     return_trace (u.header.apple ? c->dispatch (u.format3) : c->default_return_value ());
+    default:    return_trace (c->default_return_value ());
+    }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!u.header.sanitize (c) ||
+                  u.header.length < u.header.min_size ||
+                  !c->check_range (this, u.header.length))) return_trace (false);
+
+    return_trace (dispatch (c));
+  }
+
+  public:
+  union {
+  KernSubTableHeader                            header;
+  AAT::KerxSubTableFormat0<KernSubTableHeader>  format0;
+  AAT::KerxSubTableFormat1<KernSubTableHeader>  format1;
+  AAT::KerxSubTableFormat2<KernSubTableHeader>  format2;
+  KernSubTableFormat3<KernSubTableHeader>       format3;
+  } u;
+  public:
+  DEFINE_SIZE_MIN (KernSubTableHeader::static_size);
+};
+
+
+struct KernOTSubTableHeader
+{
+  static constexpr bool apple = false;
+  typedef AAT::ObsoleteTypes Types;
+
+  unsigned int tuple_count () const { return 0; }
+  bool is_horizontal () const { return (coverage & Horizontal); }
+
+  enum Coverage
+  {
+    Horizontal  = 0x01u,
+    Minimum     = 0x02u,
+    CrossStream = 0x04u,
+    Override    = 0x08u,
+
+    /* Not supported: */
+    Backwards   = 0x00u,
+    Variation   = 0x00u,
+  };
+
+  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:
+  HBUINT16      versionZ;       /* Unused. */
+  HBUINT16      length;         /* Length of the subtable (including this header). */
+  HBUINT8       format;         /* Subtable format. */
+  HBUINT8       coverage;       /* Coverage bits. */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
-struct KernSubTableFormat0
+struct KernOT : AAT::KerxTable<KernOT>
 {
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
-  {
-    hb_glyph_pair_t pair = {left, right};
-    int i = pairs.bsearch (pair);
-    if (i == -1)
-      return 0;
-    return pairs[i].get_kerning ();
-  }
+  friend struct AAT::KerxTable<KernOT>;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (pairs.sanitize (c));
-  }
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
+  static constexpr unsigned minVersion = 0u;
 
-  protected:
-  BinSearchArrayOf<KernPair> pairs;     /* Array of kerning pairs. */
-  public:
-  DEFINE_SIZE_ARRAY (8, pairs);
-};
-
-struct KernClassTable
-{
-  inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (firstGlyph.sanitize (c) && classes.sanitize (c));
-  }
+  typedef KernOTSubTableHeader SubTableHeader;
+  typedef SubTableHeader::Types Types;
+  typedef KernSubTable<SubTableHeader> SubTable;
 
   protected:
-  HBUINT16              firstGlyph;     /* First glyph in class range. */
-  ArrayOf<HBUINT16>     classes;        /* Glyph classes. */
+  HBUINT16      version;        /* Version--0x0000u */
+  HBUINT16      tableCount;     /* Number of subtables in the kerning table. */
+  SubTable      firstSubTable;  /* Subtables. */
   public:
-  DEFINE_SIZE_ARRAY (4, classes);
+  DEFINE_SIZE_MIN (4);
 };
 
-struct KernSubTableFormat2
+
+struct KernAATSubTableHeader
 {
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
+  static constexpr bool apple = true;
+  typedef AAT::ObsoleteTypes Types;
+
+  unsigned int tuple_count () const { return 0; }
+  bool is_horizontal () const       { return !(coverage & Vertical); }
+
+  enum Coverage
   {
-    unsigned int l = (this+leftClassTable).get_class (left);
-    unsigned int r = (this+rightClassTable).get_class (right);
-    unsigned int offset = l * rowWidth + r * sizeof (FWORD);
-    const FWORD *arr = &(this+array);
-    if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end))
-      return 0;
-    const FWORD *v = &StructAtOffset<FWORD> (arr, offset);
-    if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end))
-      return 0;
-    return *v;
+    Vertical    = 0x80u,
+    CrossStream = 0x40u,
+    Variation   = 0x20u,
+
+    /* Not supported: */
+    Backwards   = 0x00u,
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rowWidth.sanitize (c) &&
-                  leftClassTable.sanitize (c, this) &&
-                  rightClassTable.sanitize (c, this) &&
-                  array.sanitize (c, this));
-  }
+  public:
+  HBUINT32      length;         /* Length of the subtable (including this header). */
+  HBUINT8       coverage;       /* Coverage bits. */
+  HBUINT8       format;         /* Subtable format. */
+  HBUINT16      tupleIndex;     /* The tuple index (used for variations fonts).
+                               * This value specifies which tuple this subtable covers.
+                               * Note: We don't implement. */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct KernAAT : AAT::KerxTable<KernAAT>
+{
+  friend struct AAT::KerxTable<KernAAT>;
+
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
+  static constexpr unsigned minVersion = 0x00010000u;
+
+  typedef KernAATSubTableHeader SubTableHeader;
+  typedef SubTableHeader::Types Types;
+  typedef KernSubTable<SubTableHeader> SubTable;
 
   protected:
-  HBUINT16      rowWidth;       /* The width, in bytes, of a row in the table. */
-  OffsetTo<KernClassTable>
-                leftClassTable; /* Offset from beginning of this subtable to
-                                 * left-hand class table. */
-  OffsetTo<KernClassTable>
-                rightClassTable;/* Offset from beginning of this subtable to
-                                 * right-hand class table. */
-  OffsetTo<FWORD>
-                array;          /* Offset from beginning of this subtable to
-                                 * the start of the kerning array. */
+  HBUINT32      version;        /* Version--0x00010000u */
+  HBUINT32      tableCount;     /* Number of subtables in the kerning table. */
+  SubTable      firstSubTable;  /* Subtables. */
   public:
   DEFINE_SIZE_MIN (8);
 };
 
-struct KernSubTable
+struct kern
 {
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
+
+  bool has_data () const { return u.version32; }
+  unsigned int get_type () const { return u.major; }
+
+  bool has_state_machine () const
   {
-    switch (format) {
-    case 0: return u.format0.get_kerning (left, right);
-    case 2: return u.format2.get_kerning (left, right, end);
+    switch (get_type ()) {
+    case 0: return u.ot.has_state_machine ();
+    case 1: return u.aat.has_state_machine ();
+    default:return false;
+    }
+  }
+
+  bool has_cross_stream () const
+  {
+    switch (get_type ()) {
+    case 0: return u.ot.has_cross_stream ();
+    case 1: return u.aat.has_cross_stream ();
+    default:return false;
+    }
+  }
+
+  int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+  {
+    switch (get_type ()) {
+    case 0: return u.ot.get_h_kerning (left, right);
+    case 1: return u.aat.get_h_kerning (left, right);
     default:return 0;
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const
+  bool apply (AAT::hb_aat_apply_context_t *c) const
+  { return dispatch (c); }
+
+  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.ot));
+    case 1:     return_trace (c->dispatch (u.aat));
+    default:    return_trace (c->default_return_value ());
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    switch (format) {
-    case 0: return_trace (u.format0.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    default:return_trace (true);
-    }
+    if (!u.version32.sanitize (c)) return_trace (false);
+    return_trace (dispatch (c));
   }
 
   protected:
   union {
-  KernSubTableFormat0   format0;
-  KernSubTableFormat2   format2;
-  } u;
-  public:
-  DEFINE_SIZE_MIN (0);
-};
-
-
-template <typename T>
-struct KernSubTableWrapper
-{
-  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
-  inline const T* thiz (void) const { return static_cast<const T *> (this); }
-
-  inline bool is_horizontal (void) const
-  { return (thiz()->coverage & T::COVERAGE_CHECK_FLAGS) == T::COVERAGE_CHECK_HORIZONTAL; }
-
-  inline bool is_override (void) const
-  { return bool (thiz()->coverage & T::COVERAGE_OVERRIDE_FLAG); }
-
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
-  { return thiz()->subtable.get_kerning (left, right, end, thiz()->format); }
-
-  inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
-  { return is_horizontal () ? get_kerning (left, right, end) : 0; }
-
-  inline unsigned int get_size (void) const { return thiz()->length; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (thiz()) &&
-                  thiz()->length >= T::min_size &&
-                  c->check_array (thiz(), 1, thiz()->length) &&
-                  thiz()->subtable.sanitize (c, thiz()->format));
-  }
-};
-
-template <typename T>
-struct KernTable
-{
-  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
-  inline const T* thiz (void) const { return static_cast<const T *> (this); }
-
-  inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
-  {
-    int v = 0;
-    const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
-    unsigned int count = thiz()->nTables;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (st->is_override ())
-        v = 0;
-      v += st->get_h_kerning (left, right, table_length + (const char *) this);
-      st = &StructAfter<typename T::SubTableWrapper> (*st);
-    }
-    return v;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (thiz()) ||
-                  thiz()->version != T::VERSION))
-      return_trace (false);
-
-    const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
-    unsigned int count = thiz()->nTables;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (unlikely (!st->sanitize (c)))
-        return_trace (false);
-      st = &StructAfter<typename T::SubTableWrapper> (*st);
-    }
-
-    return_trace (true);
-  }
-};
-
-struct KernOT : KernTable<KernOT>
-{
-  friend struct KernTable<KernOT>;
-
-  static const uint16_t VERSION = 0x0000u;
-
-  struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
-  {
-    friend struct KernSubTableWrapper<SubTableWrapper>;
-
-    enum coverage_flags_t {
-      COVERAGE_DIRECTION_FLAG   = 0x01u,
-      COVERAGE_MINIMUM_FLAG     = 0x02u,
-      COVERAGE_CROSSSTREAM_FLAG = 0x04u,
-      COVERAGE_OVERRIDE_FLAG    = 0x08u,
-
-      COVERAGE_VARIATION_FLAG   = 0x00u, /* Not supported. */
-
-      COVERAGE_CHECK_FLAGS      = 0x07u,
-      COVERAGE_CHECK_HORIZONTAL = 0x01u
-    };
-
-    protected:
-    HBUINT16    versionZ;       /* Unused. */
-    HBUINT16    length;         /* Length of the subtable (including this header). */
-    HBUINT8     format;         /* Subtable format. */
-    HBUINT8     coverage;       /* Coverage bits. */
-    KernSubTable subtable;      /* Subtable data. */
-    public:
-    DEFINE_SIZE_MIN (6);
-  };
-
-  protected:
-  HBUINT16      version;        /* Version--0x0000u */
-  HBUINT16      nTables;        /* Number of subtables in the kerning table. */
-  HBUINT8               data[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (4, data);
-};
-
-struct KernAAT : KernTable<KernAAT>
-{
-  friend struct KernTable<KernAAT>;
-
-  static const uint32_t VERSION = 0x00010000u;
-
-  struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
-  {
-    friend struct KernSubTableWrapper<SubTableWrapper>;
-
-    enum coverage_flags_t {
-      COVERAGE_DIRECTION_FLAG   = 0x80u,
-      COVERAGE_CROSSSTREAM_FLAG = 0x40u,
-      COVERAGE_VARIATION_FLAG   = 0x20u,
-
-      COVERAGE_OVERRIDE_FLAG    = 0x00u, /* Not supported. */
-
-      COVERAGE_CHECK_FLAGS      = 0xE0u,
-      COVERAGE_CHECK_HORIZONTAL = 0x00u
-    };
-
-    protected:
-    HBUINT32    length;         /* Length of the subtable (including this header). */
-    HBUINT8     coverage;       /* Coverage bits. */
-    HBUINT8     format;         /* Subtable format. */
-    HBUINT16    tupleIndex;     /* The tuple index (used for variations fonts).
-                                 * This value specifies which tuple this subtable covers. */
-    KernSubTable subtable;      /* Subtable data. */
-    public:
-    DEFINE_SIZE_MIN (8);
-  };
-
-  protected:
-  HBUINT32              version;        /* Version--0x00010000u */
-  HBUINT32              nTables;        /* Number of subtables in the kerning table. */
-  HBUINT8               data[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (8, data);
-};
-
-struct kern
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_kern;
-
-  inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
-  {
-    switch (u.major) {
-    case 0: return u.ot.get_h_kerning (left, right, table_length);
-    case 1: return u.aat.get_h_kerning (left, right, table_length);
-    default:return 0;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.major.sanitize (c)) return_trace (false);
-    switch (u.major) {
-    case 0: return_trace (u.ot.sanitize (c));
-    case 1: return_trace (u.aat.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  struct accelerator_t
-  {
-    inline void init (hb_face_t *face)
-    {
-      blob = Sanitizer<kern>().sanitize (face->reference_table (HB_OT_TAG_kern));
-      table = blob->as<kern> ();
-      table_length = blob->length;
-    }
-    inline void fini (void)
-    {
-      hb_blob_destroy (blob);
-    }
-
-    inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
-    { return table->get_h_kerning (left, right, table_length); }
-
-    private:
-    hb_blob_t *blob;
-    const kern *table;
-    unsigned int table_length;
-  };
-
-  protected:
-  union {
+  HBUINT32              version32;
   HBUINT16              major;
   KernOT                ot;
   KernAAT               aat;
   } u;
   public:
-  DEFINE_SIZE_UNION (2, major);
+  DEFINE_SIZE_UNION (4, version32);
 };
 
 } /* namespace OT */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-base-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-base-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -1,6 +1,7 @@
 /*
  * Copyright © 2016 Elie Roux <elie.roux@telecom-bretagne.eu>
  * Copyright © 2018  Google, Inc.
+ * Copyright © 2018  Ebrahim Byagowi
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -28,13 +29,14 @@
 #ifndef HB_OT_LAYOUT_BASE_TABLE_HH
 #define HB_OT_LAYOUT_BASE_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-ot-layout-common-private.hh"
+#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
+
+/* To be removed */
+typedef hb_tag_t hb_ot_layout_baseline_t;
 
 namespace OT {
 
-#define NOT_INDEXED   ((unsigned int) -1)
-
 /*
  * BASE -- Baseline
  * https://docs.microsoft.com/en-us/typography/opentype/spec/base
@@ -42,30 +44,30 @@
 
 struct BaseCoordFormat1
 {
-  inline int get_coord (void) const { return coordinate; }
+  hb_position_t get_coord () const { return coordinate; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    return_trace (likely (c->check_struct (this)));
   }
 
   protected:
   HBUINT16      format;         /* Format identifier--format = 1 */
-  HBINT16       coordinate;     /* X or Y value, in design units */
+  FWORD         coordinate;     /* X or Y value, in design units */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 struct BaseCoordFormat2
 {
-  inline int get_coord (void) const
+  hb_position_t get_coord () const
   {
     /* TODO */
     return coordinate;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -73,7 +75,7 @@
 
   protected:
   HBUINT16      format;         /* Format identifier--format = 2 */
-  HBINT16       coordinate;     /* X or Y value, in design units */
+  FWORD         coordinate;     /* X or Y value, in design units */
   GlyphID       referenceGlyph; /* Glyph ID of control glyph */
   HBUINT16      coordPoint;     /* Index of contour point on the
                                  * reference glyph */
@@ -83,44 +85,53 @@
 
 struct BaseCoordFormat3
 {
-  inline int get_coord (void) const
+  hb_position_t get_coord (hb_font_t *font,
+                           const VariationStore &var_store,
+                           hb_direction_t direction) const
   {
-    /* TODO */
-    return coordinate;
+    const Device &device = this+deviceTable;
+    return coordinate + (HB_DIRECTION_IS_VERTICAL (direction) ?
+                         device.get_y_delta (font, var_store) :
+                         device.get_x_delta (font, var_store));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                          deviceTable.sanitize (c, this)));
   }
 
   protected:
-  HBUINT16              format;         /* Format identifier--format = 3 */
-  HBINT16               coordinate;     /* X or Y value, in design units */
-  OffsetTo<Device>      deviceTable;    /* Offset to Device table for X or
-                                         * Y value, from beginning of
-                                         * BaseCoord table (may be NULL). */
+  HBUINT16      format;         /* Format identifier--format = 3 */
+  FWORD         coordinate;     /* X or Y value, in design units */
+  OffsetTo<Device>
+                deviceTable;    /* Offset to Device table for X or
+                                 * Y value, from beginning of
+                                 * BaseCoord table (may be NULL). */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
 struct BaseCoord
 {
-  inline int get_coord (void) const
+  hb_position_t get_coord (hb_font_t *font,
+                           const VariationStore &var_store,
+                           hb_direction_t direction) const
   {
     switch (u.format) {
     case 1: return u.format1.get_coord ();
     case 2: return u.format2.get_coord ();
-    case 3: return u.format3.get_coord ();
+    case 3: return u.format3.get_coord (font, var_store, direction);
     default:return 0;
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
+    if (unlikely (!u.format.sanitize (c))) return_trace (false);
     switch (u.format) {
     case 1: return_trace (u.format1.sanitize (c));
     case 2: return_trace (u.format2.sanitize (c));
@@ -142,32 +153,40 @@
 
 struct FeatMinMaxRecord
 {
-  inline int get_min_value (void) const
-  { return (this+minCoord).get_coord(); }
+  static int cmp (const void *key_, const void *entry_)
+  {
+    hb_tag_t key = * (hb_tag_t *) key_;
+    const FeatMinMaxRecord &entry = * (const FeatMinMaxRecord *) entry_;
+    return key < (unsigned int) entry.tag ? -1 :
+           key > (unsigned int) entry.tag ? 1 :
+           0;
+  }
 
-  inline int get_max_value (void) const
-  { return (this+maxCoord).get_coord(); }
+  void get_min_max (const BaseCoord **min, const BaseCoord **max) const
+  {
+    if (likely (min)) *min = &(this+minCoord);
+    if (likely (max)) *max = &(this+maxCoord);
+  }
 
-  inline const Tag &get_tag () const
-  { return tag; }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  minCoord.sanitize (c, base) &&
-                  maxCoord.sanitize (c, base));
+    return_trace (likely (c->check_struct (this) &&
+                          minCoord.sanitize (c, this) &&
+                          maxCoord.sanitize (c, this)));
   }
 
   protected:
-  Tag                   tag;            /* 4-byte feature identification tag--must
-                                         * match feature tag in FeatureList */
-  OffsetTo<BaseCoord>   minCoord;       /* Offset to BaseCoord table that defines
-                                         * the minimum extent value, from beginning
-                                         * of MinMax table (may be NULL) */
-  OffsetTo<BaseCoord>   maxCoord;       /* Offset to BaseCoord table that defines
-                                         * the maximum extent value, from beginning
-                                         * of MinMax table (may be NULL) */
+  Tag           tag;            /* 4-byte feature identification tag--must
+                                 * match feature tag in FeatureList */
+  OffsetTo<BaseCoord>
+                minCoord;       /* Offset to BaseCoord table that defines
+                                 * the minimum extent value, from beginning
+                                 * of MinMax table (may be NULL) */
+  OffsetTo<BaseCoord>
+                maxCoord;       /* Offset to BaseCoord table that defines
+                                 * the maximum extent value, from beginning
+                                 * of MinMax table (may be NULL) */
   public:
   DEFINE_SIZE_STATIC (8);
 
@@ -175,356 +194,269 @@
 
 struct MinMax
 {
-  inline unsigned int get_feature_tag_index (Tag featureTableTag) const
+  void get_min_max (hb_tag_t          feature_tag,
+                           const BaseCoord **min,
+                           const BaseCoord **max) const
   {
-    /* TODO bsearch */
-    unsigned int count = featMinMaxRecords.len;
-    for (unsigned int i = 0; i < count; i++)
+    /* TODO Replace hb_bsearch() with .bsearch(). */
+    const FeatMinMaxRecord *minMaxCoord = (const FeatMinMaxRecord *)
+                                          hb_bsearch (&feature_tag, featMinMaxRecords.arrayZ,
+                                                      featMinMaxRecords.len,
+                                                      FeatMinMaxRecord::static_size,
+                                                      FeatMinMaxRecord::cmp);
+    if (minMaxCoord)
+      minMaxCoord->get_min_max (min, max);
+    else
     {
-      Tag tag = featMinMaxRecords[i].get_tag();
-      int cmp = tag.cmp(featureTableTag);
-      if (cmp == 0) return i;
-      if (cmp > 0)  return NOT_INDEXED;
+      if (likely (min)) *min = &(this+minCoord);
+      if (likely (max)) *max = &(this+maxCoord);
     }
-    return NOT_INDEXED;
   }
 
-  inline int get_min_value (unsigned int featureTableTagIndex) const
-  {
-    if (featureTableTagIndex == NOT_INDEXED)
-      return (this+minCoord).get_coord();
-    return featMinMaxRecords[featureTableTagIndex].get_min_value();
-  }
-
-  inline int get_max_value (unsigned int featureTableTagIndex) const
-  {
-    if (featureTableTagIndex == NOT_INDEXED)
-      return (this+maxCoord).get_coord();
-    return featMinMaxRecords[featureTableTagIndex].get_max_value();
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  minCoord.sanitize (c, this) &&
-                  maxCoord.sanitize (c, this) &&
-                  featMinMaxRecords.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                          minCoord.sanitize (c, this) &&
+                          maxCoord.sanitize (c, this) &&
+                          featMinMaxRecords.sanitize (c, this)));
   }
 
   protected:
-  OffsetTo<BaseCoord>   minCoord;       /* Offset to BaseCoord table that defines
-                                         * minimum extent value, from the beginning
-                                         * of MinMax table (may be NULL) */
-  OffsetTo<BaseCoord>   maxCoord;       /* Offset to BaseCoord table that defines
-                                         * maximum extent value, from the beginning
-                                         * of MinMax table (may be NULL) */
-  ArrayOf<FeatMinMaxRecord>
-                featMinMaxRecords;      /* Array of FeatMinMaxRecords, in alphabetical
-                                         * order by featureTableTag */
+  OffsetTo<BaseCoord>
+                minCoord;       /* Offset to BaseCoord table that defines
+                                 * minimum extent value, from the beginning
+                                 * of MinMax table (may be NULL) */
+  OffsetTo<BaseCoord>
+                maxCoord;       /* Offset to BaseCoord table that defines
+                                 * maximum extent value, from the beginning
+                                 * of MinMax table (may be NULL) */
+  SortedArrayOf<FeatMinMaxRecord>
+                featMinMaxRecords;
+                                /* Array of FeatMinMaxRecords, in alphabetical
+                                 * order by featureTableTag */
   public:
   DEFINE_SIZE_ARRAY (6, featMinMaxRecords);
 };
 
-/* TODO... */
-struct BaseLangSysRecord
-{
-  inline const Tag& get_tag(void) const
-  { return baseLangSysTag; }
-
-  inline unsigned int get_feature_tag_index (Tag featureTableTag) const
-  { return (this+minMax).get_feature_tag_index(featureTableTag); }
-
-  inline int get_min_value (unsigned int featureTableTagIndex) const
-  { return (this+minMax).get_min_value(featureTableTagIndex); }
-
-  inline int get_max_value (unsigned int featureTableTagIndex) const
-  { return (this+minMax).get_max_value(featureTableTagIndex); }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  minMax.sanitize (c, base));
-  }
-
-  protected:
-  Tag                   baseLangSysTag;
-  OffsetTo<MinMax>      minMax;
-  public:
-  DEFINE_SIZE_STATIC (6);
-
-};
-
 struct BaseValues
 {
-  inline unsigned int get_default_base_tag_index (void) const
-  { return defaultIndex; }
-
-  inline int get_base_coord (unsigned int baselineTagIndex) const
+  const BaseCoord &get_base_coord (int baseline_tag_index) const
   {
-    return (this+baseCoords[baselineTagIndex]).get_coord();
+    if (baseline_tag_index == -1) baseline_tag_index = defaultIndex;
+    return this+baseCoords[baseline_tag_index];
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      defaultIndex <= baseCoordCount &&
-      baseCoords.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                          baseCoords.sanitize (c, this)));
   }
 
   protected:
-  Index                         defaultIndex;
-  HBUINT16                      baseCoordCount;
-  OffsetArrayOf<BaseCoord>      baseCoords;
+  Index         defaultIndex;   /* Index number of default baseline for this
+                                 * script — equals index position of baseline tag
+                                 * in baselineTags array of the BaseTagList */
+  OffsetArrayOf<BaseCoord>
+                baseCoords;     /* Number of BaseCoord tables defined — should equal
+                                 * baseTagCount in the BaseTagList
+                                 *
+                                 * Array of offsets to BaseCoord tables, from beginning of
+                                 * BaseValues table — order matches baselineTags array in
+                                 * the BaseTagList */
   public:
-  DEFINE_SIZE_ARRAY (6, baseCoords);
-
+  DEFINE_SIZE_ARRAY (4, baseCoords);
 };
 
-struct BaseScript {
-
-  inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
+struct BaseLangSysRecord
+{
+  static int cmp (const void *key_, const void *entry_)
   {
-    Tag tag;
-    int cmp;
-    for (unsigned int i = 0; i < baseLangSysCount; i++) {
-      tag = baseLangSysRecords[i].get_tag();
-      // taking advantage of alphabetical order
-      cmp = tag.cmp(baseLangSysTag);
-      if (cmp == 0) return i;
-      if (cmp > 0)  return NOT_INDEXED;
-    }
-    return NOT_INDEXED;
+    hb_tag_t key = * (hb_tag_t *) key_;
+    const BaseLangSysRecord &entry = * (const BaseLangSysRecord *) entry_;
+    return key < (unsigned int) entry.baseLangSysTag ? -1 :
+           key > (unsigned int) entry.baseLangSysTag ? 1 :
+           0;
   }
 
-  inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (baseLangSysIndex == NOT_INDEXED) {
-      if (unlikely(defaultMinMax)) return NOT_INDEXED;
-      return (this+defaultMinMax).get_feature_tag_index(featureTableTag);
-    }
-    if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED;
-    return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag);
-  }
+  const MinMax &get_min_max () const
+  { return this+minMax; }
 
-  inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    if (baseLangSysIndex == NOT_INDEXED)
-      return (this+defaultMinMax).get_min_value(featureTableTagIndex);
-    return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
-  }
-
-  inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    if (baseLangSysIndex == NOT_INDEXED)
-      return (this+defaultMinMax).get_min_value(featureTableTagIndex);
-    return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
-  }
-
-  inline unsigned int get_default_base_tag_index (void) const
-  { return (this+baseValues).get_default_base_tag_index(); }
-
-  inline int get_base_coord (unsigned int baselineTagIndex) const
-  { return (this+baseValues).get_base_coord(baselineTagIndex); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseValues.sanitize (c, this) &&
-      defaultMinMax.sanitize (c, this) &&
-      baseLangSysRecords.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                          minMax.sanitize (c, this)));
   }
 
   protected:
-  OffsetTo<BaseValues>        baseValues;
-  OffsetTo<MinMax>            defaultMinMax;
-  HBUINT16                      baseLangSysCount;
-  ArrayOf<BaseLangSysRecord>  baseLangSysRecords;
-
+  Tag           baseLangSysTag; /* 4-byte language system identification tag */
+  OffsetTo<MinMax>
+                minMax;         /* Offset to MinMax table, from beginning
+                                 * of BaseScript table */
   public:
-    DEFINE_SIZE_ARRAY (8, baseLangSysRecords);
+  DEFINE_SIZE_STATIC (6);
 };
 
-
-struct BaseScriptRecord {
-
-  inline const Tag& get_tag (void) const
-  { return baseScriptTag; }
-
-  inline unsigned int get_default_base_tag_index(void) const
-  { return (this+baseScript).get_default_base_tag_index(); }
-
-  inline int get_base_coord(unsigned int baselineTagIndex) const
-  { return (this+baseScript).get_base_coord(baselineTagIndex); }
+struct BaseScript
+{
+  const MinMax &get_min_max (hb_tag_t language_tag) const
+  {
+    /* TODO Replace hb_bsearch() with .bsearch(). */
+    const BaseLangSysRecord* record = (const BaseLangSysRecord *)
+                                      hb_bsearch (&language_tag, baseLangSysRecords.arrayZ,
+                                                  baseLangSysRecords.len,
+                                                  BaseLangSysRecord::static_size,
+                                                  BaseLangSysRecord::cmp);
+    return record ? record->get_min_max () : this+defaultMinMax;
+  }
 
-  inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
-  { return (this+baseScript).get_lang_tag_index(baseLangSysTag); }
-
-  inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
-  { return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); }
+  const BaseCoord &get_base_coord (int baseline_tag_index) const
+  { return (this+baseValues).get_base_coord (baseline_tag_index); }
 
-  inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  { return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); }
+  bool is_empty () const { return !baseValues; }
 
-  inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  { return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseScript != Null(OffsetTo<BaseScript>) &&
-      baseScript.sanitize (c, base));
+    return_trace (likely (c->check_struct (this) &&
+                          baseValues.sanitize (c, this) &&
+                          defaultMinMax.sanitize (c, this) &&
+                          baseLangSysRecords.sanitize (c, this)));
   }
 
   protected:
-  Tag                   baseScriptTag;
-  OffsetTo<BaseScript>  baseScript;
+  OffsetTo<BaseValues>
+                baseValues;     /* Offset to BaseValues table, from beginning
+                                 * of BaseScript table (may be NULL) */
+  OffsetTo<MinMax>
+                defaultMinMax;  /* Offset to MinMax table, from beginning of
+                                 * BaseScript table (may be NULL) */
+  SortedArrayOf<BaseLangSysRecord>
+                baseLangSysRecords;
+                                /* Number of BaseLangSysRecords
+                                 * defined — may be zero (0) */
 
   public:
-    DEFINE_SIZE_STATIC (6);
+  DEFINE_SIZE_ARRAY (6, baseLangSysRecords);
 };
 
-struct BaseScriptList {
-
-  inline unsigned int get_base_script_index (Tag baseScriptTag) const
+struct BaseScriptList;
+struct BaseScriptRecord
+{
+  static int cmp (const void *key_, const void *entry_)
   {
-    for (unsigned int i = 0; i < baseScriptCount; i++)
-      if (baseScriptRecords[i].get_tag() == baseScriptTag)
-        return i;
-    return NOT_INDEXED;
-  }
-
-  inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
-    return baseScriptRecords[baseScriptIndex].get_default_base_tag_index();
+    hb_tag_t key = * (hb_tag_t *) key_;
+    const BaseScriptRecord &entry = * (const BaseScriptRecord *) entry_;
+    return key < (unsigned int) entry.baseScriptTag ? -1 :
+           key > (unsigned int) entry.baseScriptTag ? 1 :
+           0;
   }
 
-  inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return baseScriptRecords[baseScriptIndex].get_base_coord(baselineTagIndex);
-  }
+  const BaseScript &get_base_script (const BaseScriptList *list) const
+  { return list+baseScript; }
 
-  inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
-    return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag);
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          baseScript.sanitize (c, base)));
   }
 
-  inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+  protected:
+  Tag           baseScriptTag;  /* 4-byte script identification tag */
+  OffsetTo<BaseScript>
+                baseScript;     /* Offset to BaseScript table, from beginning
+                                 * of BaseScriptList */
+
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct BaseScriptList
+{
+  const BaseScriptRecord *find_record (hb_tag_t script) const
   {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
-    return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag);
+    /* TODO Replace hb_bsearch() with .bsearch(). */
+    return (const BaseScriptRecord *) hb_bsearch (&script, baseScriptRecords.arrayZ,
+                                                  baseScriptRecords.len,
+                                                  BaseScriptRecord::static_size,
+                                                  BaseScriptRecord::cmp);
   }
 
-  inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  /* TODO: Or client should handle fallback? */
+  const BaseScript &get_base_script (hb_tag_t script) const
   {
-    return baseScriptRecords[baseScriptIndex].get_max_value(baseLangSysIndex, featureTableTagIndex);
+    const BaseScriptRecord *record = find_record (script);
+    if (!record) record = find_record ((hb_script_t) HB_TAG ('D','F','L','T'));
+
+    return record ? record->get_base_script (this) : Null (BaseScript);
   }
 
-  inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return baseScriptRecords[baseScriptIndex].get_min_value(baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-      baseScriptRecords.sanitize (c, this));
+                  baseScriptRecords.sanitize (c, this));
   }
 
   protected:
-  HBUINT16                    baseScriptCount;
-  ArrayOf<BaseScriptRecord> baseScriptRecords;
+  SortedArrayOf<BaseScriptRecord>
+                        baseScriptRecords;
 
   public:
-  DEFINE_SIZE_ARRAY (4, baseScriptRecords);
-
-};
-
-struct BaseTagList
-{
-
-  inline unsigned int get_tag_index(Tag baselineTag) const
-  {
-    for (unsigned int i = 0; i < baseTagCount; i++)
-      if (baselineTags[i] == baselineTag)
-        return i;
-    return NOT_INDEXED;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  HBUINT16        baseTagCount;
-  SortedArrayOf<Tag>  baselineTags;
-
-  public:
-  DEFINE_SIZE_ARRAY (4, baselineTags);
+  DEFINE_SIZE_ARRAY (2, baseScriptRecords);
 };
 
 struct Axis
 {
-
-  inline unsigned int get_base_tag_index(Tag baselineTag) const
+  bool get_baseline (hb_ot_layout_baseline_t   baseline,
+                            hb_tag_t                  script_tag,
+                            hb_tag_t                  language_tag,
+                            const BaseCoord         **coord) const
   {
-    if (unlikely(baseTagList == Null(OffsetTo<BaseTagList>))) return NOT_INDEXED;
-    return (this+baseTagList).get_tag_index(baselineTag);
-  }
+    const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
+    if (base_script.is_empty ()) return false;
 
-  inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
-    return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex);
-  }
+    if (likely (coord)) *coord = &base_script.get_base_coord ((this+baseTagList).bsearch (baseline));
 
-  inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex);
+    return true;
   }
 
-  inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+  bool get_min_max (hb_tag_t          script_tag,
+                    hb_tag_t          language_tag,
+                    hb_tag_t          feature_tag,
+                    const BaseCoord **min_coord,
+                    const BaseCoord **max_coord) const
   {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
-    return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag);
-  }
+    const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
+    if (base_script.is_empty ()) return false;
 
-  inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
-    return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag);
+    base_script.get_min_max (language_tag).get_min_max (feature_tag, min_coord, max_coord);
+
+    return true;
   }
 
-  inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+baseScriptList).get_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+baseScriptList).get_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseTagList.sanitize (c, this) &&
-      baseScriptList.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                          (this+baseTagList).sanitize (c) &&
+                          (this+baseScriptList).sanitize (c)));
   }
 
   protected:
-  OffsetTo<BaseTagList>     baseTagList;
-  OffsetTo<BaseScriptList>  baseScriptList;
+  OffsetTo<SortedArrayOf<Tag> >
+                baseTagList;    /* Offset to BaseTagList table, from beginning
+                                 * of Axis table (may be NULL)
+                                 * Array of 4-byte baseline identification tags — must
+                                 * be in alphabetical order */
+  OffsetTo<BaseScriptList>
+                baseScriptList; /* Offset to BaseScriptList table, from beginning
+                                 * of Axis table
+                                 * Array of BaseScriptRecords, in alphabetical order
+                                 * by baseScriptTag */
 
   public:
   DEFINE_SIZE_STATIC (4);
@@ -532,119 +464,72 @@
 
 struct BASE
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_BASE;
-
-  inline bool has_vert_axis(void)
-  { return vertAxis != Null(OffsetTo<Axis>); }
-
-  inline bool has_horiz_axis(void)
-  { return horizAxis != Null(OffsetTo<Axis>); }
-
-  // horizontal axis base coords:
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_BASE;
 
-  inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const
-  {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_base_tag_index(baselineTag);
-  }
+  const Axis &get_axis (hb_direction_t direction) const
+  { return HB_DIRECTION_IS_VERTICAL (direction) ? this+vAxis : this+hAxis; }
 
-  inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
-  }
+  const VariationStore &get_var_store () const
+  { return version.to_int () < 0x00010001u ? Null (VariationStore) : this+varStore; }
 
-  inline int get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
-  }
-
-  // vertical axis base coords:
-
-  inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
+  bool get_baseline (hb_font_t               *font,
+                     hb_ot_layout_baseline_t  baseline,
+                     hb_direction_t           direction,
+                     hb_tag_t                 script_tag,
+                     hb_tag_t                 language_tag,
+                     hb_position_t           *base) const
   {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_base_tag_index(baselineTag);
-  }
+    const BaseCoord *base_coord;
+    if (!get_axis (direction).get_baseline (baseline, script_tag, language_tag, &base_coord))
+      return false;
 
-  inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
-  }
-
-  inline int get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
+    if (likely (base && base_coord)) *base = base_coord->get_coord (font,
+                                                                    get_var_store (),
+                                                                    direction);
+    return true;
   }
 
-  // horizontal axis min/max coords:
-
-  inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
-  {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
-  }
-
-  inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+  /* TODO: Expose this separately sometime? */
+  bool get_min_max (hb_font_t      *font,
+                    hb_direction_t  direction,
+                    hb_tag_t        script_tag,
+                    hb_tag_t        language_tag,
+                    hb_tag_t        feature_tag,
+                    hb_position_t  *min,
+                    hb_position_t  *max)
   {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
-  }
+    const BaseCoord *min_coord, *max_coord;
+    if (!get_axis (direction).get_min_max (script_tag, language_tag, feature_tag,
+                                           &min_coord, &max_coord))
+      return false;
 
-  inline int get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline int get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+    const VariationStore &var_store = get_var_store ();
+    if (likely (min && min_coord)) *min = min_coord->get_coord (font, var_store, direction);
+    if (likely (max && max_coord)) *max = max_coord->get_coord (font, var_store, direction);
+    return true;
   }
 
-    // vertical axis min/max coords:
-
-  inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
-  {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
-  }
-
-  inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
-  }
-
-  inline int get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline int get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  likely (version.major == 1) &&
-                  horizAxis.sanitize (c, this) &&
-                  vertAxis.sanitize (c, this) &&
-                  (version.to_int () < 0x00010001u || varStore.sanitize (c, this)));
+    return_trace (likely (c->check_struct (this) &&
+                          likely (version.major == 1) &&
+                          hAxis.sanitize (c, this) &&
+                          vAxis.sanitize (c, this) &&
+                          (version.to_int () < 0x00010001u || varStore.sanitize (c, this))));
   }
 
   protected:
-  FixedVersion<>  version;
-  OffsetTo<Axis>  horizAxis;
-  OffsetTo<Axis>  vertAxis;
+  FixedVersion<>version;        /* Version of the BASE table */
+  OffsetTo<Axis>hAxis;          /* Offset to horizontal Axis table, from beginning
+                                 * of BASE table (may be NULL) */
+  OffsetTo<Axis>vAxis;          /* Offset to vertical Axis table, from beginning
+                                 * of BASE table (may be NULL) */
   LOffsetTo<VariationStore>
-                varStore;               /* Offset to the table of Item Variation
-                                         * Store--from beginning of BASE
-                                         * header (may be NULL).  Introduced
-                                         * in version 0x00010001. */
+                varStore;       /* Offset to the table of Item Variation
+                                 * Store--from beginning of BASE
+                                 * header (may be NULL).  Introduced
+                                 * in version 0x00010001. */
   public:
   DEFINE_SIZE_MIN (8);
 };
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-common-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1786 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2010,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): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH
-#define HB_OT_LAYOUT_COMMON_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-ot-layout-private.hh"
-#include "hb-open-type-private.hh"
-#include "hb-set-private.hh"
-
-
-#ifndef HB_MAX_NESTING_LEVEL
-#define HB_MAX_NESTING_LEVEL    6
-#endif
-#ifndef HB_MAX_CONTEXT_LENGTH
-#define HB_MAX_CONTEXT_LENGTH   64
-#endif
-
-
-namespace OT {
-
-
-#define NOT_COVERED             ((unsigned int) -1)
-
-
-
-/*
- *
- * OpenType Layout Common Table Formats
- *
- */
-
-
-/*
- * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
- */
-
-template <typename Type>
-struct Record
-{
-  inline int cmp (hb_tag_t a) const {
-    return tag.cmp (a);
-  }
-
-  struct sanitize_closure_t {
-    hb_tag_t tag;
-    const void *list_base;
-  };
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    const sanitize_closure_t closure = {tag, base};
-    return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
-  }
-
-  Tag           tag;            /* 4-byte Tag identifier */
-  OffsetTo<Type>
-                offset;         /* Offset from beginning of object holding
-                                 * the Record */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-template <typename Type>
-struct RecordArrayOf : SortedArrayOf<Record<Type> > {
-  inline const Tag& get_tag (unsigned int i) const
-  {
-    /* We cheat slightly and don't define separate Null objects
-     * for Record types.  Instead, we return the correct Null(Tag)
-     * here. */
-    if (unlikely (i >= this->len)) return Null(Tag);
-    return (*this)[i].tag;
-  }
-  inline unsigned int get_tags (unsigned int start_offset,
-                                unsigned int *record_count /* IN/OUT */,
-                                hb_tag_t     *record_tags /* OUT */) const
-  {
-    if (record_count) {
-      const Record<Type> *arr = this->sub_array (start_offset, record_count);
-      unsigned int count = *record_count;
-      for (unsigned int i = 0; i < count; i++)
-        record_tags[i] = arr[i].tag;
-    }
-    return this->len;
-  }
-  inline bool find_index (hb_tag_t tag, unsigned int *index) const
-  {
-    /* If we want to allow non-sorted data, we can lsearch(). */
-    int i = this->/*lsearch*/bsearch (tag);
-    if (i != -1) {
-        if (index) *index = i;
-        return true;
-    } else {
-      if (index) *index = Index::NOT_FOUND_INDEX;
-      return false;
-    }
-  }
-};
-
-template <typename Type>
-struct RecordListOf : RecordArrayOf<Type>
-{
-  inline const Type& operator [] (unsigned int i) const
-  { return this+RecordArrayOf<Type>::operator [](i).offset; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (RecordArrayOf<Type>::sanitize (c, this));
-  }
-};
-
-
-struct RangeRecord
-{
-  inline int cmp (hb_codepoint_t g) const {
-    return g < start ? -1 : g <= end ? 0 : +1 ;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  inline bool intersects (const hb_set_t *glyphs) const {
-    return glyphs->intersects (start, end);
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    return glyphs->add_range (start, end);
-  }
-
-  GlyphID       start;          /* First GlyphID in the range */
-  GlyphID       end;            /* Last GlyphID in the range */
-  HBUINT16      value;          /* Value */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-DEFINE_NULL_DATA (OT, RangeRecord, "\000\001");
-
-
-struct IndexArray : ArrayOf<Index>
-{
-  inline unsigned int get_indexes (unsigned int start_offset,
-                                   unsigned int *_count /* IN/OUT */,
-                                   unsigned int *_indexes /* OUT */) const
-  {
-    if (_count) {
-      const HBUINT16 *arr = this->sub_array (start_offset, _count);
-      unsigned int count = *_count;
-      for (unsigned int i = 0; i < count; i++)
-        _indexes[i] = arr[i];
-    }
-    return this->len;
-  }
-};
-
-
-struct Script;
-struct LangSys;
-struct Feature;
-
-
-struct LangSys
-{
-  inline unsigned int get_feature_count (void) const
-  { return featureIndex.len; }
-  inline hb_tag_t get_feature_index (unsigned int i) const
-  { return featureIndex[i]; }
-  inline unsigned int get_feature_indexes (unsigned int start_offset,
-                                           unsigned int *feature_count /* IN/OUT */,
-                                           unsigned int *feature_indexes /* OUT */) const
-  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
-
-  inline bool has_required_feature (void) const { return reqFeatureIndex != 0xFFFFu; }
-  inline unsigned int get_required_feature_index (void) const
-  {
-    if (reqFeatureIndex == 0xFFFFu)
-      return Index::NOT_FOUND_INDEX;
-   return reqFeatureIndex;;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c,
-                        const Record<LangSys>::sanitize_closure_t * = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && featureIndex.sanitize (c));
-  }
-
-  Offset16      lookupOrderZ;   /* = Null (reserved for an offset to a
-                                 * reordering table) */
-  HBUINT16      reqFeatureIndex;/* Index of a feature required for this
-                                 * language system--if no required features
-                                 * = 0xFFFFu */
-  IndexArray    featureIndex;   /* Array of indices into the FeatureList */
-  public:
-  DEFINE_SIZE_ARRAY (6, featureIndex);
-};
-DEFINE_NULL_DATA (OT, LangSys, "\0\0\xFF\xFF");
-
-
-struct Script
-{
-  inline unsigned int get_lang_sys_count (void) const
-  { return langSys.len; }
-  inline const Tag& get_lang_sys_tag (unsigned int i) const
-  { return langSys.get_tag (i); }
-  inline unsigned int get_lang_sys_tags (unsigned int start_offset,
-                                         unsigned int *lang_sys_count /* IN/OUT */,
-                                         hb_tag_t     *lang_sys_tags /* OUT */) const
-  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
-  inline const LangSys& get_lang_sys (unsigned int i) const
-  {
-    if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
-    return this+langSys[i].offset;
-  }
-  inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
-  { return langSys.find_index (tag, index); }
-
-  inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
-  inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
-
-  inline bool sanitize (hb_sanitize_context_t *c,
-                        const Record<Script>::sanitize_closure_t * = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
-  }
-
-  protected:
-  OffsetTo<LangSys>
-                defaultLangSys; /* Offset to DefaultLangSys table--from
-                                 * beginning of Script table--may be Null */
-  RecordArrayOf<LangSys>
-                langSys;        /* Array of LangSysRecords--listed
-                                 * alphabetically by LangSysTag */
-  public:
-  DEFINE_SIZE_ARRAY (4, langSys);
-};
-
-typedef RecordListOf<Script> ScriptList;
-
-
-/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
-struct FeatureParamsSize
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return_trace (false);
-
-    /* This subtable has some "history", if you will.  Some earlier versions of
-     * Adobe tools calculated the offset of the FeatureParams sutable from the
-     * beginning of the FeatureList table!  Now, that is dealt with in the
-     * Feature implementation.  But we still need to be able to tell junk from
-     * real data.  Note: We don't check that the nameID actually exists.
-     *
-     * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
-     *
-     * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
-     * coming out soon, and that the makeotf program will build a font with a
-     * 'size' feature that is correct by the specification.
-     *
-     * The specification for this feature tag is in the "OpenType Layout Tag
-     * Registry". You can see a copy of this at:
-     * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size
-     *
-     * Here is one set of rules to determine if the 'size' feature is built
-     * correctly, or as by the older versions of MakeOTF. You may be able to do
-     * better.
-     *
-     * Assume that the offset to the size feature is according to specification,
-     * and make the following value checks. If it fails, assume the size
-     * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
-     * If this fails, reject the 'size' feature. The older makeOTF's calculated the
-     * offset from the beginning of the FeatureList table, rather than from the
-     * beginning of the 'size' Feature table.
-     *
-     * If "design size" == 0:
-     *     fails check
-     *
-     * Else if ("subfamily identifier" == 0 and
-     *     "range start" == 0 and
-     *     "range end" == 0 and
-     *     "range start" == 0 and
-     *     "menu name ID" == 0)
-     *     passes check: this is the format used when there is a design size
-     * specified, but there is no recommended size range.
-     *
-     * Else if ("design size" <  "range start" or
-     *     "design size" >   "range end" or
-     *     "range end" <= "range start" or
-     *     "menu name ID"  < 256 or
-     *     "menu name ID"  > 32767 or
-     *     menu name ID is not a name ID which is actually in the name table)
-     *     fails test
-     * Else
-     *     passes test.
-     */
-
-    if (!designSize)
-      return_trace (false);
-    else if (subfamilyID == 0 &&
-             subfamilyNameID == 0 &&
-             rangeStart == 0 &&
-             rangeEnd == 0)
-      return_trace (true);
-    else if (designSize < rangeStart ||
-             designSize > rangeEnd ||
-             subfamilyNameID < 256 ||
-             subfamilyNameID > 32767)
-      return_trace (false);
-    else
-      return_trace (true);
-  }
-
-  HBUINT16      designSize;     /* Represents the design size in 720/inch
-                                 * units (decipoints).  The design size entry
-                                 * must be non-zero.  When there is a design
-                                 * size but no recommended size range, the
-                                 * rest of the array will consist of zeros. */
-  HBUINT16      subfamilyID;    /* Has no independent meaning, but serves
-                                 * as an identifier that associates fonts
-                                 * in a subfamily. All fonts which share a
-                                 * Preferred or Font Family name and which
-                                 * differ only by size range shall have the
-                                 * same subfamily value, and no fonts which
-                                 * differ in weight or style shall have the
-                                 * same subfamily value. If this value is
-                                 * zero, the remaining fields in the array
-                                 * will be ignored. */
-  HBUINT16      subfamilyNameID;/* If the preceding value is non-zero, this
-                                 * value must be set in the range 256 - 32767
-                                 * (inclusive). It records the value of a
-                                 * field in the name table, which must
-                                 * contain English-language strings encoded
-                                 * in Windows Unicode and Macintosh Roman,
-                                 * and may contain additional strings
-                                 * localized to other scripts and languages.
-                                 * Each of these strings is the name an
-                                 * application should use, in combination
-                                 * with the family name, to represent the
-                                 * subfamily in a menu.  Applications will
-                                 * choose the appropriate version based on
-                                 * their selection criteria. */
-  HBUINT16      rangeStart;     /* Large end of the recommended usage range
-                                 * (inclusive), stored in 720/inch units
-                                 * (decipoints). */
-  HBUINT16      rangeEnd;       /* Small end of the recommended usage range
-                                   (exclusive), stored in 720/inch units
-                                 * (decipoints). */
-  public:
-  DEFINE_SIZE_STATIC (10);
-};
-
-/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#ssxx */
-struct FeatureParamsStylisticSet
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    /* Right now minorVersion is at zero.  Which means, any table supports
-     * the uiNameID field. */
-    return_trace (c->check_struct (this));
-  }
-
-  HBUINT16      version;        /* (set to 0): This corresponds to a “minor”
-                                 * version number. Additional data may be
-                                 * added to the end of this Feature Parameters
-                                 * table in the future. */
-
-  NameID        uiNameID;       /* The 'name' table name ID that specifies a
-                                 * string (or strings, for multiple languages)
-                                 * for a user-interface label for this
-                                 * feature.  The values of uiLabelNameId and
-                                 * sampleTextNameId are expected to be in the
-                                 * font-specific name ID range (256-32767),
-                                 * though that is not a requirement in this
-                                 * Feature Parameters specification. The
-                                 * user-interface label for the feature can
-                                 * be provided in multiple languages. An
-                                 * English string should be included as a
-                                 * fallback. The string should be kept to a
-                                 * minimal length to fit comfortably with
-                                 * different application interfaces. */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#cv01-cv99 */
-struct FeatureParamsCharacterVariants
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  characters.sanitize (c));
-  }
-
-  HBUINT16      format;                 /* Format number is set to 0. */
-  NameID        featUILableNameID;      /* The ‘name’ table name ID that
-                                         * specifies a string (or strings,
-                                         * for multiple languages) for a
-                                         * user-interface label for this
-                                         * feature. (May be nullptr.) */
-  NameID        featUITooltipTextNameID;/* The ‘name’ table name ID that
-                                         * specifies a string (or strings,
-                                         * for multiple languages) that an
-                                         * application can use for tooltip
-                                         * text for this feature. (May be
-                                         * nullptr.) */
-  NameID        sampleTextNameID;       /* The ‘name’ table name ID that
-                                         * specifies sample text that
-                                         * illustrates the effect of this
-                                         * feature. (May be nullptr.) */
-  HBUINT16      numNamedParameters;     /* Number of named parameters. (May
-                                         * be zero.) */
-  NameID        firstParamUILabelNameID;/* The first ‘name’ table name ID
-                                         * used to specify strings for
-                                         * user-interface labels for the
-                                         * feature parameters. (Must be zero
-                                         * if numParameters is zero.) */
-  ArrayOf<HBUINT24>
-                characters;             /* Array of the Unicode Scalar Value
-                                         * of the characters for which this
-                                         * feature provides glyph variants.
-                                         * (May be zero.) */
-  public:
-  DEFINE_SIZE_ARRAY (14, characters);
-};
-
-struct FeatureParams
-{
-  inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
-  {
-    TRACE_SANITIZE (this);
-    if (tag == HB_TAG ('s','i','z','e'))
-      return_trace (u.size.sanitize (c));
-    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
-      return_trace (u.stylisticSet.sanitize (c));
-    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
-      return_trace (u.characterVariants.sanitize (c));
-    return_trace (true);
-  }
-
-  inline const FeatureParamsSize& get_size_params (hb_tag_t tag) const
-  {
-    if (tag == HB_TAG ('s','i','z','e'))
-      return u.size;
-    return Null(FeatureParamsSize);
-  }
-
-  private:
-  union {
-  FeatureParamsSize                     size;
-  FeatureParamsStylisticSet             stylisticSet;
-  FeatureParamsCharacterVariants        characterVariants;
-  } u;
-  DEFINE_SIZE_STATIC (17);
-};
-
-struct Feature
-{
-  inline unsigned int get_lookup_count (void) const
-  { return lookupIndex.len; }
-  inline hb_tag_t get_lookup_index (unsigned int i) const
-  { return lookupIndex[i]; }
-  inline unsigned int get_lookup_indexes (unsigned int start_index,
-                                          unsigned int *lookup_count /* IN/OUT */,
-                                          unsigned int *lookup_tags /* OUT */) const
-  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
-
-  inline const FeatureParams &get_feature_params (void) const
-  { return this+featureParams; }
-
-  inline bool sanitize (hb_sanitize_context_t *c,
-                        const Record<Feature>::sanitize_closure_t *closure = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
-      return_trace (false);
-
-    /* Some earlier versions of Adobe tools calculated the offset of the
-     * FeatureParams subtable from the beginning of the FeatureList table!
-     *
-     * If sanitizing "failed" for the FeatureParams subtable, try it with the
-     * alternative location.  We would know sanitize "failed" if old value
-     * of the offset was non-zero, but it's zeroed now.
-     *
-     * Only do this for the 'size' feature, since at the time of the faulty
-     * Adobe tools, only the 'size' feature had FeatureParams defined.
-     */
-
-    OffsetTo<FeatureParams> orig_offset = featureParams;
-    if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
-      return_trace (false);
-
-    if (likely (orig_offset.is_null ()))
-      return_trace (true);
-
-    if (featureParams == 0 && closure &&
-        closure->tag == HB_TAG ('s','i','z','e') &&
-        closure->list_base && closure->list_base < this)
-    {
-      unsigned int new_offset_int = (unsigned int) orig_offset -
-                                    (((char *) this) - ((char *) closure->list_base));
-
-      OffsetTo<FeatureParams> new_offset;
-      /* Check that it did not overflow. */
-      new_offset.set (new_offset_int);
-      if (new_offset == new_offset_int &&
-          c->try_set (&featureParams, new_offset) &&
-          !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
-        return_trace (false);
-
-      if (c->edit_count > 1)
-        c->edit_count--; /* This was a "legitimate" edit; don't contribute to error count. */
-    }
-
-    return_trace (true);
-  }
-
-  OffsetTo<FeatureParams>
-                 featureParams; /* Offset to Feature Parameters table (if one
-                                 * has been defined for the feature), relative
-                                 * to the beginning of the Feature Table; = Null
-                                 * if not required */
-  IndexArray     lookupIndex;   /* Array of LookupList indices */
-  public:
-  DEFINE_SIZE_ARRAY (4, lookupIndex);
-};
-
-typedef RecordListOf<Feature> FeatureList;
-
-
-struct LookupFlag : HBUINT16
-{
-  enum Flags {
-    RightToLeft         = 0x0001u,
-    IgnoreBaseGlyphs    = 0x0002u,
-    IgnoreLigatures     = 0x0004u,
-    IgnoreMarks         = 0x0008u,
-    IgnoreFlags         = 0x000Eu,
-    UseMarkFilteringSet = 0x0010u,
-    Reserved            = 0x00E0u,
-    MarkAttachmentType  = 0xFF00u
-  };
-  public:
-  DEFINE_SIZE_STATIC (2);
-};
-
-} /* namespace OT */
-/* This has to be outside the namespace. */
-HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags);
-namespace OT {
-
-struct Lookup
-{
-  inline unsigned int get_subtable_count (void) const { return subTable.len; }
-
-  template <typename SubTableType>
-  inline const SubTableType& get_subtable (unsigned int i) const
-  { return this+CastR<OffsetArrayOf<SubTableType> > (subTable)[i]; }
-
-  template <typename SubTableType>
-  inline const OffsetArrayOf<SubTableType>& get_subtables (void) const
-  { return CastR<OffsetArrayOf<SubTableType> > (subTable); }
-  template <typename SubTableType>
-  inline OffsetArrayOf<SubTableType>& get_subtables (void)
-  { return CastR<OffsetArrayOf<SubTableType> > (subTable); }
-
-  inline unsigned int get_type (void) const { return lookupType; }
-
-  /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
-   * higher 16-bit is mark-filtering-set if the lookup uses one.
-   * Not to be confused with glyph_props which is very similar. */
-  inline uint32_t get_props (void) const
-  {
-    unsigned int flag = lookupFlag;
-    if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
-    {
-      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-      flag += (markFilteringSet << 16);
-    }
-    return flag;
-  }
-
-  template <typename SubTableType, typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    unsigned int lookup_type = get_type ();
-    TRACE_DISPATCH (this, lookup_type);
-    unsigned int count = get_subtable_count ();
-    for (unsigned int i = 0; i < count; i++) {
-      typename context_t::return_t r = get_subtable<SubTableType> (i).dispatch (c, lookup_type);
-      if (c->stop_sublookup_iteration (r))
-        return_trace (r);
-    }
-    return_trace (c->default_return_value ());
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         unsigned int lookup_type,
-                         uint32_t lookup_props,
-                         unsigned int num_subtables)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    lookupType.set (lookup_type);
-    lookupFlag.set (lookup_props & 0xFFFFu);
-    if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
-    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
-    {
-      HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-      markFilteringSet.set (lookup_props >> 16);
-    }
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    /* Real sanitize of the subtables is done by GSUB/GPOS/... */
-    if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
-    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
-    {
-      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-      if (!markFilteringSet.sanitize (c)) return_trace (false);
-    }
-    return_trace (true);
-  }
-
-  private:
-  HBUINT16      lookupType;             /* Different enumerations for GSUB and GPOS */
-  HBUINT16      lookupFlag;             /* Lookup qualifiers */
-  ArrayOf<Offset16>
-                subTable;               /* Array of SubTables */
-  HBUINT16      markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets
-                                         * structure. This field is only present if bit
-                                         * UseMarkFilteringSet of lookup flags is set. */
-  public:
-  DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX);
-};
-
-typedef OffsetListOf<Lookup> LookupList;
-
-
-/*
- * Coverage Table
- */
-
-struct CoverageFormat1
-{
-  friend struct Coverage;
-
-  private:
-  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
-  {
-    int i = glyphArray.bsearch (glyph_id);
-    static_assert ((((unsigned int) -1) == NOT_COVERED), "");
-    return i;
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    glyphArray.len.set (num_glyphs);
-    if (unlikely (!c->extend (glyphArray))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      glyphArray[i] = glyphs[i];
-    glyphs += num_glyphs;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (glyphArray.sanitize (c));
-  }
-
-  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
-    return glyphs->has (glyphArray[index]);
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    return glyphs->add_sorted_array (glyphArray.arrayZ, glyphArray.len);
-  }
-
-  public:
-  /* Older compilers need this to be public. */
-  struct Iter {
-    inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
-    inline bool more (void) { return i < c->glyphArray.len; }
-    inline void next (void) { i++; }
-    inline hb_codepoint_t get_glyph (void) { return c->glyphArray[i]; }
-    inline unsigned int get_coverage (void) { return i; }
-
-    private:
-    const struct CoverageFormat1 *c;
-    unsigned int i;
-  };
-  private:
-
-  protected:
-  HBUINT16      coverageFormat; /* Format identifier--format = 1 */
-  SortedArrayOf<GlyphID>
-                glyphArray;     /* Array of GlyphIDs--in numerical order */
-  public:
-  DEFINE_SIZE_ARRAY (4, glyphArray);
-};
-
-struct CoverageFormat2
-{
-  friend struct Coverage;
-
-  private:
-  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
-  {
-    int i = rangeRecord.bsearch (glyph_id);
-    if (i != -1) {
-      const RangeRecord &range = rangeRecord[i];
-      return (unsigned int) range.value + (glyph_id - range.start);
-    }
-    return NOT_COVERED;
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-
-    if (unlikely (!num_glyphs))
-    {
-      rangeRecord.len.set (0);
-      return_trace (true);
-    }
-
-    unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < num_glyphs; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i])
-        num_ranges++;
-    rangeRecord.len.set (num_ranges);
-    if (unlikely (!c->extend (rangeRecord))) return_trace (false);
-
-    unsigned int range = 0;
-    rangeRecord[range].start = glyphs[0];
-    rangeRecord[range].value.set (0);
-    for (unsigned int i = 1; i < num_glyphs; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i]) {
-        range++;
-        rangeRecord[range].start = glyphs[i];
-        rangeRecord[range].value.set (i);
-        rangeRecord[range].end = glyphs[i];
-      } else {
-        rangeRecord[range].end = glyphs[i];
-      }
-    glyphs += num_glyphs;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rangeRecord.sanitize (c));
-  }
-
-  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
-    unsigned int i;
-    unsigned int count = rangeRecord.len;
-    for (i = 0; i < count; i++) {
-      const RangeRecord &range = rangeRecord[i];
-      if (range.value <= index &&
-          index < (unsigned int) range.value + (range.end - range.start) &&
-          range.intersects (glyphs))
-        return true;
-      else if (index < range.value)
-        return false;
-    }
-    return false;
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
-        return false;
-    return true;
-  }
-
-  public:
-  /* Older compilers need this to be public. */
-  struct Iter
-  {
-    inline void init (const CoverageFormat2 &c_)
-    {
-      c = &c_;
-      coverage = 0;
-      i = 0;
-      j = c->rangeRecord.len ? c->rangeRecord[0].start : 0;
-      if (unlikely (c->rangeRecord[0].start > c->rangeRecord[0].end))
-      {
-        /* Broken table. Skip. */
-        i = c->rangeRecord.len;
-      }
-    }
-    inline bool more (void) { return i < c->rangeRecord.len; }
-    inline void next (void)
-    {
-      if (j >= c->rangeRecord[i].end)
-      {
-        i++;
-        if (more ())
-        {
-          hb_codepoint_t old = j;
-          j = c->rangeRecord[i].start;
-          if (unlikely (j <= old))
-          {
-            /* Broken table. Skip. Important to avoid DoS. */
-           i = c->rangeRecord.len;
-           return;
-          }
-          coverage = c->rangeRecord[i].value;
-        }
-        return;
-      }
-      coverage++;
-      j++;
-    }
-    inline hb_codepoint_t get_glyph (void) { return j; }
-    inline unsigned int get_coverage (void) { return coverage; }
-
-    private:
-    const struct CoverageFormat2 *c;
-    unsigned int i, coverage;
-    hb_codepoint_t j;
-  };
-  private:
-
-  protected:
-  HBUINT16      coverageFormat; /* Format identifier--format = 2 */
-  SortedArrayOf<RangeRecord>
-                rangeRecord;    /* Array of glyph ranges--ordered by
-                                 * Start GlyphID. rangeCount entries
-                                 * long */
-  public:
-  DEFINE_SIZE_ARRAY (4, rangeRecord);
-};
-
-struct Coverage
-{
-  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.get_coverage (glyph_id);
-    case 2: return u.format2.get_coverage (glyph_id);
-    default:return NOT_COVERED;
-    }
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < num_glyphs; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i])
-        num_ranges++;
-    u.format.set (num_glyphs * 2 < num_ranges * 3 ? 1 : 2);
-    switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs));
-    case 2: return_trace (u.format2.serialize (c, glyphs, num_glyphs));
-    default:return_trace (false);
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  inline bool intersects (const hb_set_t *glyphs) const {
-    /* TODO speed this up */
-    Coverage::Iter iter;
-    for (iter.init (*this); iter.more (); iter.next ()) {
-      if (glyphs->has (iter.get_glyph ()))
-        return true;
-    }
-    return false;
-  }
-
-  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
-    switch (u.format) {
-    case 1: return u.format1.intersects_coverage (glyphs, index);
-    case 2: return u.format2.intersects_coverage (glyphs, index);
-    default:return false;
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    switch (u.format) {
-    case 1: return u.format1.add_coverage (glyphs);
-    case 2: return u.format2.add_coverage (glyphs);
-    default:return false;
-    }
-  }
-
-  struct Iter {
-    Iter (void) : format (0), u () {};
-    inline void init (const Coverage &c_) {
-      format = c_.u.format;
-      switch (format) {
-      case 1: u.format1.init (c_.u.format1); return;
-      case 2: u.format2.init (c_.u.format2); return;
-      default:                               return;
-      }
-    }
-    inline bool more (void) {
-      switch (format) {
-      case 1: return u.format1.more ();
-      case 2: return u.format2.more ();
-      default:return false;
-      }
-    }
-    inline void next (void) {
-      switch (format) {
-      case 1: u.format1.next (); break;
-      case 2: u.format2.next (); break;
-      default:                   break;
-      }
-    }
-    inline hb_codepoint_t get_glyph (void) {
-      switch (format) {
-      case 1: return u.format1.get_glyph ();
-      case 2: return u.format2.get_glyph ();
-      default:return 0;
-      }
-    }
-    inline unsigned int get_coverage (void) {
-      switch (format) {
-      case 1: return u.format1.get_coverage ();
-      case 2: return u.format2.get_coverage ();
-      default:return -1;
-      }
-    }
-
-    private:
-    unsigned int format;
-    union {
-    CoverageFormat2::Iter       format2; /* Put this one first since it's larger; helps shut up compiler. */
-    CoverageFormat1::Iter       format1;
-    } u;
-  };
-
-  protected:
-  union {
-  HBUINT16              format;         /* Format identifier */
-  CoverageFormat1       format1;
-  CoverageFormat2       format2;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-
-/*
- * Class Definition Table
- */
-
-struct ClassDefFormat1
-{
-  friend struct ClassDef;
-
-  private:
-  inline unsigned int get_class (hb_codepoint_t glyph_id) const
-  {
-    unsigned int i = (unsigned int) (glyph_id - startGlyph);
-    if (unlikely (i < classValue.len))
-      return classValue[i];
-    return 0;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && classValue.sanitize (c));
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    unsigned int start = 0;
-    unsigned int count = classValue.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (classValue[i])
-        continue;
-
-      if (start != i)
-        if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + i)))
-          return false;
-
-      start = i + 1;
-    }
-    if (start != count)
-      if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + count)))
-        return false;
-
-    return true;
-  }
-
-  template <typename set_t>
-  inline bool add_class (set_t *glyphs, unsigned int klass) const {
-    unsigned int count = classValue.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (classValue[i] == klass)
-        glyphs->add (startGlyph + i);
-    }
-    return true;
-  }
-
-  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
-    unsigned int count = classValue.len;
-    if (klass == 0)
-    {
-      /* Match if there's any glyph that is not listed! */
-      hb_codepoint_t g = HB_SET_VALUE_INVALID;
-      if (!hb_set_next (glyphs, &g))
-        return false;
-      if (g < startGlyph)
-        return true;
-      g = startGlyph + count - 1;
-      if (hb_set_next (glyphs, &g))
-        return true;
-      /* Fall through. */
-    }
-    for (unsigned int i = 0; i < count; i++)
-      if (classValue[i] == klass && glyphs->has (startGlyph + i))
-        return true;
-    return false;
-  }
-
-  protected:
-  HBUINT16      classFormat;            /* Format identifier--format = 1 */
-  GlyphID       startGlyph;             /* First GlyphID of the classValueArray */
-  ArrayOf<HBUINT16>
-                classValue;             /* Array of Class Values--one per GlyphID */
-  public:
-  DEFINE_SIZE_ARRAY (6, classValue);
-};
-
-struct ClassDefFormat2
-{
-  friend struct ClassDef;
-
-  private:
-  inline unsigned int get_class (hb_codepoint_t glyph_id) const
-  {
-    int i = rangeRecord.bsearch (glyph_id);
-    if (unlikely (i != -1))
-      return rangeRecord[i].value;
-    return 0;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rangeRecord.sanitize (c));
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (rangeRecord[i].value)
-        if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
-          return false;
-    return true;
-  }
-
-  template <typename set_t>
-  inline bool add_class (set_t *glyphs, unsigned int klass) const {
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (rangeRecord[i].value == klass)
-        if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
-          return false;
-    }
-    return true;
-  }
-
-  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
-    unsigned int count = rangeRecord.len;
-    if (klass == 0)
-    {
-      /* Match if there's any glyph that is not listed! */
-      hb_codepoint_t g = HB_SET_VALUE_INVALID;
-      for (unsigned int i = 0; i < count; i++)
-      {
-        if (!hb_set_next (glyphs, &g))
-          break;
-        if (g < rangeRecord[i].start)
-          return true;
-        g = rangeRecord[i].end;
-      }
-      if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
-        return true;
-      /* Fall through. */
-    }
-    for (unsigned int i = 0; i < count; i++)
-      if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
-        return true;
-    return false;
-  }
-
-  protected:
-  HBUINT16      classFormat;    /* Format identifier--format = 2 */
-  SortedArrayOf<RangeRecord>
-                rangeRecord;    /* Array of glyph ranges--ordered by
-                                 * Start GlyphID */
-  public:
-  DEFINE_SIZE_ARRAY (4, rangeRecord);
-};
-
-struct ClassDef
-{
-  inline unsigned int get_class (hb_codepoint_t glyph_id) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.get_class (glyph_id);
-    case 2: return u.format2.get_class (glyph_id);
-    default:return 0;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    switch (u.format) {
-    case 1: return u.format1.add_coverage (glyphs);
-    case 2: return u.format2.add_coverage (glyphs);
-    default:return false;
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename set_t>
-  inline bool add_class (set_t *glyphs, unsigned int klass) const {
-    switch (u.format) {
-    case 1: return u.format1.add_class (glyphs, klass);
-    case 2: return u.format2.add_class (glyphs, klass);
-    default:return false;
-    }
-  }
-
-  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
-    switch (u.format) {
-    case 1: return u.format1.intersects_class (glyphs, klass);
-    case 2: return u.format2.intersects_class (glyphs, klass);
-    default:return false;
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16              format;         /* Format identifier */
-  ClassDefFormat1       format1;
-  ClassDefFormat2       format2;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-
-/*
- * Item Variation Store
- */
-
-struct VarRegionAxis
-{
-  inline float evaluate (int coord) const
-  {
-    int start = startCoord, peak = peakCoord, end = endCoord;
-
-    /* TODO Move these to sanitize(). */
-    if (unlikely (start > peak || peak > end))
-      return 1.;
-    if (unlikely (start < 0 && end > 0 && peak != 0))
-      return 1.;
-
-    if (peak == 0 || coord == peak)
-      return 1.;
-
-    if (coord <= start || end <= coord)
-      return 0.;
-
-    /* Interpolate */
-    if (coord < peak)
-      return float (coord - start) / (peak - start);
-    else
-      return float (end - coord) / (end - peak);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-    /* TODO Handle invalid start/peak/end configs, so we don't
-     * have to do that at runtime. */
-  }
-
-  public:
-  F2DOT14       startCoord;
-  F2DOT14       peakCoord;
-  F2DOT14       endCoord;
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct VarRegionList
-{
-  inline float evaluate (unsigned int region_index,
-                         int *coords, unsigned int coord_len) const
-  {
-    if (unlikely (region_index >= regionCount))
-      return 0.;
-
-    const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
-
-    float v = 1.;
-    unsigned int count = axisCount;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      int coord = i < coord_len ? coords[i] : 0;
-      float factor = axes[i].evaluate (coord);
-      if (factor == 0.f)
-        return 0.;
-      v *= factor;
-    }
-    return v;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  axesZ.sanitize (c, (unsigned int) axisCount * (unsigned int) regionCount));
-  }
-
-  protected:
-  HBUINT16      axisCount;
-  HBUINT16      regionCount;
-  UnsizedArrayOf<VarRegionAxis>
-                axesZ;
-  public:
-  DEFINE_SIZE_ARRAY (4, axesZ);
-};
-
-struct VarData
-{
-  inline unsigned int get_row_size (void) const
-  { return shortCount + regionIndices.len; }
-
-  inline unsigned int get_size (void) const
-  { return itemCount * get_row_size (); }
-
-  inline float get_delta (unsigned int inner,
-                          int *coords, unsigned int coord_count,
-                          const VarRegionList &regions) const
-  {
-    if (unlikely (inner >= itemCount))
-      return 0.;
-
-   unsigned int count = regionIndices.len;
-   unsigned int scount = shortCount;
-
-   const HBUINT8 *bytes = &StructAfter<HBUINT8> (regionIndices);
-   const HBUINT8 *row = bytes + inner * (scount + count);
-
-   float delta = 0.;
-   unsigned int i = 0;
-
-   const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row);
-   for (; i < scount; i++)
-   {
-     float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
-     delta += scalar * *scursor++;
-   }
-   const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
-   for (; i < count; i++)
-   {
-     float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
-     delta += scalar * *bcursor++;
-   }
-
-   return delta;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  regionIndices.sanitize(c) &&
-                  shortCount <= regionIndices.len &&
-                  c->check_array (&StructAfter<HBUINT8> (regionIndices),
-                                  get_row_size (), itemCount));
-  }
-
-  protected:
-  HBUINT16              itemCount;
-  HBUINT16              shortCount;
-  ArrayOf<HBUINT16>     regionIndices;
-  HBUINT8               bytesX[VAR];
-  public:
-  DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX);
-};
-
-struct VariationStore
-{
-  inline float get_delta (unsigned int outer, unsigned int inner,
-                          int *coords, unsigned int coord_count) const
-  {
-    if (unlikely (outer >= dataSets.len))
-      return 0.;
-
-    return (this+dataSets[outer]).get_delta (inner,
-                                             coords, coord_count,
-                                             this+regions);
-  }
-
-  inline float get_delta (unsigned int index,
-                          int *coords, unsigned int coord_count) const
-  {
-    unsigned int outer = index >> 16;
-    unsigned int inner = index & 0xFFFF;
-    return get_delta (outer, inner, coords, coord_count);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  format == 1 &&
-                  regions.sanitize (c, this) &&
-                  dataSets.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16                              format;
-  LOffsetTo<VarRegionList>              regions;
-  OffsetArrayOf<VarData, HBUINT32>      dataSets;
-  public:
-  DEFINE_SIZE_ARRAY (8, dataSets);
-};
-
-/*
- * Feature Variations
- */
-
-struct ConditionFormat1
-{
-  friend struct Condition;
-
-  private:
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
-    return filterRangeMinValue <= coord && coord <= filterRangeMaxValue;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  HBUINT16      format;         /* Format identifier--format = 1 */
-  HBUINT16      axisIndex;
-  F2DOT14       filterRangeMinValue;
-  F2DOT14       filterRangeMaxValue;
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct Condition
-{
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.evaluate (coords, coord_len);
-    default:return false;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16              format;         /* Format identifier */
-  ConditionFormat1      format1;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-struct ConditionSet
-{
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    unsigned int count = conditions.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len))
-        return false;
-    return true;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (conditions.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<Condition, HBUINT32> conditions;
-  public:
-  DEFINE_SIZE_ARRAY (2, conditions);
-};
-
-struct FeatureTableSubstitutionRecord
-{
-  friend struct FeatureTableSubstitution;
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && feature.sanitize (c, base));
-  }
-
-  protected:
-  HBUINT16              featureIndex;
-  LOffsetTo<Feature>    feature;
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct FeatureTableSubstitution
-{
-  inline const Feature *find_substitute (unsigned int feature_index) const
-  {
-    unsigned int count = substitutions.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      const FeatureTableSubstitutionRecord &record = substitutions.arrayZ[i];
-      if (record.featureIndex == feature_index)
-        return &(this+record.feature);
-    }
-    return nullptr;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-                  likely (version.major == 1) &&
-                  substitutions.sanitize (c, this));
-  }
-
-  protected:
-  FixedVersion<>        version;        /* Version--0x00010000u */
-  ArrayOf<FeatureTableSubstitutionRecord>
-                        substitutions;
-  public:
-  DEFINE_SIZE_ARRAY (6, substitutions);
-};
-
-struct FeatureVariationRecord
-{
-  friend struct FeatureVariations;
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (conditions.sanitize (c, base) &&
-                  substitutions.sanitize (c, base));
-  }
-
-  protected:
-  LOffsetTo<ConditionSet>
-                        conditions;
-  LOffsetTo<FeatureTableSubstitution>
-                        substitutions;
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct FeatureVariations
-{
-  static const unsigned int NOT_FOUND_INDEX = 0xFFFFFFFFu;
-
-  inline bool find_index (const int *coords, unsigned int coord_len,
-                          unsigned int *index) const
-  {
-    unsigned int count = varRecords.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      const FeatureVariationRecord &record = varRecords.arrayZ[i];
-      if ((this+record.conditions).evaluate (coords, coord_len))
-      {
-        *index = i;
-        return true;
-      }
-    }
-    *index = NOT_FOUND_INDEX;
-    return false;
-  }
-
-  inline const Feature *find_substitute (unsigned int variations_index,
-                                         unsigned int feature_index) const
-  {
-    const FeatureVariationRecord &record = varRecords[variations_index];
-    return (this+record.substitutions).find_substitute (feature_index);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-                  likely (version.major == 1) &&
-                  varRecords.sanitize (c, this));
-  }
-
-  protected:
-  FixedVersion<>        version;        /* Version--0x00010000u */
-  LArrayOf<FeatureVariationRecord>
-                        varRecords;
-  public:
-  DEFINE_SIZE_ARRAY (8, varRecords);
-};
-
-
-/*
- * Device Tables
- */
-
-struct HintingDevice
-{
-  friend struct Device;
-
-  private:
-
-  inline hb_position_t get_x_delta (hb_font_t *font) const
-  { return get_delta (font->x_ppem, font->x_scale); }
-
-  inline hb_position_t get_y_delta (hb_font_t *font) const
-  { return get_delta (font->y_ppem, font->y_scale); }
-
-  inline unsigned int get_size (void) const
-  {
-    unsigned int f = deltaFormat;
-    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * HBUINT16::static_size;
-    return HBUINT16::static_size * (4 + ((endSize - startSize) >> (4 - f)));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
-  }
-
-  private:
-
-  inline int get_delta (unsigned int ppem, int scale) const
-  {
-    if (!ppem) return 0;
-
-    int pixels = get_delta_pixels (ppem);
-
-    if (!pixels) return 0;
-
-    return (int) (pixels * (int64_t) scale / ppem);
-  }
-  inline int get_delta_pixels (unsigned int ppem_size) const
-  {
-    unsigned int f = deltaFormat;
-    if (unlikely (f < 1 || f > 3))
-      return 0;
-
-    if (ppem_size < startSize || ppem_size > endSize)
-      return 0;
-
-    unsigned int s = ppem_size - startSize;
-
-    unsigned int byte = deltaValue[s >> (4 - f)];
-    unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
-    unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
-
-    int delta = bits & mask;
-
-    if ((unsigned int) delta >= ((mask + 1) >> 1))
-      delta -= mask + 1;
-
-    return delta;
-  }
-
-  protected:
-  HBUINT16      startSize;              /* Smallest size to correct--in ppem */
-  HBUINT16      endSize;                /* Largest size to correct--in ppem */
-  HBUINT16      deltaFormat;            /* Format of DeltaValue array data: 1, 2, or 3
-                                         * 1    Signed 2-bit value, 8 values per uint16
-                                         * 2    Signed 4-bit value, 4 values per uint16
-                                         * 3    Signed 8-bit value, 2 values per uint16
-                                         */
-  HBUINT16      deltaValue[VAR];        /* Array of compressed data */
-  public:
-  DEFINE_SIZE_ARRAY (6, deltaValue);
-};
-
-struct VariationDevice
-{
-  friend struct Device;
-
-  private:
-
-  inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const
-  { return font->em_scalef_x (get_delta (font, store)); }
-
-  inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
-  { return font->em_scalef_y (get_delta (font, store)); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  private:
-
-  inline float get_delta (hb_font_t *font, const VariationStore &store) const
-  {
-    return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords);
-  }
-
-  protected:
-  HBUINT16      outerIndex;
-  HBUINT16      innerIndex;
-  HBUINT16      deltaFormat;    /* Format identifier for this table: 0x0x8000 */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct DeviceHeader
-{
-  protected:
-  HBUINT16              reserved1;
-  HBUINT16              reserved2;
-  public:
-  HBUINT16              format;         /* Format identifier */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct Device
-{
-  inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const
-  {
-    switch (u.b.format)
-    {
-    case 1: case 2: case 3:
-      return u.hinting.get_x_delta (font);
-    case 0x8000:
-      return u.variation.get_x_delta (font, store);
-    default:
-      return 0;
-    }
-  }
-  inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const
-  {
-    switch (u.b.format)
-    {
-    case 1: case 2: case 3:
-      return u.hinting.get_y_delta (font);
-    case 0x8000:
-      return u.variation.get_y_delta (font, store);
-    default:
-      return 0;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.b.format.sanitize (c)) return_trace (false);
-    switch (u.b.format) {
-    case 1: case 2: case 3:
-      return_trace (u.hinting.sanitize (c));
-    case 0x8000:
-      return_trace (u.variation.sanitize (c));
-    default:
-      return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  DeviceHeader          b;
-  HintingDevice         hinting;
-  VariationDevice       variation;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (6, b);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-common.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,2178 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2010,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): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_LAYOUT_COMMON_HH
+#define HB_OT_LAYOUT_COMMON_HH
+
+#include "hb.hh"
+#include "hb-ot-layout.hh"
+#include "hb-open-type.hh"
+#include "hb-set.hh"
+
+
+#ifndef HB_MAX_NESTING_LEVEL
+#define HB_MAX_NESTING_LEVEL    6
+#endif
+#ifndef HB_MAX_CONTEXT_LENGTH
+#define HB_MAX_CONTEXT_LENGTH   64
+#endif
+#ifndef HB_CLOSURE_MAX_STAGES
+/*
+ * The maximum number of times a lookup can be applied during shaping.
+ * Used to limit the number of iterations of the closure algorithm.
+ * This must be larger than the number of times add_pause() is
+ * called in a collect_features call of any shaper.
+ */
+#define HB_CLOSURE_MAX_STAGES   32
+#endif
+
+#ifndef HB_MAX_SCRIPTS
+#define HB_MAX_SCRIPTS  500
+#endif
+
+#ifndef HB_MAX_LANGSYS
+#define HB_MAX_LANGSYS  2000
+#endif
+
+
+namespace OT {
+
+
+#define NOT_COVERED             ((unsigned int) -1)
+
+
+
+/*
+ *
+ * OpenType Layout Common Table Formats
+ *
+ */
+
+
+/*
+ * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
+ */
+
+struct Record_sanitize_closure_t {
+  hb_tag_t tag;
+  const void *list_base;
+};
+
+template <typename Type>
+struct Record
+{
+  int cmp (hb_tag_t a) const { return tag.cmp (a); }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    const Record_sanitize_closure_t closure = {tag, base};
+    return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
+  }
+
+  Tag           tag;            /* 4-byte Tag identifier */
+  OffsetTo<Type>
+                offset;         /* Offset from beginning of object holding
+                                 * the Record */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+template <typename Type>
+struct RecordArrayOf : SortedArrayOf<Record<Type> >
+{
+  const OffsetTo<Type>& get_offset (unsigned int i) const
+  { return (*this)[i].offset; }
+  OffsetTo<Type>& get_offset (unsigned int i)
+  { return (*this)[i].offset; }
+  const Tag& get_tag (unsigned int i) const
+  { return (*this)[i].tag; }
+  unsigned int get_tags (unsigned int start_offset,
+                         unsigned int *record_count /* IN/OUT */,
+                         hb_tag_t     *record_tags /* OUT */) const
+  {
+    if (record_count) {
+      const Record<Type> *arr = this->sub_array (start_offset, record_count);
+      unsigned int count = *record_count;
+      for (unsigned int i = 0; i < count; i++)
+        record_tags[i] = arr[i].tag;
+    }
+    return this->len;
+  }
+  bool find_index (hb_tag_t tag, unsigned int *index) const
+  {
+    return this->bfind (tag, index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
+  }
+};
+
+template <typename Type>
+struct RecordListOf : RecordArrayOf<Type>
+{
+  const Type& operator [] (unsigned int i) const
+  { return this+this->get_offset (i); }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct RecordListOf<Type> *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    unsigned int count = this->len;
+    for (unsigned int i = 0; i < count; i++)
+      out->get_offset (i).serialize_subset (c, (*this)[i], out);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (RecordArrayOf<Type>::sanitize (c, this));
+  }
+};
+
+
+struct RangeRecord
+{
+  int cmp (hb_codepoint_t g) const
+  { return g < start ? -1 : g <= end ? 0 : +1; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  { return glyphs->intersects (start, end); }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  { return glyphs->add_range (start, end); }
+
+  GlyphID       start;          /* First GlyphID in the range */
+  GlyphID       end;            /* Last GlyphID in the range */
+  HBUINT16      value;          /* Value */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
+
+
+struct IndexArray : ArrayOf<Index>
+{
+  unsigned int get_indexes (unsigned int start_offset,
+                            unsigned int *_count /* IN/OUT */,
+                            unsigned int *_indexes /* OUT */) const
+  {
+    if (_count) {
+      const HBUINT16 *arr = this->sub_array (start_offset, _count);
+      unsigned int count = *_count;
+      for (unsigned int i = 0; i < count; i++)
+        _indexes[i] = arr[i];
+    }
+    return this->len;
+  }
+
+  void add_indexes_to (hb_set_t* output /* OUT */) const
+  {
+    output->add_array (arrayZ, len);
+  }
+};
+
+
+struct Script;
+struct LangSys;
+struct Feature;
+
+
+struct LangSys
+{
+  unsigned int get_feature_count () const
+  { return featureIndex.len; }
+  hb_tag_t get_feature_index (unsigned int i) const
+  { return featureIndex[i]; }
+  unsigned int get_feature_indexes (unsigned int start_offset,
+                                    unsigned int *feature_count /* IN/OUT */,
+                                    unsigned int *feature_indexes /* OUT */) const
+  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
+  void add_feature_indexes_to (hb_set_t *feature_indexes) const
+  { featureIndex.add_indexes_to (feature_indexes); }
+
+  bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
+  unsigned int get_required_feature_index () const
+  {
+    if (reqFeatureIndex == 0xFFFFu)
+      return Index::NOT_FOUND_INDEX;
+   return reqFeatureIndex;;
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    return_trace (c->serializer->embed (*this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                 const Record_sanitize_closure_t * = nullptr) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && featureIndex.sanitize (c));
+  }
+
+  Offset16      lookupOrderZ;   /* = Null (reserved for an offset to a
+                                 * reordering table) */
+  HBUINT16      reqFeatureIndex;/* Index of a feature required for this
+                                 * language system--if no required features
+                                 * = 0xFFFFu */
+  IndexArray    featureIndex;   /* Array of indices into the FeatureList */
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (6, featureIndex);
+};
+DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
+
+struct Script
+{
+  unsigned int get_lang_sys_count () const
+  { return langSys.len; }
+  const Tag& get_lang_sys_tag (unsigned int i) const
+  { return langSys.get_tag (i); }
+  unsigned int get_lang_sys_tags (unsigned int start_offset,
+                                  unsigned int *lang_sys_count /* IN/OUT */,
+                                  hb_tag_t     *lang_sys_tags /* OUT */) const
+  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
+  const LangSys& get_lang_sys (unsigned int i) const
+  {
+    if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
+    return this+langSys[i].offset;
+  }
+  bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
+  { return langSys.find_index (tag, index); }
+
+  bool has_default_lang_sys () const           { return defaultLangSys != 0; }
+  const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct Script *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    out->defaultLangSys.serialize_subset (c, this+defaultLangSys, out);
+    unsigned int count = langSys.len;
+    for (unsigned int i = 0; i < count; i++)
+      out->langSys.arrayZ[i].offset.serialize_subset (c, this+langSys[i].offset, out);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                 const Record_sanitize_closure_t * = nullptr) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
+  }
+
+  protected:
+  OffsetTo<LangSys>
+                defaultLangSys; /* Offset to DefaultLangSys table--from
+                                 * beginning of Script table--may be Null */
+  RecordArrayOf<LangSys>
+                langSys;        /* Array of LangSysRecords--listed
+                                 * alphabetically by LangSysTag */
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (4, langSys);
+};
+
+typedef RecordListOf<Script> ScriptList;
+
+
+/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
+struct FeatureParamsSize
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this))) return_trace (false);
+
+    /* This subtable has some "history", if you will.  Some earlier versions of
+     * Adobe tools calculated the offset of the FeatureParams sutable from the
+     * beginning of the FeatureList table!  Now, that is dealt with in the
+     * Feature implementation.  But we still need to be able to tell junk from
+     * real data.  Note: We don't check that the nameID actually exists.
+     *
+     * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
+     *
+     * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
+     * coming out soon, and that the makeotf program will build a font with a
+     * 'size' feature that is correct by the specification.
+     *
+     * The specification for this feature tag is in the "OpenType Layout Tag
+     * Registry". You can see a copy of this at:
+     * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size
+     *
+     * Here is one set of rules to determine if the 'size' feature is built
+     * correctly, or as by the older versions of MakeOTF. You may be able to do
+     * better.
+     *
+     * Assume that the offset to the size feature is according to specification,
+     * and make the following value checks. If it fails, assume the size
+     * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
+     * If this fails, reject the 'size' feature. The older makeOTF's calculated the
+     * offset from the beginning of the FeatureList table, rather than from the
+     * beginning of the 'size' Feature table.
+     *
+     * If "design size" == 0:
+     *     fails check
+     *
+     * Else if ("subfamily identifier" == 0 and
+     *     "range start" == 0 and
+     *     "range end" == 0 and
+     *     "range start" == 0 and
+     *     "menu name ID" == 0)
+     *     passes check: this is the format used when there is a design size
+     * specified, but there is no recommended size range.
+     *
+     * Else if ("design size" <  "range start" or
+     *     "design size" >   "range end" or
+     *     "range end" <= "range start" or
+     *     "menu name ID"  < 256 or
+     *     "menu name ID"  > 32767 or
+     *     menu name ID is not a name ID which is actually in the name table)
+     *     fails test
+     * Else
+     *     passes test.
+     */
+
+    if (!designSize)
+      return_trace (false);
+    else if (subfamilyID == 0 &&
+             subfamilyNameID == 0 &&
+             rangeStart == 0 &&
+             rangeEnd == 0)
+      return_trace (true);
+    else if (designSize < rangeStart ||
+             designSize > rangeEnd ||
+             subfamilyNameID < 256 ||
+             subfamilyNameID > 32767)
+      return_trace (false);
+    else
+      return_trace (true);
+  }
+
+  HBUINT16      designSize;     /* Represents the design size in 720/inch
+                                 * units (decipoints).  The design size entry
+                                 * must be non-zero.  When there is a design
+                                 * size but no recommended size range, the
+                                 * rest of the array will consist of zeros. */
+  HBUINT16      subfamilyID;    /* Has no independent meaning, but serves
+                                 * as an identifier that associates fonts
+                                 * in a subfamily. All fonts which share a
+                                 * Preferred or Font Family name and which
+                                 * differ only by size range shall have the
+                                 * same subfamily value, and no fonts which
+                                 * differ in weight or style shall have the
+                                 * same subfamily value. If this value is
+                                 * zero, the remaining fields in the array
+                                 * will be ignored. */
+  NameID        subfamilyNameID;/* If the preceding value is non-zero, this
+                                 * value must be set in the range 256 - 32767
+                                 * (inclusive). It records the value of a
+                                 * field in the name table, which must
+                                 * contain English-language strings encoded
+                                 * in Windows Unicode and Macintosh Roman,
+                                 * and may contain additional strings
+                                 * localized to other scripts and languages.
+                                 * Each of these strings is the name an
+                                 * application should use, in combination
+                                 * with the family name, to represent the
+                                 * subfamily in a menu.  Applications will
+                                 * choose the appropriate version based on
+                                 * their selection criteria. */
+  HBUINT16      rangeStart;     /* Large end of the recommended usage range
+                                 * (inclusive), stored in 720/inch units
+                                 * (decipoints). */
+  HBUINT16      rangeEnd;       /* Small end of the recommended usage range
+                                   (exclusive), stored in 720/inch units
+                                 * (decipoints). */
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#ssxx */
+struct FeatureParamsStylisticSet
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    /* Right now minorVersion is at zero.  Which means, any table supports
+     * the uiNameID field. */
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT16      version;        /* (set to 0): This corresponds to a “minor”
+                                 * version number. Additional data may be
+                                 * added to the end of this Feature Parameters
+                                 * table in the future. */
+
+  NameID        uiNameID;       /* The 'name' table name ID that specifies a
+                                 * string (or strings, for multiple languages)
+                                 * for a user-interface label for this
+                                 * feature.  The values of uiLabelNameId and
+                                 * sampleTextNameId are expected to be in the
+                                 * font-specific name ID range (256-32767),
+                                 * though that is not a requirement in this
+                                 * Feature Parameters specification. The
+                                 * user-interface label for the feature can
+                                 * be provided in multiple languages. An
+                                 * English string should be included as a
+                                 * fallback. The string should be kept to a
+                                 * minimal length to fit comfortably with
+                                 * different application interfaces. */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#cv01-cv99 */
+struct FeatureParamsCharacterVariants
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  characters.sanitize (c));
+  }
+
+  HBUINT16      format;                 /* Format number is set to 0. */
+  NameID        featUILableNameID;      /* The ‘name’ table name ID that
+                                         * specifies a string (or strings,
+                                         * for multiple languages) for a
+                                         * user-interface label for this
+                                         * feature. (May be NULL.) */
+  NameID        featUITooltipTextNameID;/* The ‘name’ table name ID that
+                                         * specifies a string (or strings,
+                                         * for multiple languages) that an
+                                         * application can use for tooltip
+                                         * text for this feature. (May be
+                                         * nullptr.) */
+  NameID        sampleTextNameID;       /* The ‘name’ table name ID that
+                                         * specifies sample text that
+                                         * illustrates the effect of this
+                                         * feature. (May be NULL.) */
+  HBUINT16      numNamedParameters;     /* Number of named parameters. (May
+                                         * be zero.) */
+  NameID        firstParamUILabelNameID;/* The first ‘name’ table name ID
+                                         * used to specify strings for
+                                         * user-interface labels for the
+                                         * feature parameters. (Must be zero
+                                         * if numParameters is zero.) */
+  ArrayOf<HBUINT24>
+                characters;             /* Array of the Unicode Scalar Value
+                                         * of the characters for which this
+                                         * feature provides glyph variants.
+                                         * (May be zero.) */
+  public:
+  DEFINE_SIZE_ARRAY (14, characters);
+};
+
+struct FeatureParams
+{
+  bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
+  {
+    TRACE_SANITIZE (this);
+    if (tag == HB_TAG ('s','i','z','e'))
+      return_trace (u.size.sanitize (c));
+    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
+      return_trace (u.stylisticSet.sanitize (c));
+    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
+      return_trace (u.characterVariants.sanitize (c));
+    return_trace (true);
+  }
+
+  const FeatureParamsSize& get_size_params (hb_tag_t tag) const
+  {
+    if (tag == HB_TAG ('s','i','z','e'))
+      return u.size;
+    return Null (FeatureParamsSize);
+  }
+
+  const FeatureParamsStylisticSet& get_stylistic_set_params (hb_tag_t tag) const
+  {
+    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
+      return u.stylisticSet;
+    return Null (FeatureParamsStylisticSet);
+  }
+
+  const FeatureParamsCharacterVariants& get_character_variants_params (hb_tag_t tag) const
+  {
+    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
+      return u.characterVariants;
+    return Null (FeatureParamsCharacterVariants);
+  }
+
+  private:
+  union {
+  FeatureParamsSize                     size;
+  FeatureParamsStylisticSet             stylisticSet;
+  FeatureParamsCharacterVariants        characterVariants;
+  } u;
+  public:
+  DEFINE_SIZE_STATIC (17);
+};
+
+struct Feature
+{
+  unsigned int get_lookup_count () const
+  { return lookupIndex.len; }
+  hb_tag_t get_lookup_index (unsigned int i) const
+  { return lookupIndex[i]; }
+  unsigned int get_lookup_indexes (unsigned int start_index,
+                                   unsigned int *lookup_count /* IN/OUT */,
+                                   unsigned int *lookup_tags /* OUT */) const
+  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
+  void add_lookup_indexes_to (hb_set_t *lookup_indexes) const
+  { lookupIndex.add_indexes_to (lookup_indexes); }
+
+  const FeatureParams &get_feature_params () const
+  { return this+featureParams; }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct Feature *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    out->featureParams.set (0); /* TODO(subset) FeatureParams. */
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                 const Record_sanitize_closure_t *closure = nullptr) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
+      return_trace (false);
+
+    /* Some earlier versions of Adobe tools calculated the offset of the
+     * FeatureParams subtable from the beginning of the FeatureList table!
+     *
+     * If sanitizing "failed" for the FeatureParams subtable, try it with the
+     * alternative location.  We would know sanitize "failed" if old value
+     * of the offset was non-zero, but it's zeroed now.
+     *
+     * Only do this for the 'size' feature, since at the time of the faulty
+     * Adobe tools, only the 'size' feature had FeatureParams defined.
+     */
+
+    OffsetTo<FeatureParams> orig_offset = featureParams;
+    if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
+      return_trace (false);
+
+    if (likely (orig_offset.is_null ()))
+      return_trace (true);
+
+    if (featureParams == 0 && closure &&
+        closure->tag == HB_TAG ('s','i','z','e') &&
+        closure->list_base && closure->list_base < this)
+    {
+      unsigned int new_offset_int = (unsigned int) orig_offset -
+                                    (((char *) this) - ((char *) closure->list_base));
+
+      OffsetTo<FeatureParams> new_offset;
+      /* Check that it did not overflow. */
+      new_offset.set (new_offset_int);
+      if (new_offset == new_offset_int &&
+          c->try_set (&featureParams, new_offset) &&
+          !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
+        return_trace (false);
+    }
+
+    return_trace (true);
+  }
+
+  OffsetTo<FeatureParams>
+                 featureParams; /* Offset to Feature Parameters table (if one
+                                 * has been defined for the feature), relative
+                                 * to the beginning of the Feature Table; = Null
+                                 * if not required */
+  IndexArray     lookupIndex;   /* Array of LookupList indices */
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
+};
+
+typedef RecordListOf<Feature> FeatureList;
+
+
+struct LookupFlag : HBUINT16
+{
+  enum Flags {
+    RightToLeft         = 0x0001u,
+    IgnoreBaseGlyphs    = 0x0002u,
+    IgnoreLigatures     = 0x0004u,
+    IgnoreMarks         = 0x0008u,
+    IgnoreFlags         = 0x000Eu,
+    UseMarkFilteringSet = 0x0010u,
+    Reserved            = 0x00E0u,
+    MarkAttachmentType  = 0xFF00u
+  };
+  public:
+  DEFINE_SIZE_STATIC (2);
+};
+
+} /* namespace OT */
+/* This has to be outside the namespace. */
+HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags);
+namespace OT {
+
+struct Lookup
+{
+  unsigned int get_subtable_count () const { return subTable.len; }
+
+  template <typename TSubTable>
+  const TSubTable& get_subtable (unsigned int i) const
+  { return this+CastR<OffsetArrayOf<TSubTable> > (subTable)[i]; }
+
+  template <typename TSubTable>
+  const OffsetArrayOf<TSubTable>& get_subtables () const
+  { return CastR<OffsetArrayOf<TSubTable> > (subTable); }
+  template <typename TSubTable>
+  OffsetArrayOf<TSubTable>& get_subtables ()
+  { return CastR<OffsetArrayOf<TSubTable> > (subTable); }
+
+  unsigned int get_size () const
+  {
+    const HBUINT16 &markFilteringSet = StructAfter<const HBUINT16> (subTable);
+    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
+      return (const char *) &StructAfter<const char> (markFilteringSet) - (const char *) this;
+    return (const char *) &markFilteringSet - (const char *) this;
+  }
+
+  unsigned int get_type () const { return lookupType; }
+
+  /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
+   * higher 16-bit is mark-filtering-set if the lookup uses one.
+   * Not to be confused with glyph_props which is very similar. */
+  uint32_t get_props () const
+  {
+    unsigned int flag = lookupFlag;
+    if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
+    {
+      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
+      flag += (markFilteringSet << 16);
+    }
+    return flag;
+  }
+
+  template <typename TSubTable, typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    unsigned int lookup_type = get_type ();
+    TRACE_DISPATCH (this, lookup_type);
+    unsigned int count = get_subtable_count ();
+    for (unsigned int i = 0; i < count; i++) {
+      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type);
+      if (c->stop_sublookup_iteration (r))
+        return_trace (r);
+    }
+    return_trace (c->default_return_value ());
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  unsigned int lookup_type,
+                  uint32_t lookup_props,
+                  unsigned int num_subtables)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    lookupType.set (lookup_type);
+    lookupFlag.set (lookup_props & 0xFFFFu);
+    if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
+    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
+    {
+      if (unlikely (!c->extend (*this))) return_trace (false);
+      HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
+      markFilteringSet.set (lookup_props >> 16);
+    }
+    return_trace (true);
+  }
+
+  /* Older compilers need this to NOT be locally defined in a function. */
+  template <typename TSubTable>
+  struct SubTableSubsetWrapper
+  {
+    SubTableSubsetWrapper (const TSubTable &subtable_,
+                           unsigned int lookup_type_) :
+                             subtable (subtable_),
+                             lookup_type (lookup_type_) {}
+
+    bool subset (hb_subset_context_t *c) const
+    { return subtable.dispatch (c, lookup_type); }
+
+    private:
+    const TSubTable &subtable;
+    unsigned int lookup_type;
+  };
+
+  template <typename TSubTable>
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct Lookup *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+
+    /* Subset the actual subtables. */
+    /* TODO Drop empty ones, either by calling intersects() beforehand,
+     * or just dropping null offsets after. */
+    const OffsetArrayOf<TSubTable>& subtables = get_subtables<TSubTable> ();
+    OffsetArrayOf<TSubTable>& out_subtables = out->get_subtables<TSubTable> ();
+    unsigned int count = subTable.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      SubTableSubsetWrapper<TSubTable> wrapper (this+subtables[i], get_type ());
+
+      out_subtables[i].serialize_subset (c, wrapper, out);
+    }
+
+    return_trace (true);
+  }
+
+  /* Older compilers need this to NOT be locally defined in a function. */
+  template <typename TSubTable>
+  struct SubTableSanitizeWrapper : TSubTable
+  {
+    bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) const
+    { return this->dispatch (c, lookup_type); }
+  };
+
+  template <typename TSubTable>
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
+    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
+    {
+      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
+      if (!markFilteringSet.sanitize (c)) return_trace (false);
+    }
+
+    if (unlikely (!CastR<OffsetArrayOf<SubTableSanitizeWrapper<TSubTable> > > (subTable)
+                   .sanitize (c, this, get_type ())))
+      return_trace (false);
+
+    if (unlikely (get_type () == TSubTable::Extension))
+    {
+      /* The spec says all subtables of an Extension lookup should
+       * have the same type, which shall not be the Extension type
+       * itself (but we already checked for that).
+       * This is specially important if one has a reverse type! */
+      unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
+      unsigned int count = get_subtable_count ();
+      for (unsigned int i = 1; i < count; i++)
+        if (get_subtable<TSubTable> (i).u.extension.get_type () != type)
+          return_trace (false);
+    }
+    return_trace (true);
+    return_trace (true);
+  }
+
+  private:
+  HBUINT16      lookupType;             /* Different enumerations for GSUB and GPOS */
+  HBUINT16      lookupFlag;             /* Lookup qualifiers */
+  ArrayOf<Offset16>
+                subTable;               /* Array of SubTables */
+/*HBUINT16      markFilteringSetX[VAR];*//* Index (base 0) into GDEF mark glyph sets
+                                         * structure. This field is only present if bit
+                                         * UseMarkFilteringSet of lookup flags is set. */
+  public:
+  DEFINE_SIZE_ARRAY (6, subTable);
+};
+
+typedef OffsetListOf<Lookup> LookupList;
+
+
+/*
+ * Coverage Table
+ */
+
+struct CoverageFormat1
+{
+  friend struct Coverage;
+
+  private:
+  unsigned int get_coverage (hb_codepoint_t glyph_id) const
+  {
+    unsigned int i;
+    glyphArray.bfind (glyph_id, &i, HB_BFIND_NOT_FOUND_STORE, NOT_COVERED);
+    return i;
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    return_trace (glyphArray.serialize (c, glyphs));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (glyphArray.sanitize (c));
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    /* TODO Speed up, using hb_set_next() and bsearch()? */
+    unsigned int count = glyphArray.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (glyphs->has (glyphArray[i]))
+        return true;
+    return false;
+  }
+  bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+  { return glyphs->has (glyphArray[index]); }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    return glyphs->add_sorted_array (glyphArray.arrayZ, glyphArray.len);
+  }
+
+  public:
+  /* Older compilers need this to be public. */
+  struct Iter {
+    void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }
+    void fini () {}
+    bool more () { return i < c->glyphArray.len; }
+    void next () { i++; }
+    hb_codepoint_t get_glyph () { return c->glyphArray[i]; }
+    unsigned int get_coverage () { return i; }
+
+    private:
+    const struct CoverageFormat1 *c;
+    unsigned int i;
+  };
+  private:
+
+  protected:
+  HBUINT16      coverageFormat; /* Format identifier--format = 1 */
+  SortedArrayOf<GlyphID>
+                glyphArray;     /* Array of GlyphIDs--in numerical order */
+  public:
+  DEFINE_SIZE_ARRAY (4, glyphArray);
+};
+
+struct CoverageFormat2
+{
+  friend struct Coverage;
+
+  private:
+  unsigned int get_coverage (hb_codepoint_t glyph_id) const
+  {
+    const RangeRecord &range = rangeRecord.bsearch (glyph_id);
+    return likely (range.start <= range.end) ?
+           (unsigned int) range.value + (glyph_id - range.start) :
+           NOT_COVERED;
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    if (unlikely (!glyphs.length))
+    {
+      rangeRecord.len.set (0);
+      return_trace (true);
+    }
+
+    unsigned int num_ranges = 1;
+    for (unsigned int i = 1; i < glyphs.length; i++)
+      if (glyphs[i - 1] + 1 != glyphs[i])
+        num_ranges++;
+    rangeRecord.len.set (num_ranges);
+    if (unlikely (!c->extend (rangeRecord))) return_trace (false);
+
+    unsigned int range = 0;
+    rangeRecord[range].start = glyphs[0];
+    rangeRecord[range].value.set (0);
+    for (unsigned int i = 1; i < glyphs.length; i++)
+    {
+      if (glyphs[i - 1] + 1 != glyphs[i])
+      {
+        range++;
+        rangeRecord[range].start = glyphs[i];
+        rangeRecord[range].value.set (i);
+      }
+      rangeRecord[range].end = glyphs[i];
+    }
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (rangeRecord.sanitize (c));
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    /* TODO Speed up, using hb_set_next() and bsearch()? */
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (rangeRecord[i].intersects (glyphs))
+        return true;
+    return false;
+  }
+  bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+  {
+    unsigned int i;
+    unsigned int count = rangeRecord.len;
+    for (i = 0; i < count; i++) {
+      const RangeRecord &range = rangeRecord[i];
+      if (range.value <= index &&
+          index < (unsigned int) range.value + (range.end - range.start) &&
+          range.intersects (glyphs))
+        return true;
+      else if (index < range.value)
+        return false;
+    }
+    return false;
+  }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
+        return false;
+    return true;
+  }
+
+  public:
+  /* Older compilers need this to be public. */
+  struct Iter
+  {
+    void init (const CoverageFormat2 &c_)
+    {
+      c = &c_;
+      coverage = 0;
+      i = 0;
+      j = c->rangeRecord.len ? c->rangeRecord[0].start : 0;
+      if (unlikely (c->rangeRecord[0].start > c->rangeRecord[0].end))
+      {
+        /* Broken table. Skip. */
+        i = c->rangeRecord.len;
+      }
+    }
+    void fini () {}
+    bool more () { return i < c->rangeRecord.len; }
+    void next ()
+    {
+      if (j >= c->rangeRecord[i].end)
+      {
+        i++;
+        if (more ())
+        {
+          hb_codepoint_t old = j;
+          j = c->rangeRecord[i].start;
+          if (unlikely (j <= old))
+          {
+            /* Broken table. Skip. Important to avoid DoS. */
+           i = c->rangeRecord.len;
+           return;
+          }
+          coverage = c->rangeRecord[i].value;
+        }
+        return;
+      }
+      coverage++;
+      j++;
+    }
+    hb_codepoint_t get_glyph () { return j; }
+    unsigned int get_coverage () { return coverage; }
+
+    private:
+    const struct CoverageFormat2 *c;
+    unsigned int i, coverage;
+    hb_codepoint_t j;
+  };
+  private:
+
+  protected:
+  HBUINT16      coverageFormat; /* Format identifier--format = 2 */
+  SortedArrayOf<RangeRecord>
+                rangeRecord;    /* Array of glyph ranges--ordered by
+                                 * Start GlyphID. rangeCount entries
+                                 * long */
+  public:
+  DEFINE_SIZE_ARRAY (4, rangeRecord);
+};
+
+struct Coverage
+{
+  unsigned int get_coverage (hb_codepoint_t glyph_id) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.get_coverage (glyph_id);
+    case 2: return u.format2.get_coverage (glyph_id);
+    default:return NOT_COVERED;
+    }
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    unsigned int num_ranges = 1;
+    for (unsigned int i = 1; i < glyphs.length; i++)
+      if (glyphs[i - 1] + 1 != glyphs[i])
+        num_ranges++;
+    u.format.set (glyphs.length * 2 < num_ranges * 3 ? 1 : 2);
+
+    switch (u.format)
+    {
+    case 1: return_trace (u.format1.serialize (c, glyphs));
+    case 2: return_trace (u.format2.serialize (c, glyphs));
+    default:return_trace (false);
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format)
+    {
+    case 1: return_trace (u.format1.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    switch (u.format)
+    {
+    case 1: return u.format1.intersects (glyphs);
+    case 2: return u.format2.intersects (glyphs);
+    default:return false;
+    }
+  }
+  bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+  {
+    switch (u.format)
+    {
+    case 1: return u.format1.intersects_coverage (glyphs, index);
+    case 2: return u.format2.intersects_coverage (glyphs, index);
+    default:return false;
+    }
+  }
+
+  /* Might return false if array looks unsorted.
+   * Used for faster rejection of corrupt data. */
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    switch (u.format)
+    {
+    case 1: return u.format1.add_coverage (glyphs);
+    case 2: return u.format2.add_coverage (glyphs);
+    default:return false;
+    }
+  }
+
+  struct Iter
+  {
+    Iter (const Coverage &c_)
+    {
+      memset (this, 0, sizeof (*this));
+      format = c_.u.format;
+      switch (format)
+      {
+      case 1: u.format1.init (c_.u.format1); return;
+      case 2: u.format2.init (c_.u.format2); return;
+      default:                               return;
+      }
+    }
+    bool more ()
+    {
+      switch (format)
+      {
+      case 1: return u.format1.more ();
+      case 2: return u.format2.more ();
+      default:return false;
+      }
+    }
+    void next ()
+    {
+      switch (format)
+      {
+      case 1: u.format1.next (); break;
+      case 2: u.format2.next (); break;
+      default:                   break;
+      }
+    }
+    hb_codepoint_t get_glyph ()
+    {
+      switch (format)
+      {
+      case 1: return u.format1.get_glyph ();
+      case 2: return u.format2.get_glyph ();
+      default:return 0;
+      }
+    }
+    unsigned int get_coverage ()
+    {
+      switch (format)
+      {
+      case 1: return u.format1.get_coverage ();
+      case 2: return u.format2.get_coverage ();
+      default:return -1;
+      }
+    }
+
+    private:
+    unsigned int format;
+    union {
+    CoverageFormat2::Iter       format2; /* Put this one first since it's larger; helps shut up compiler. */
+    CoverageFormat1::Iter       format1;
+    } u;
+  };
+
+  protected:
+  union {
+  HBUINT16              format;         /* Format identifier */
+  CoverageFormat1       format1;
+  CoverageFormat2       format2;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+
+
+/*
+ * Class Definition Table
+ */
+
+static inline void ClassDef_serialize (hb_serialize_context_t *c,
+                                       hb_array_t<const GlyphID> glyphs,
+                                       hb_array_t<const HBUINT16> klasses);
+
+struct ClassDefFormat1
+{
+  friend struct ClassDef;
+
+  private:
+  unsigned int get_class (hb_codepoint_t glyph_id) const
+  {
+    return classValue[(unsigned int) (glyph_id - startGlyph)];
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const HBUINT16> glyphs,
+                  hb_array_t<const HBUINT16> klasses)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    if (unlikely (!glyphs.length))
+    {
+      startGlyph.set (0);
+      classValue.len.set (0);
+      return_trace (true);
+    }
+
+    hb_codepoint_t glyph_min = glyphs[0];
+    hb_codepoint_t glyph_max = glyphs[glyphs.length - 1];
+
+    startGlyph.set (glyph_min);
+    classValue.len.set (glyph_max - glyph_min + 1);
+    if (unlikely (!c->extend (classValue))) return_trace (false);
+
+    for (unsigned int i = 0; i < glyphs.length; i++)
+      classValue[glyphs[i] - glyph_min] = klasses[i];
+
+    return_trace (true);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset;
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+    hb_vector_t<GlyphID> glyphs;
+    hb_vector_t<HBUINT16> klasses;
+
+    hb_codepoint_t start = startGlyph;
+    hb_codepoint_t end   = start + classValue.len;
+    for (hb_codepoint_t g = start; g < end; g++)
+    {
+      unsigned int value = classValue[g - start];
+      if (!value) continue;
+      if (!glyphset.has (g)) continue;
+      glyphs.push()->set (glyph_map[g]);
+      klasses.push()->set (value);
+    }
+    c->serializer->propagate_error (glyphs, klasses);
+    ClassDef_serialize (c->serializer, glyphs, klasses);
+    return_trace (glyphs.length);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && classValue.sanitize (c));
+  }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    unsigned int start = 0;
+    unsigned int count = classValue.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (classValue[i])
+        continue;
+
+      if (start != i)
+        if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + i)))
+          return false;
+
+      start = i + 1;
+    }
+    if (start != count)
+      if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + count)))
+        return false;
+
+    return true;
+  }
+
+  template <typename set_t>
+  bool add_class (set_t *glyphs, unsigned int klass) const
+  {
+    unsigned int count = classValue.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (classValue[i] == klass) glyphs->add (startGlyph + i);
+    return true;
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    /* TODO Speed up, using hb_set_next()? */
+    hb_codepoint_t start = startGlyph;
+    hb_codepoint_t end = startGlyph + classValue.len;
+    for (hb_codepoint_t iter = startGlyph - 1;
+         hb_set_next (glyphs, &iter) && iter < end;)
+      if (classValue[iter - start]) return true;
+    return false;
+  }
+  bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
+  {
+    unsigned int count = classValue.len;
+    if (klass == 0)
+    {
+      /* Match if there's any glyph that is not listed! */
+      hb_codepoint_t g = HB_SET_VALUE_INVALID;
+      if (!hb_set_next (glyphs, &g)) return false;
+      if (g < startGlyph) return true;
+      g = startGlyph + count - 1;
+      if (hb_set_next (glyphs, &g)) return true;
+      /* Fall through. */
+    }
+    for (unsigned int i = 0; i < count; i++)
+      if (classValue[i] == klass && glyphs->has (startGlyph + i))
+        return true;
+    return false;
+  }
+
+  protected:
+  HBUINT16      classFormat;    /* Format identifier--format = 1 */
+  GlyphID       startGlyph;     /* First GlyphID of the classValueArray */
+  ArrayOf<HBUINT16>
+                classValue;     /* Array of Class Values--one per GlyphID */
+  public:
+  DEFINE_SIZE_ARRAY (6, classValue);
+};
+
+struct ClassDefFormat2
+{
+  friend struct ClassDef;
+
+  private:
+  unsigned int get_class (hb_codepoint_t glyph_id) const
+  {
+    return rangeRecord.bsearch (glyph_id).value;
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const HBUINT16> glyphs,
+                  hb_array_t<const HBUINT16> klasses)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    if (unlikely (!glyphs.length))
+    {
+      rangeRecord.len.set (0);
+      return_trace (true);
+    }
+
+    unsigned int num_ranges = 1;
+    for (unsigned int i = 1; i < glyphs.length; i++)
+      if (glyphs[i - 1] + 1 != glyphs[i] ||
+          klasses[i - 1] != klasses[i])
+        num_ranges++;
+    rangeRecord.len.set (num_ranges);
+    if (unlikely (!c->extend (rangeRecord))) return_trace (false);
+
+    unsigned int range = 0;
+    rangeRecord[range].start = glyphs[0];
+    rangeRecord[range].value.set (klasses[0]);
+    for (unsigned int i = 1; i < glyphs.length; i++)
+    {
+      if (glyphs[i - 1] + 1 != glyphs[i] ||
+          klasses[i - 1] != klasses[i])
+      {
+        range++;
+        rangeRecord[range].start = glyphs[i];
+        rangeRecord[range].value = klasses[i];
+      }
+      rangeRecord[range].end = glyphs[i];
+    }
+    return_trace (true);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset;
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+    hb_vector_t<GlyphID> glyphs;
+    hb_vector_t<HBUINT16> klasses;
+
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      unsigned int value = rangeRecord[i].value;
+      if (!value) continue;
+      hb_codepoint_t start = rangeRecord[i].start;
+      hb_codepoint_t end   = rangeRecord[i].end + 1;
+      for (hb_codepoint_t g = start; g < end; g++)
+      {
+        if (!glyphset.has (g)) continue;
+        glyphs.push ()->set (glyph_map[g]);
+        klasses.push ()->set (value);
+      }
+    }
+    c->serializer->propagate_error (glyphs, klasses);
+    ClassDef_serialize (c->serializer, glyphs, klasses);
+    return_trace (glyphs.length);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (rangeRecord.sanitize (c));
+  }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (rangeRecord[i].value)
+        if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
+          return false;
+    return true;
+  }
+
+  template <typename set_t>
+  bool add_class (set_t *glyphs, unsigned int klass) const
+  {
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (rangeRecord[i].value == klass)
+        if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
+          return false;
+    }
+    return true;
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    /* TODO Speed up, using hb_set_next() and bsearch()? */
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (rangeRecord[i].intersects (glyphs))
+        return true;
+    return false;
+  }
+  bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
+  {
+    unsigned int count = rangeRecord.len;
+    if (klass == 0)
+    {
+      /* Match if there's any glyph that is not listed! */
+      hb_codepoint_t g = HB_SET_VALUE_INVALID;
+      for (unsigned int i = 0; i < count; i++)
+      {
+        if (!hb_set_next (glyphs, &g))
+          break;
+        if (g < rangeRecord[i].start)
+          return true;
+        g = rangeRecord[i].end;
+      }
+      if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
+        return true;
+      /* Fall through. */
+    }
+    for (unsigned int i = 0; i < count; i++)
+      if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
+        return true;
+    return false;
+  }
+
+  protected:
+  HBUINT16      classFormat;    /* Format identifier--format = 2 */
+  SortedArrayOf<RangeRecord>
+                rangeRecord;    /* Array of glyph ranges--ordered by
+                                 * Start GlyphID */
+  public:
+  DEFINE_SIZE_ARRAY (4, rangeRecord);
+};
+
+struct ClassDef
+{
+  unsigned int get_class (hb_codepoint_t glyph_id) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.get_class (glyph_id);
+    case 2: return u.format2.get_class (glyph_id);
+    default:return 0;
+    }
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  hb_array_t<const HBUINT16> klasses)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    unsigned int format = 2;
+    if (glyphs.length)
+    {
+      hb_codepoint_t glyph_min = glyphs[0];
+      hb_codepoint_t glyph_max = glyphs[glyphs.length - 1];
+
+      unsigned int num_ranges = 1;
+      for (unsigned int i = 1; i < glyphs.length; i++)
+        if (glyphs[i - 1] + 1 != glyphs[i] ||
+            klasses[i - 1] != klasses[i])
+          num_ranges++;
+
+      if (1 + (glyph_max - glyph_min + 1) < num_ranges * 3)
+        format = 1;
+    }
+    u.format.set (format);
+
+    switch (u.format)
+    {
+    case 1: return_trace (u.format1.serialize (c, glyphs, klasses));
+    case 2: return_trace (u.format2.serialize (c, glyphs, klasses));
+    default:return_trace (false);
+    }
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    switch (u.format) {
+    case 1: return_trace (u.format1.subset (c));
+    case 2: return_trace (u.format2.subset (c));
+    default:return_trace (false);
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format) {
+    case 1: return_trace (u.format1.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
+  /* Might return false if array looks unsorted.
+   * Used for faster rejection of corrupt data. */
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.add_coverage (glyphs);
+    case 2: return u.format2.add_coverage (glyphs);
+    default:return false;
+    }
+  }
+
+  /* Might return false if array looks unsorted.
+   * Used for faster rejection of corrupt data. */
+  template <typename set_t>
+  bool add_class (set_t *glyphs, unsigned int klass) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.add_class (glyphs, klass);
+    case 2: return u.format2.add_class (glyphs, klass);
+    default:return false;
+    }
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.intersects (glyphs);
+    case 2: return u.format2.intersects (glyphs);
+    default:return false;
+    }
+  }
+  bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.intersects_class (glyphs, klass);
+    case 2: return u.format2.intersects_class (glyphs, klass);
+    default:return false;
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16              format;         /* Format identifier */
+  ClassDefFormat1       format1;
+  ClassDefFormat2       format2;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+
+static inline void ClassDef_serialize (hb_serialize_context_t *c,
+                                       hb_array_t<const GlyphID> glyphs,
+                                       hb_array_t<const HBUINT16> klasses)
+{ c->start_embed<ClassDef> ()->serialize (c, glyphs, klasses); }
+
+
+/*
+ * Item Variation Store
+ */
+
+struct VarRegionAxis
+{
+  float evaluate (int coord) const
+  {
+    int start = startCoord, peak = peakCoord, end = endCoord;
+
+    /* TODO Move these to sanitize(). */
+    if (unlikely (start > peak || peak > end))
+      return 1.;
+    if (unlikely (start < 0 && end > 0 && peak != 0))
+      return 1.;
+
+    if (peak == 0 || coord == peak)
+      return 1.;
+
+    if (coord <= start || end <= coord)
+      return 0.;
+
+    /* Interpolate */
+    if (coord < peak)
+      return float (coord - start) / (peak - start);
+    else
+      return float (end - coord) / (end - peak);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+    /* TODO Handle invalid start/peak/end configs, so we don't
+     * have to do that at runtime. */
+  }
+
+  public:
+  F2DOT14       startCoord;
+  F2DOT14       peakCoord;
+  F2DOT14       endCoord;
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct VarRegionList
+{
+  float evaluate (unsigned int region_index,
+                         const int *coords, unsigned int coord_len) const
+  {
+    if (unlikely (region_index >= regionCount))
+      return 0.;
+
+    const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
+
+    float v = 1.;
+    unsigned int count = axisCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      int coord = i < coord_len ? coords[i] : 0;
+      float factor = axes[i].evaluate (coord);
+      if (factor == 0.f)
+        return 0.;
+      v *= factor;
+    }
+    return v;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  axesZ.sanitize (c, (unsigned int) axisCount * (unsigned int) regionCount));
+  }
+
+  unsigned int get_region_count () const { return regionCount; }
+
+  protected:
+  HBUINT16      axisCount;
+  HBUINT16      regionCount;
+  UnsizedArrayOf<VarRegionAxis>
+                axesZ;
+  public:
+  DEFINE_SIZE_ARRAY (4, axesZ);
+};
+
+struct VarData
+{
+  unsigned int get_region_index_count () const
+  { return regionIndices.len; }
+
+  unsigned int get_row_size () const
+  { return shortCount + regionIndices.len; }
+
+  unsigned int get_size () const
+  { return itemCount * get_row_size (); }
+
+  float get_delta (unsigned int inner,
+                          const int *coords, unsigned int coord_count,
+                          const VarRegionList &regions) const
+  {
+    if (unlikely (inner >= itemCount))
+      return 0.;
+
+   unsigned int count = regionIndices.len;
+   unsigned int scount = shortCount;
+
+   const HBUINT8 *bytes = &StructAfter<HBUINT8> (regionIndices);
+   const HBUINT8 *row = bytes + inner * (scount + count);
+
+   float delta = 0.;
+   unsigned int i = 0;
+
+   const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row);
+   for (; i < scount; i++)
+   {
+     float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+     delta += scalar * *scursor++;
+   }
+   const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
+   for (; i < count; i++)
+   {
+     float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+     delta += scalar * *bcursor++;
+   }
+
+   return delta;
+  }
+
+  void get_scalars (int *coords, unsigned int coord_count,
+                    const VarRegionList &regions,
+                    float *scalars /*OUT */,
+                    unsigned int num_scalars) const
+  {
+    assert (num_scalars == regionIndices.len);
+   for (unsigned int i = 0; i < num_scalars; i++)
+   {
+     scalars[i] = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+   }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  regionIndices.sanitize (c) &&
+                  shortCount <= regionIndices.len &&
+                  c->check_range (&StructAfter<HBUINT8> (regionIndices),
+                                  itemCount,
+                                  get_row_size ()));
+  }
+
+  protected:
+  HBUINT16              itemCount;
+  HBUINT16              shortCount;
+  ArrayOf<HBUINT16>     regionIndices;
+/*UnsizedArrayOf<HBUINT8>bytesX;*/
+  public:
+  DEFINE_SIZE_ARRAY (6, regionIndices);
+};
+
+struct VariationStore
+{
+  float get_delta (unsigned int outer, unsigned int inner,
+                   const int *coords, unsigned int coord_count) const
+  {
+    if (unlikely (outer >= dataSets.len))
+      return 0.;
+
+    return (this+dataSets[outer]).get_delta (inner,
+                                             coords, coord_count,
+                                             this+regions);
+  }
+
+  float get_delta (unsigned int index,
+                   const int *coords, unsigned int coord_count) const
+  {
+    unsigned int outer = index >> 16;
+    unsigned int inner = index & 0xFFFF;
+    return get_delta (outer, inner, coords, coord_count);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  format == 1 &&
+                  regions.sanitize (c, this) &&
+                  dataSets.sanitize (c, this));
+  }
+
+  unsigned int get_region_index_count (unsigned int ivs) const
+  { return (this+dataSets[ivs]).get_region_index_count (); }
+
+  void get_scalars (unsigned int ivs,
+                    int *coords, unsigned int coord_count,
+                    float *scalars /*OUT*/,
+                    unsigned int num_scalars) const
+  {
+    (this+dataSets[ivs]).get_scalars (coords, coord_count, this+regions,
+                                      &scalars[0], num_scalars);
+  }
+
+  protected:
+  HBUINT16                              format;
+  LOffsetTo<VarRegionList>              regions;
+  LOffsetArrayOf<VarData>               dataSets;
+  public:
+  DEFINE_SIZE_ARRAY (8, dataSets);
+};
+
+/*
+ * Feature Variations
+ */
+
+struct ConditionFormat1
+{
+  friend struct Condition;
+
+  private:
+  bool evaluate (const int *coords, unsigned int coord_len) const
+  {
+    int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
+    return filterRangeMinValue <= coord && coord <= filterRangeMaxValue;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 1 */
+  HBUINT16      axisIndex;
+  F2DOT14       filterRangeMinValue;
+  F2DOT14       filterRangeMaxValue;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct Condition
+{
+  bool evaluate (const int *coords, unsigned int coord_len) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.evaluate (coords, coord_len);
+    default:return false;
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format) {
+    case 1: return_trace (u.format1.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16              format;         /* Format identifier */
+  ConditionFormat1      format1;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+
+struct ConditionSet
+{
+  bool evaluate (const int *coords, unsigned int coord_len) const
+  {
+    unsigned int count = conditions.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len))
+        return false;
+    return true;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (conditions.sanitize (c, this));
+  }
+
+  protected:
+  LOffsetArrayOf<Condition>     conditions;
+  public:
+  DEFINE_SIZE_ARRAY (2, conditions);
+};
+
+struct FeatureTableSubstitutionRecord
+{
+  friend struct FeatureTableSubstitution;
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && feature.sanitize (c, base));
+  }
+
+  protected:
+  HBUINT16              featureIndex;
+  LOffsetTo<Feature>    feature;
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct FeatureTableSubstitution
+{
+  const Feature *find_substitute (unsigned int feature_index) const
+  {
+    unsigned int count = substitutions.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const FeatureTableSubstitutionRecord &record = substitutions.arrayZ[i];
+      if (record.featureIndex == feature_index)
+        return &(this+record.feature);
+    }
+    return nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+                  likely (version.major == 1) &&
+                  substitutions.sanitize (c, this));
+  }
+
+  protected:
+  FixedVersion<>        version;        /* Version--0x00010000u */
+  ArrayOf<FeatureTableSubstitutionRecord>
+                        substitutions;
+  public:
+  DEFINE_SIZE_ARRAY (6, substitutions);
+};
+
+struct FeatureVariationRecord
+{
+  friend struct FeatureVariations;
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (conditions.sanitize (c, base) &&
+                  substitutions.sanitize (c, base));
+  }
+
+  protected:
+  LOffsetTo<ConditionSet>
+                        conditions;
+  LOffsetTo<FeatureTableSubstitution>
+                        substitutions;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct FeatureVariations
+{
+  static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFFFFFu;
+
+  bool find_index (const int *coords, unsigned int coord_len,
+                          unsigned int *index) const
+  {
+    unsigned int count = varRecords.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const FeatureVariationRecord &record = varRecords.arrayZ[i];
+      if ((this+record.conditions).evaluate (coords, coord_len))
+      {
+        *index = i;
+        return true;
+      }
+    }
+    *index = NOT_FOUND_INDEX;
+    return false;
+  }
+
+  const Feature *find_substitute (unsigned int variations_index,
+                                  unsigned int feature_index) const
+  {
+    const FeatureVariationRecord &record = varRecords[variations_index];
+    return (this+record.substitutions).find_substitute (feature_index);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    return_trace (c->serializer->embed (*this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+                  likely (version.major == 1) &&
+                  varRecords.sanitize (c, this));
+  }
+
+  protected:
+  FixedVersion<>        version;        /* Version--0x00010000u */
+  LArrayOf<FeatureVariationRecord>
+                        varRecords;
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (8, varRecords);
+};
+
+
+/*
+ * Device Tables
+ */
+
+struct HintingDevice
+{
+  friend struct Device;
+
+  private:
+
+  hb_position_t get_x_delta (hb_font_t *font) const
+  { return get_delta (font->x_ppem, font->x_scale); }
+
+  hb_position_t get_y_delta (hb_font_t *font) const
+  { return get_delta (font->y_ppem, font->y_scale); }
+
+  unsigned int get_size () const
+  {
+    unsigned int f = deltaFormat;
+    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * HBUINT16::static_size;
+    return HBUINT16::static_size * (4 + ((endSize - startSize) >> (4 - f)));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
+  }
+
+  private:
+
+  int get_delta (unsigned int ppem, int scale) const
+  {
+    if (!ppem) return 0;
+
+    int pixels = get_delta_pixels (ppem);
+
+    if (!pixels) return 0;
+
+    return (int) (pixels * (int64_t) scale / ppem);
+  }
+  int get_delta_pixels (unsigned int ppem_size) const
+  {
+    unsigned int f = deltaFormat;
+    if (unlikely (f < 1 || f > 3))
+      return 0;
+
+    if (ppem_size < startSize || ppem_size > endSize)
+      return 0;
+
+    unsigned int s = ppem_size - startSize;
+
+    unsigned int byte = deltaValueZ[s >> (4 - f)];
+    unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
+    unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
+
+    int delta = bits & mask;
+
+    if ((unsigned int) delta >= ((mask + 1) >> 1))
+      delta -= mask + 1;
+
+    return delta;
+  }
+
+  protected:
+  HBUINT16      startSize;              /* Smallest size to correct--in ppem */
+  HBUINT16      endSize;                /* Largest size to correct--in ppem */
+  HBUINT16      deltaFormat;            /* Format of DeltaValue array data: 1, 2, or 3
+                                         * 1    Signed 2-bit value, 8 values per uint16
+                                         * 2    Signed 4-bit value, 4 values per uint16
+                                         * 3    Signed 8-bit value, 2 values per uint16
+                                         */
+  UnsizedArrayOf<HBUINT16>
+                deltaValueZ;            /* Array of compressed data */
+  public:
+  DEFINE_SIZE_ARRAY (6, deltaValueZ);
+};
+
+struct VariationDevice
+{
+  friend struct Device;
+
+  private:
+
+  hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const
+  { return font->em_scalef_x (get_delta (font, store)); }
+
+  hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
+  { return font->em_scalef_y (get_delta (font, store)); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  private:
+
+  float get_delta (hb_font_t *font, const VariationStore &store) const
+  {
+    return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords);
+  }
+
+  protected:
+  HBUINT16      outerIndex;
+  HBUINT16      innerIndex;
+  HBUINT16      deltaFormat;    /* Format identifier for this table: 0x0x8000 */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct DeviceHeader
+{
+  protected:
+  HBUINT16              reserved1;
+  HBUINT16              reserved2;
+  public:
+  HBUINT16              format;         /* Format identifier */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct Device
+{
+  hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
+  {
+    switch (u.b.format)
+    {
+    case 1: case 2: case 3:
+      return u.hinting.get_x_delta (font);
+    case 0x8000:
+      return u.variation.get_x_delta (font, store);
+    default:
+      return 0;
+    }
+  }
+  hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
+  {
+    switch (u.b.format)
+    {
+    case 1: case 2: case 3:
+      return u.hinting.get_y_delta (font);
+    case 0x8000:
+      return u.variation.get_y_delta (font, store);
+    default:
+      return 0;
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.b.format.sanitize (c)) return_trace (false);
+    switch (u.b.format) {
+    case 1: case 2: case 3:
+      return_trace (u.hinting.sanitize (c));
+    case 0x8000:
+      return_trace (u.variation.sanitize (c));
+    default:
+      return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  DeviceHeader          b;
+  HintingDevice         hinting;
+  VariationDevice       variation;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (6, b);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_LAYOUT_COMMON_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gdef-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gdef-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -29,9 +29,9 @@
 #ifndef HB_OT_LAYOUT_GDEF_TABLE_HH
 #define HB_OT_LAYOUT_GDEF_TABLE_HH
 
-#include "hb-ot-layout-common-private.hh"
+#include "hb-ot-layout-common.hh"
 
-#include "hb-font-private.hh"
+#include "hb-font.hh"
 
 
 namespace OT {
@@ -46,10 +46,10 @@
 
 struct AttachList
 {
-  inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
-                                         unsigned int start_offset,
-                                         unsigned int *point_count /* IN/OUT */,
-                                         unsigned int *point_array /* OUT */) const
+  unsigned int get_attach_points (hb_codepoint_t glyph_id,
+                                  unsigned int start_offset,
+                                  unsigned int *point_count /* IN/OUT */,
+                                  unsigned int *point_array /* OUT */) const
   {
     unsigned int index = (this+coverage).get_coverage (glyph_id);
     if (index == NOT_COVERED)
@@ -61,9 +61,10 @@
 
     const AttachPoint &points = this+attachPoint[index];
 
-    if (point_count) {
-      const HBUINT16 *array = points.sub_array (start_offset, point_count);
-      unsigned int count = *point_count;
+    if (point_count)
+    {
+      hb_array_t<const HBUINT16> array = points.sub_array (start_offset, point_count);
+      unsigned int count = array.length;
       for (unsigned int i = 0; i < count; i++)
         point_array[i] = array[i];
     }
@@ -71,7 +72,7 @@
     return points.len;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && attachPoint.sanitize (c, this));
@@ -97,12 +98,12 @@
   friend struct CaretValue;
 
   private:
-  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
+  hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
   {
     return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -120,16 +121,14 @@
   friend struct CaretValue;
 
   private:
-  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
+  hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
   {
     hb_position_t x, y;
-    if (font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y))
-      return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
-    else
-      return 0;
+    font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y);
+    return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -146,14 +145,15 @@
 {
   friend struct CaretValue;
 
-  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, const VariationStore &var_store) const
+  hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction,
+                                 const VariationStore &var_store) const
   {
     return HB_DIRECTION_IS_HORIZONTAL (direction) ?
            font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) :
            font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
@@ -172,7 +172,7 @@
 
 struct CaretValue
 {
-  inline hb_position_t get_caret_value (hb_font_t *font,
+  hb_position_t get_caret_value (hb_font_t *font,
                                         hb_direction_t direction,
                                         hb_codepoint_t glyph_id,
                                         const VariationStore &var_store) const
@@ -185,7 +185,7 @@
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
@@ -210,17 +210,18 @@
 
 struct LigGlyph
 {
-  inline unsigned int get_lig_carets (hb_font_t *font,
-                                      hb_direction_t direction,
-                                      hb_codepoint_t glyph_id,
-                                      const VariationStore &var_store,
-                                      unsigned int start_offset,
-                                      unsigned int *caret_count /* IN/OUT */,
-                                      hb_position_t *caret_array /* OUT */) const
+  unsigned int get_lig_carets (hb_font_t *font,
+                               hb_direction_t direction,
+                               hb_codepoint_t glyph_id,
+                               const VariationStore &var_store,
+                               unsigned int start_offset,
+                               unsigned int *caret_count /* IN/OUT */,
+                               hb_position_t *caret_array /* OUT */) const
   {
-    if (caret_count) {
-      const OffsetTo<CaretValue> *array = carets.sub_array (start_offset, caret_count);
-      unsigned int count = *caret_count;
+    if (caret_count)
+    {
+      hb_array_t <const OffsetTo<CaretValue> > array = carets.sub_array (start_offset, caret_count);
+      unsigned int count = array.length;
       for (unsigned int i = 0; i < count; i++)
         caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store);
     }
@@ -228,7 +229,7 @@
     return carets.len;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (carets.sanitize (c, this));
@@ -245,13 +246,13 @@
 
 struct LigCaretList
 {
-  inline unsigned int get_lig_carets (hb_font_t *font,
-                                      hb_direction_t direction,
-                                      hb_codepoint_t glyph_id,
-                                      const VariationStore &var_store,
-                                      unsigned int start_offset,
-                                      unsigned int *caret_count /* IN/OUT */,
-                                      hb_position_t *caret_array /* OUT */) const
+  unsigned int get_lig_carets (hb_font_t *font,
+                               hb_direction_t direction,
+                               hb_codepoint_t glyph_id,
+                               const VariationStore &var_store,
+                               unsigned int start_offset,
+                               unsigned int *caret_count /* IN/OUT */,
+                               hb_position_t *caret_array /* OUT */) const
   {
     unsigned int index = (this+coverage).get_coverage (glyph_id);
     if (index == NOT_COVERED)
@@ -264,7 +265,7 @@
     return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
@@ -284,10 +285,10 @@
 
 struct MarkGlyphSetsFormat1
 {
-  inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
+  bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this));
@@ -304,7 +305,7 @@
 
 struct MarkGlyphSets
 {
-  inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
+  bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   {
     switch (u.format) {
     case 1: return u.format1.covers (set_index, glyph_id);
@@ -312,7 +313,7 @@
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
@@ -337,9 +338,10 @@
  * https://docs.microsoft.com/en-us/typography/opentype/spec/gdef
  */
 
+
 struct GDEF
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_GDEF;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF;
 
   enum GlyphClasses {
     UnclassifiedGlyph   = 0,
@@ -349,59 +351,47 @@
     ComponentGlyph      = 4
   };
 
-  inline bool has_glyph_classes (void) const { return glyphClassDef != 0; }
-  inline unsigned int get_glyph_class (hb_codepoint_t glyph) const
+  bool has_data () const { return version.to_int (); }
+  bool has_glyph_classes () const { return glyphClassDef != 0; }
+  unsigned int get_glyph_class (hb_codepoint_t glyph) const
   { return (this+glyphClassDef).get_class (glyph); }
-  inline void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
+  void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
   { (this+glyphClassDef).add_class (glyphs, klass); }
 
-  inline bool has_mark_attachment_types (void) const { return markAttachClassDef != 0; }
-  inline unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
+  bool has_mark_attachment_types () const { return markAttachClassDef != 0; }
+  unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
   { return (this+markAttachClassDef).get_class (glyph); }
 
-  inline bool has_attach_points (void) const { return attachList != 0; }
-  inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
-                                         unsigned int start_offset,
-                                         unsigned int *point_count /* IN/OUT */,
-                                         unsigned int *point_array /* OUT */) const
+  bool has_attach_points () const { return attachList != 0; }
+  unsigned int get_attach_points (hb_codepoint_t glyph_id,
+                                  unsigned int start_offset,
+                                  unsigned int *point_count /* IN/OUT */,
+                                  unsigned int *point_array /* OUT */) const
   { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); }
 
-  inline bool has_lig_carets (void) const { return ligCaretList != 0; }
-  inline unsigned int get_lig_carets (hb_font_t *font,
-                                      hb_direction_t direction,
-                                      hb_codepoint_t glyph_id,
-                                      unsigned int start_offset,
-                                      unsigned int *caret_count /* IN/OUT */,
-                                      hb_position_t *caret_array /* OUT */) const
+  bool has_lig_carets () const { return ligCaretList != 0; }
+  unsigned int get_lig_carets (hb_font_t *font,
+                               hb_direction_t direction,
+                               hb_codepoint_t glyph_id,
+                               unsigned int start_offset,
+                               unsigned int *caret_count /* IN/OUT */,
+                               hb_position_t *caret_array /* OUT */) const
   { return (this+ligCaretList).get_lig_carets (font,
                                                direction, glyph_id, get_var_store(),
                                                start_offset, caret_count, caret_array); }
 
-  inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; }
-  inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
+  bool has_mark_sets () const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; }
+  bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); }
 
-  inline bool has_var_store (void) const { return version.to_int () >= 0x00010003u && varStore != 0; }
-  inline const VariationStore &get_var_store (void) const
+  bool has_var_store () const { return version.to_int () >= 0x00010003u && varStore != 0; }
+  const VariationStore &get_var_store () const
   { return version.to_int () >= 0x00010003u ? this+varStore : Null(VariationStore); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-                  likely (version.major == 1) &&
-                  glyphClassDef.sanitize (c, this) &&
-                  attachList.sanitize (c, this) &&
-                  ligCaretList.sanitize (c, this) &&
-                  markAttachClassDef.sanitize (c, this) &&
-                  (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
-                  (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
-  }
-
   /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
-   * glyph class and other bits, and high 8-bit gthe mark attachment type (if any).
+   * glyph class and other bits, and high 8-bit the mark attachment type (if any).
    * Not to be confused with lookup_props which is very similar. */
-  inline unsigned int get_glyph_props (hb_codepoint_t glyph) const
+  unsigned int get_glyph_props (hb_codepoint_t glyph) const
   {
     unsigned int klass = get_glyph_class (glyph);
 
@@ -419,6 +409,65 @@
     }
   }
 
+  HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
+                                   hb_face_t *face) const;
+
+  struct accelerator_t
+  {
+    void init (hb_face_t *face)
+    {
+      this->table = hb_sanitize_context_t().reference_table<GDEF> (face);
+      if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face)))
+      {
+        hb_blob_destroy (this->table.get_blob ());
+        this->table = hb_blob_get_empty ();
+      }
+    }
+
+    void fini () { this->table.destroy (); }
+
+    hb_blob_ptr_t<GDEF> table;
+  };
+
+  unsigned int get_size () const
+  {
+    return min_size +
+           (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +
+           (version.to_int () >= 0x00010003u ? varStore.static_size : 0);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct GDEF *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+
+    out->glyphClassDef.serialize_subset (c, this+glyphClassDef, out);
+    out->attachList.set (0);//TODO(subset) serialize_subset (c, this+attachList, out);
+    out->ligCaretList.set (0);//TODO(subset) serialize_subset (c, this+ligCaretList, out);
+    out->markAttachClassDef.serialize_subset (c, this+markAttachClassDef, out);
+
+    if (version.to_int () >= 0x00010002u)
+      out->markGlyphSetsDef.set (0);// TODO(subset) serialize_subset (c, this+markGlyphSetsDef, out);
+
+    if (version.to_int () >= 0x00010003u)
+      out->varStore.set (0);// TODO(subset) serialize_subset (c, this+varStore, out);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+                  likely (version.major == 1) &&
+                  glyphClassDef.sanitize (c, this) &&
+                  attachList.sanitize (c, this) &&
+                  ligCaretList.sanitize (c, this) &&
+                  markAttachClassDef.sanitize (c, this) &&
+                  (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
+                  (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
+  }
 
   protected:
   FixedVersion<>version;                /* Version of the GDEF table--currently
@@ -453,6 +502,7 @@
   DEFINE_SIZE_MIN (12);
 };
 
+struct GDEF_accelerator_t : GDEF::accelerator_t {};
 
 } /* namespace OT */
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gpos-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gpos-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -29,7 +29,7 @@
 #ifndef HB_OT_LAYOUT_GPOS_TABLE_HH
 #define HB_OT_LAYOUT_GPOS_TABLE_HH
 
-#include "hb-ot-layout-gsubgpos-private.hh"
+#include "hb-ot-layout-gsubgpos.hh"
 
 
 namespace OT {
@@ -53,7 +53,7 @@
 
 typedef HBUINT16 Value;
 
-typedef Value ValueRecord[VAR];
+typedef UnsizedArrayOf<Value> ValueRecord;
 
 struct ValueFormat : HBUINT16
 {
@@ -84,79 +84,79 @@
   HBINT16               yAdvance;               /* Vertical adjustment for advance--in
                                          * design units (only used for vertical
                                          * writing) */
-  Offset        xPlaDevice;             /* Offset to Device table for
+  OffsetTo<Device>      xPlaDevice;     /* Offset to Device table for
                                          * horizontal placement--measured from
                                          * beginning of PosTable (may be NULL) */
-  Offset        yPlaDevice;             /* Offset to Device table for vertical
+  OffsetTo<Device>      yPlaDevice;     /* Offset to Device table for vertical
                                          * placement--measured from beginning
                                          * of PosTable (may be NULL) */
-  Offset        xAdvDevice;             /* Offset to Device table for
+  OffsetTo<Device>      xAdvDevice;     /* Offset to Device table for
                                          * horizontal advance--measured from
                                          * beginning of PosTable (may be NULL) */
-  Offset        yAdvDevice;             /* Offset to Device table for vertical
+  OffsetTo<Device>      yAdvDevice;     /* Offset to Device table for vertical
                                          * advance--measured from beginning of
                                          * PosTable (may be NULL) */
 #endif
 
-  inline unsigned int get_len (void) const
-  { return _hb_popcount ((unsigned int) *this); }
-  inline unsigned int get_size (void) const
-  { return get_len () * Value::static_size; }
+  unsigned int get_len () const  { return hb_popcount ((unsigned int) *this); }
+  unsigned int get_size () const { return get_len () * Value::static_size; }
 
-  void apply_value (hb_ot_apply_context_t   *c,
+  bool apply_value (hb_ot_apply_context_t   *c,
                     const void           *base,
                     const Value          *values,
                     hb_glyph_position_t  &glyph_pos) const
   {
+    bool ret = false;
     unsigned int format = *this;
-    if (!format) return;
+    if (!format) return ret;
 
     hb_font_t *font = c->font;
-    hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
+    bool horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
 
-    if (format & xPlacement) glyph_pos.x_offset  += font->em_scale_x (get_short (values++));
-    if (format & yPlacement) glyph_pos.y_offset  += font->em_scale_y (get_short (values++));
+    if (format & xPlacement) glyph_pos.x_offset  += font->em_scale_x (get_short (values++, &ret));
+    if (format & yPlacement) glyph_pos.y_offset  += font->em_scale_y (get_short (values++, &ret));
     if (format & xAdvance) {
-      if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values));
+      if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
       values++;
     }
     /* y_advance values grow downward but font-space grows upward, hence negation */
     if (format & yAdvance) {
-      if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values));
+      if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
       values++;
     }
 
-    if (!has_device ()) return;
+    if (!has_device ()) return ret;
 
     bool use_x_device = font->x_ppem || font->num_coords;
     bool use_y_device = font->y_ppem || font->num_coords;
 
-    if (!use_x_device && !use_y_device) return;
+    if (!use_x_device && !use_y_device) return ret;
 
     const VariationStore &store = c->var_store;
 
     /* pixel -> fractional pixel */
     if (format & xPlaDevice) {
-      if (use_x_device) glyph_pos.x_offset  += (base + get_device (values)).get_x_delta (font, store);
+      if (use_x_device) glyph_pos.x_offset  += (base + get_device (values, &ret)).get_x_delta (font, store);
       values++;
     }
     if (format & yPlaDevice) {
-      if (use_y_device) glyph_pos.y_offset  += (base + get_device (values)).get_y_delta (font, store);
+      if (use_y_device) glyph_pos.y_offset  += (base + get_device (values, &ret)).get_y_delta (font, store);
       values++;
     }
     if (format & xAdvDevice) {
-      if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font, store);
+      if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store);
       values++;
     }
     if (format & yAdvDevice) {
       /* y_advance values grow downward but font-space grows upward, hence negation */
-      if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font, store);
+      if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store);
       values++;
     }
+    return ret;
   }
 
   private:
-  inline bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
+  bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
   {
     unsigned int format = *this;
 
@@ -173,33 +173,40 @@
     return true;
   }
 
-  static inline OffsetTo<Device>& get_device (Value* value)
-  { return *CastP<OffsetTo<Device> > (value); }
-  static inline const OffsetTo<Device>& get_device (const Value* value)
+  static OffsetTo<Device>& get_device (Value* value)
   { return *CastP<OffsetTo<Device> > (value); }
+  static const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
+  {
+    if (worked) *worked |= bool (*value);
+    return *CastP<OffsetTo<Device> > (value);
+  }
 
-  static inline const HBINT16& get_short (const Value* value)
-  { return *CastP<HBINT16> (value); }
+  static const HBINT16& get_short (const Value* value, bool *worked=nullptr)
+  {
+    if (worked) *worked |= bool (*value);
+    return *CastP<HBINT16> (value);
+  }
 
   public:
 
-  inline bool has_device (void) const {
+  bool has_device () const
+  {
     unsigned int format = *this;
     return (format & devices) != 0;
   }
 
-  inline bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
+  bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
   }
 
-  inline bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
+  bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
   {
     TRACE_SANITIZE (this);
     unsigned int len = get_len ();
 
-    if (!c->check_array (values, get_size (), count)) return_trace (false);
+    if (!c->check_range (values, count, get_size ())) return_trace (false);
 
     if (!has_device ()) return_trace (true);
 
@@ -213,7 +220,7 @@
   }
 
   /* Just sanitize referenced Device tables.  Doesn't check the values themselves. */
-  inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
+  bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
   {
     TRACE_SANITIZE (this);
 
@@ -232,15 +239,15 @@
 
 struct AnchorFormat1
 {
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
-                          float *x, float *y) const
+  void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+                   float *x, float *y) const
   {
     hb_font_t *font = c->font;
     *x = font->em_fscale_x (xCoordinate);
     *y = font->em_fscale_y (yCoordinate);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -256,22 +263,22 @@
 
 struct AnchorFormat2
 {
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
-                          float *x, float *y) const
+  void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+                   float *x, float *y) const
   {
     hb_font_t *font = c->font;
     unsigned int x_ppem = font->x_ppem;
     unsigned int y_ppem = font->y_ppem;
     hb_position_t cx = 0, cy = 0;
-    hb_bool_t ret;
+    bool ret;
 
     ret = (x_ppem || y_ppem) &&
-           font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
+          font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
     *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
     *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -288,8 +295,8 @@
 
 struct AnchorFormat3
 {
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
-                          float *x, float *y) const
+  void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+                   float *x, float *y) const
   {
     hb_font_t *font = c->font;
     *x = font->em_fscale_x (xCoordinate);
@@ -301,7 +308,7 @@
       *y += (this+yDeviceTable).get_y_delta (font, c->var_store);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
@@ -325,8 +332,8 @@
 
 struct Anchor
 {
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
-                          float *x, float *y) const
+  void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+                   float *x, float *y) const
   {
     *x = *y = 0;
     switch (u.format) {
@@ -337,7 +344,7 @@
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
@@ -363,20 +370,22 @@
 
 struct AnchorMatrix
 {
-  inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols, bool *found) const {
+  const Anchor& get_anchor (unsigned int row, unsigned int col,
+                            unsigned int cols, bool *found) const
+  {
     *found = false;
     if (unlikely (row >= rows || col >= cols)) return Null(Anchor);
     *found = !matrixZ[row * cols + col].is_null ();
     return this+matrixZ[row * cols + col];
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
   {
     TRACE_SANITIZE (this);
     if (!c->check_struct (this)) return_trace (false);
-    if (unlikely (_hb_unsigned_int_mul_overflows (rows, cols))) return_trace (false);
+    if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
     unsigned int count = rows * cols;
-    if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false);
+    if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
     for (unsigned int i = 0; i < count; i++)
       if (!matrixZ[i].sanitize (c, this)) return_trace (false);
     return_trace (true);
@@ -384,8 +393,8 @@
 
   HBUINT16      rows;                   /* Number of rows */
   protected:
-  OffsetTo<Anchor>
-                matrixZ[VAR];           /* Matrix of offsets to Anchor tables--
+  UnsizedArrayOf<OffsetTo<Anchor> >
+                matrixZ;                /* Matrix of offsets to Anchor tables--
                                          * from beginning of AnchorMatrix table */
   public:
   DEFINE_SIZE_ARRAY (2, matrixZ);
@@ -396,7 +405,7 @@
 {
   friend struct MarkArray;
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
@@ -413,10 +422,10 @@
 
 struct MarkArray : ArrayOf<MarkRecord>  /* Array of MarkRecords--in Coverage order */
 {
-  inline bool apply (hb_ot_apply_context_t *c,
-                     unsigned int mark_index, unsigned int glyph_index,
-                     const AnchorMatrix &anchors, unsigned int class_count,
-                     unsigned int glyph_pos) const
+  bool apply (hb_ot_apply_context_t *c,
+              unsigned int mark_index, unsigned int glyph_index,
+              const AnchorMatrix &anchors, unsigned int class_count,
+              unsigned int glyph_pos) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -447,7 +456,7 @@
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (ArrayOf<MarkRecord>::sanitize (c, this));
@@ -459,18 +468,15 @@
 
 struct SinglePosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-  }
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -483,7 +489,14 @@
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -507,18 +520,15 @@
 
 struct SinglePosFormat2
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-  }
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -535,7 +545,14 @@
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -560,7 +577,7 @@
 struct SinglePos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -598,19 +615,36 @@
 {
   friend struct PairPosFormat1;
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c,
-                              const ValueFormat *valueFormats) const
+  bool intersects (const hb_set_t *glyphs,
+                          const ValueFormat *valueFormats) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     unsigned int len1 = valueFormats[0].get_len ();
     unsigned int len2 = valueFormats[1].get_len ();
     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
 
-    const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
+    const PairValueRecord *record = &firstPairValueRecord;
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (glyphs->has (record->secondGlyph))
+        return true;
+      record = &StructAtOffset<const PairValueRecord> (record, record_size);
+    }
+    return false;
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c,
+                              const ValueFormat *valueFormats) const
+  {
+    unsigned int len1 = valueFormats[0].get_len ();
+    unsigned int len2 = valueFormats[1].get_len ();
+    unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
+
+    const PairValueRecord *record = &firstPairValueRecord;
     c->input->add_array (&record->secondGlyph, len, record_size);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c,
+  bool apply (hb_ot_apply_context_t *c,
                      const ValueFormat *valueFormats,
                      unsigned int pos) const
   {
@@ -620,7 +654,6 @@
     unsigned int len2 = valueFormats[1].get_len ();
     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
 
-    const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
     unsigned int count = len;
 
     /* Hand-coded bsearch. */
@@ -630,8 +663,8 @@
     int min = 0, max = (int) count - 1;
     while (min <= max)
     {
-      int mid = (min + max) / 2;
-      const PairValueRecord *record = &StructAtOffset<PairValueRecord> (record_array, record_size * mid);
+      int mid = ((unsigned int) min + (unsigned int) max) / 2;
+      const PairValueRecord *record = &StructAtOffset<PairValueRecord> (&firstPairValueRecord, record_size * mid);
       hb_codepoint_t mid_x = record->secondGlyph;
       if (x < mid_x)
         max = mid - 1;
@@ -639,9 +672,10 @@
         min = mid + 1;
       else
       {
-        buffer->unsafe_to_break (buffer->idx, pos + 1);
-        valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
-        valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
+        /* Note the intentional use of "|" instead of short-circuit "||". */
+        if (valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()) |
+            valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]))
+          buffer->unsafe_to_break (buffer->idx, pos + 1);
         if (len2)
           pos++;
         buffer->idx = pos;
@@ -652,50 +686,65 @@
     return_trace (false);
   }
 
-  struct sanitize_closure_t {
+  struct sanitize_closure_t
+  {
     const void *base;
     const ValueFormat *valueFormats;
     unsigned int len1; /* valueFormats[0].get_len() */
     unsigned int stride; /* 1 + len1 + len2 */
   };
 
-  inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
+  bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
   {
     TRACE_SANITIZE (this);
     if (!(c->check_struct (this)
-       && c->check_array (arrayZ, HBUINT16::static_size * closure->stride, len))) return_trace (false);
+       && c->check_range (&firstPairValueRecord,
+                          len,
+                          HBUINT16::static_size,
+                          closure->stride))) return_trace (false);
 
     unsigned int count = len;
-    const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
+    const PairValueRecord *record = &firstPairValueRecord;
     return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) &&
                   closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
   }
 
   protected:
-  HBUINT16      len;                    /* Number of PairValueRecords */
-  HBUINT16      arrayZ[VAR];            /* Array of PairValueRecords--ordered
-                                         * by GlyphID of the second glyph */
+  HBUINT16              len;    /* Number of PairValueRecords */
+  PairValueRecord       firstPairValueRecord;
+                                /* Array of PairValueRecords--ordered
+                                 * by GlyphID of the second glyph */
   public:
-  DEFINE_SIZE_ARRAY (2, arrayZ);
+  DEFINE_SIZE_MIN (2);
 };
 
 struct PairPosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_COLLECT_GLYPHS (this);
+    unsigned int count = pairSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (glyphs->has (iter.get_glyph ()) &&
+          (this+pairSet[iter.get_coverage ()]).intersects (glyphs, valueFormat))
+        return true;
+    }
+    return false;
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
     unsigned int count = pairSet.len;
     for (unsigned int i = 0; i < count; i++)
       (this+pairSet[i]).collect_glyphs (c, valueFormat);
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -709,7 +758,14 @@
     return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
 
@@ -717,7 +773,8 @@
 
     unsigned int len1 = valueFormat[0].get_len ();
     unsigned int len2 = valueFormat[1].get_len ();
-    PairSet::sanitize_closure_t closure = {
+    PairSet::sanitize_closure_t closure =
+    {
       this,
       valueFormat,
       len1,
@@ -747,19 +804,21 @@
 
 struct PairPosFormat2
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_COLLECT_GLYPHS (this);
+    return (this+coverage).intersects (glyphs) &&
+           (this+classDef2).intersects (glyphs);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
     if (unlikely (!(this+classDef2).add_coverage (c->input))) return;
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -778,10 +837,11 @@
     unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
     if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
 
-    buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
     const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
-    valueFormat1.apply_value (c, this, v, buffer->cur_pos());
-    valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
+    /* Note the intentional use of "|" instead of short-circuit "||". */
+    if (valueFormat1.apply_value (c, this, v, buffer->cur_pos()) |
+        valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]))
+      buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
 
     buffer->idx = skippy_iter.idx;
     if (len2)
@@ -790,7 +850,14 @@
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!(c->check_struct (this)
@@ -803,7 +870,9 @@
     unsigned int stride = len1 + len2;
     unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
     unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
-    return_trace (c->check_array (values, record_size, count) &&
+    return_trace (c->check_range ((const void *) values,
+                                  count,
+                                  record_size) &&
                   valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
                   valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
   }
@@ -841,7 +910,7 @@
 struct PairPos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -865,7 +934,7 @@
 {
   friend struct CursivePosFormat1;
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
@@ -889,39 +958,36 @@
 
 struct CursivePosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-  }
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
 
     const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage  (buffer->cur().codepoint)];
-    if (!this_record.exitAnchor) return_trace (false);
+    if (!this_record.entryAnchor) return_trace (false);
 
     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
-    if (!skippy_iter.next ()) return_trace (false);
+    if (!skippy_iter.prev ()) return_trace (false);
 
-    const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint)];
-    if (!next_record.entryAnchor) return_trace (false);
+    const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint)];
+    if (!prev_record.exitAnchor) return_trace (false);
 
-    unsigned int i = buffer->idx;
-    unsigned int j = skippy_iter.idx;
+    unsigned int i = skippy_iter.idx;
+    unsigned int j = buffer->idx;
 
     buffer->unsafe_to_break (i, j);
     float entry_x, entry_y, exit_x, exit_y;
-    (this+this_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
-    (this+next_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
+    (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
+    (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
 
     hb_glyph_position_t *pos = buffer->pos;
 
@@ -968,7 +1034,7 @@
      * parent.
      *
      * Optimize things for the case of RightToLeft, as that's most common in
-     * Arabinc. */
+     * Arabic. */
     unsigned int child  = i;
     unsigned int parent = j;
     hb_position_t x_offset = entry_x - exit_x;
@@ -997,11 +1063,18 @@
     else
       pos[child].x_offset = x_offset;
 
-    buffer->idx = j;
+    buffer->idx++;
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
@@ -1022,7 +1095,7 @@
 struct CursivePos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1047,19 +1120,19 @@
 
 struct MarkBasePosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+markCoverage).intersects (glyphs) &&
+           (this+baseCoverage).intersects (glyphs); }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
     if (unlikely (!(this+baseCoverage).add_coverage (c->input))) return;
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+markCoverage;
-  }
+  const Coverage &get_coverage () const { return this+markCoverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1088,7 +1161,7 @@
            ))
         break;
       skippy_iter.reject ();
-    } while (1);
+    } while (true);
 
     /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
     //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
@@ -1099,7 +1172,14 @@
     return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -1131,7 +1211,7 @@
 struct MarkBasePos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1161,19 +1241,19 @@
 
 struct MarkLigPosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+markCoverage).intersects (glyphs) &&
+           (this+ligatureCoverage).intersects (glyphs); }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
     if (unlikely (!(this+ligatureCoverage).add_coverage (c->input))) return;
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+markCoverage;
-  }
+  const Coverage &get_coverage () const { return this+markCoverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1216,7 +1296,14 @@
     return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -1249,7 +1336,7 @@
 struct MarkLigPos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1274,19 +1361,19 @@
 
 struct MarkMarkPosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+mark1Coverage).intersects (glyphs) &&
+           (this+mark2Coverage).intersects (glyphs); }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+mark1Coverage).add_coverage (c->input))) return;
     if (unlikely (!(this+mark2Coverage).add_coverage (c->input))) return;
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+mark1Coverage;
-  }
+  const Coverage &get_coverage () const { return this+mark1Coverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1330,7 +1417,14 @@
     return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -1364,7 +1458,7 @@
 struct MarkMarkPos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1388,7 +1482,7 @@
 
 struct ExtensionPos : Extension<ExtensionPos>
 {
-  typedef struct PosLookupSubTable LookupSubTable;
+  typedef struct PosLookupSubTable SubTable;
 };
 
 
@@ -1400,6 +1494,7 @@
 
 struct PosLookupSubTable
 {
+  friend struct Lookup;
   friend struct PosLookup;
 
   enum Type {
@@ -1415,10 +1510,9 @@
   };
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
+  typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
   {
     TRACE_DISPATCH (this, lookup_type);
-    if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ());
     switch (lookup_type) {
     case Single:                return_trace (u.single.dispatch (c));
     case Pair:                  return_trace (u.pair.dispatch (c));
@@ -1435,7 +1529,6 @@
 
   protected:
   union {
-  HBUINT16              sub_format;
   SinglePos             single;
   PairPos               pair;
   CursivePos            cursive;
@@ -1447,34 +1540,39 @@
   ExtensionPos          extension;
   } u;
   public:
-  DEFINE_SIZE_UNION (2, sub_format);
+  DEFINE_SIZE_MIN (0);
 };
 
 
 struct PosLookup : Lookup
 {
-  inline const PosLookupSubTable& get_subtable (unsigned int i) const
-  { return Lookup::get_subtable<PosLookupSubTable> (i); }
+  typedef struct PosLookupSubTable SubTable;
 
-  inline bool is_reverse (void) const
+  const SubTable& get_subtable (unsigned int i) const
+  { return Lookup::get_subtable<SubTable> (i); }
+
+  bool is_reverse () const
   {
     return false;
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     return_trace (dispatch (c));
   }
 
-  inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_COLLECT_GLYPHS (this);
-    return_trace (dispatch (c));
+    hb_intersects_context_t c (glyphs);
+    return dispatch (&c);
   }
 
+  hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { return dispatch (c); }
+
   template <typename set_t>
-  inline void add_coverage (set_t *glyphs) const
+  void add_coverage (set_t *glyphs) const
   {
     hb_add_coverage_context_t<set_t> c (glyphs);
     dispatch (&c);
@@ -1483,22 +1581,19 @@
   static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
 
   template <typename context_t>
-  static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+  static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  { return Lookup::dispatch<PosLookupSubTable> (c); }
+  typename context_t::return_t dispatch (context_t *c) const
+  { return Lookup::dispatch<SubTable> (c); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!Lookup::sanitize (c))) return_trace (false);
-    return_trace (dispatch (c));
-  }
+  bool subset (hb_subset_context_t *c) const
+  { return Lookup::subset<SubTable> (c); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return Lookup::sanitize<SubTable> (c); }
 };
 
-typedef OffsetListOf<PosLookup> PosLookupList;
-
 /*
  * GPOS -- Glyph Positioning
  * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
@@ -1506,22 +1601,25 @@
 
 struct GPOS : GSUBGPOS
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_GPOS;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
 
-  inline const PosLookup& get_lookup (unsigned int i) const
+  const PosLookup& get_lookup (unsigned int i) const
   { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
 
   static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
   static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
   static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false);
-    const OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
-    return_trace (list.sanitize (c, this));
-  }
+  bool subset (hb_subset_context_t *c) const
+  { return GSUBGPOS::subset<PosLookup> (c); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return GSUBGPOS::sanitize<PosLookup> (c); }
+
+  HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
+                                   hb_face_t *face) const;
+
+  typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
 };
 
 
@@ -1551,7 +1649,10 @@
   pos[j].attach_type() = type;
 }
 static void
-propagate_attachment_offsets (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction)
+propagate_attachment_offsets (hb_glyph_position_t *pos,
+                              unsigned int len,
+                              unsigned int i,
+                              hb_direction_t direction)
 {
   /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
    * offset of glyph they are attached to. */
@@ -1559,11 +1660,14 @@
   if (likely (!chain))
     return;
 
+  pos[i].attach_chain() = 0;
+
   unsigned int j = (int) i + chain;
 
-  pos[i].attach_chain() = 0;
+  if (unlikely (j >= len))
+    return;
 
-  propagate_attachment_offsets (pos, j, direction);
+  propagate_attachment_offsets (pos, len, j, direction);
 
   assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE));
 
@@ -1602,7 +1706,7 @@
 }
 
 void
-GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
+GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
 {
   //_hb_buffer_assert_gsubgpos_vars (buffer);
 }
@@ -1619,24 +1723,25 @@
   /* Handle attachments */
   if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
     for (unsigned int i = 0; i < len; i++)
-      propagate_attachment_offsets (pos, i, direction);
+      propagate_attachment_offsets (pos, len, i, direction);
 }
 
 
+struct GPOS_accelerator_t : GPOS::accelerator_t {};
+
+
 /* Out-of-class implementation for methods recursing */
 
 template <typename context_t>
 /*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
 {
-  const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
-  const PosLookup &l = gpos.get_lookup (lookup_index);
+  const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
   return l.dispatch (c);
 }
 
 /*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
 {
-  const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
-  const PosLookup &l = gpos.get_lookup (lookup_index);
+  const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
   unsigned int saved_lookup_props = c->lookup_props;
   unsigned int saved_lookup_index = c->lookup_index;
   c->set_lookup_index (lookup_index);
@@ -1648,10 +1753,6 @@
 }
 
 
-#undef attach_chain
-#undef attach_type
-
-
 } /* namespace OT */
 
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsub-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsub-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -29,34 +29,37 @@
 #ifndef HB_OT_LAYOUT_GSUB_TABLE_HH
 #define HB_OT_LAYOUT_GSUB_TABLE_HH
 
-#include "hb-ot-layout-gsubgpos-private.hh"
+#include "hb-ot-layout-gsubgpos.hh"
 
 
 namespace OT {
 
 
+static inline void SingleSubst_serialize (hb_serialize_context_t *c,
+                                          hb_array_t<const GlyphID> glyphs,
+                                          hb_array_t<const GlyphID> substitutes);
+
 struct SingleSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       /* TODO Switch to range-based API to work around malicious fonts.
        * https://github.com/harfbuzz/harfbuzz/issues/363 */
       hb_codepoint_t glyph_id = iter.get_glyph ();
       if (c->glyphs->has (glyph_id))
-        c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
+        c->out->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       /* TODO Switch to range-based API to work around malicious fonts.
        * https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -65,18 +68,15 @@
     }
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
@@ -91,19 +91,37 @@
     return_trace (true);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         unsigned int num_glyphs,
-                         int delta)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  int delta)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */
+    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
+    deltaGlyphID.set (delta); /* TODO(serialize) overflow? */
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset;
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+    hb_vector_t<GlyphID> from;
+    hb_vector_t<GlyphID> to;
+    hb_codepoint_t delta = deltaGlyphID;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (!glyphset.has (iter.get_glyph ())) continue;
+      from.push ()->set (glyph_map[iter.get_glyph ()]);
+      to.push ()->set (glyph_map[(iter.get_glyph () + delta) & 0xFFFF]);
+    }
+    c->serializer->propagate_error (from, to);
+    SingleSubst_serialize (c->serializer, from, to);
+    return_trace (from.length);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
@@ -122,27 +140,26 @@
 
 struct SingleSubstFormat2
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
     unsigned int count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       if (c->glyphs->has (iter.get_glyph ()))
-        c->glyphs->add (substitute[iter.get_coverage ()]);
+        c->out->add (substitute[iter.get_coverage ()]);
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
     unsigned int count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -150,45 +167,57 @@
     }
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
     if (unlikely (index >= substitute.len)) return_trace (false);
 
-    glyph_id = substitute[index];
-    c->replace_glyph (glyph_id);
+    c->replace_glyph (substitute[index]);
 
     return_trace (true);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         Supplier<GlyphID> &substitutes,
-                         unsigned int num_glyphs)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  hb_array_t<const GlyphID> substitutes)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return_trace (false);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
+    if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
+    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset;
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+    hb_vector_t<GlyphID> from;
+    hb_vector_t<GlyphID> to;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (!glyphset.has (iter.get_glyph ())) continue;
+      from.push ()->set (glyph_map[iter.get_glyph ()]);
+      to.push ()->set (glyph_map[substitute[iter.get_coverage ()]]);
+    }
+    c->serializer->propagate_error (from, to);
+    SingleSubst_serialize (c->serializer, from, to);
+    return_trace (from.length);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && substitute.sanitize (c));
@@ -208,35 +237,35 @@
 
 struct SingleSubst
 {
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         Supplier<GlyphID> &substitutes,
-                         unsigned int num_glyphs)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  hb_array_t<const GlyphID> substitutes)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 2;
     int delta = 0;
-    if (num_glyphs) {
+    if (glyphs.length)
+    {
       format = 1;
       /* TODO(serialize) check for wrap-around */
       delta = substitutes[0] - glyphs[0];
-      for (unsigned int i = 1; i < num_glyphs; i++)
-        if (delta != substitutes[i] - glyphs[i]) {
+      for (unsigned int i = 1; i < glyphs.length; i++)
+        if (delta != (int) (substitutes[i] - glyphs[i])) {
           format = 2;
           break;
         }
     }
     u.format.set (format);
     switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs, delta));
-    case 2: return_trace (u.format2.serialize (c, glyphs, substitutes, num_glyphs));
+    case 1: return_trace (u.format1.serialize (c, glyphs, delta));
+    case 2: return_trace (u.format2.serialize (c, glyphs, substitutes));
     default:return_trace (false);
     }
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -255,24 +284,25 @@
   } u;
 };
 
+static inline void
+SingleSubst_serialize (hb_serialize_context_t *c,
+                       hb_array_t<const GlyphID> glyphs,
+                       hb_array_t<const GlyphID> substitutes)
+{ c->start_embed<SingleSubst> ()->serialize (c, glyphs, substitutes); }
 
 struct Sequence
 {
-  inline void closure (hb_closure_context_t *c) const
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
     unsigned int count = substitute.len;
     for (unsigned int i = 0; i < count; i++)
-      c->glyphs->add (substitute[i]);
+      c->out->add (substitute[i]);
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    c->output->add_array (substitute.arrayZ, substitute.len);
-  }
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { c->output->add_array (substitute.arrayZ, substitute.len); }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int count = substitute.len;
@@ -304,17 +334,14 @@
     return_trace (true);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         unsigned int num_glyphs)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
+    return_trace (substitute.serialize (c, glyphs));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (substitute.sanitize (c));
@@ -329,12 +356,13 @@
 
 struct MultipleSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
     unsigned int count = sequence.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -343,27 +371,23 @@
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
     unsigned int count = sequence.len;
     for (unsigned int i = 0; i < count; i++)
-        (this+sequence[i]).collect_glyphs (c);
+      (this+sequence[i]).collect_glyphs (c);
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
@@ -373,25 +397,33 @@
     return_trace ((this+sequence[index]).apply (c));
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         Supplier<unsigned int> &substitute_len_list,
-                         unsigned int num_glyphs,
-                         Supplier<GlyphID> &substitute_glyphs_list)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  hb_array_t<const unsigned int> substitute_len_list,
+                  hb_array_t<const GlyphID> substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!sequence.serialize (c, num_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      if (unlikely (!sequence[i].serialize (c, this).serialize (c,
-                                                                substitute_glyphs_list,
-                                                                substitute_len_list[i]))) return_trace (false);
-    substitute_len_list += num_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
+    if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      unsigned int substitute_len = substitute_len_list[i];
+      if (unlikely (!sequence[i].serialize (c, this)
+                                .serialize (c, substitute_glyphs_list.sub_array (0, substitute_len))))
+        return_trace (false);
+      substitute_glyphs_list += substitute_len;
+    }
+    return_trace (coverage.serialize (c, this).serialize (c, glyphs));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this));
@@ -411,24 +443,23 @@
 
 struct MultipleSubst
 {
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         Supplier<unsigned int> &substitute_len_list,
-                         unsigned int num_glyphs,
-                         Supplier<GlyphID> &substitute_glyphs_list)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  hb_array_t<const unsigned int> substitute_len_list,
+                  hb_array_t<const GlyphID> substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 1;
     u.format.set (format);
     switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, num_glyphs, substitute_glyphs_list));
+    case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list));
     default:return_trace (false);
     }
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -445,103 +476,138 @@
   } u;
 };
 
+struct AlternateSet
+{
+  void closure (hb_closure_context_t *c) const
+  {
+    unsigned int count = alternates.len;
+    for (unsigned int i = 0; i < count; i++)
+      c->out->add (alternates[i]);
+  }
 
-typedef ArrayOf<GlyphID> AlternateSet;  /* Array of alternate GlyphIDs--in
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { c->output->add_array (alternates.arrayZ, alternates.len); }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int count = alternates.len;
+
+    if (unlikely (!count)) return_trace (false);
+
+    hb_mask_t glyph_mask = c->buffer->cur().mask;
+    hb_mask_t lookup_mask = c->lookup_mask;
+
+    /* Note: This breaks badly if two features enabled this lookup together. */
+    unsigned int shift = hb_ctz (lookup_mask);
+    unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
+
+    /* If alt_index is MAX, randomize feature if it is the rand feature. */
+    if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
+      alt_index = c->random_number () % count + 1;
+
+    if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
+
+    c->replace_glyph (alternates[alt_index - 1]);
+
+    return_trace (true);
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    return_trace (alternates.serialize (c, glyphs));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (alternates.sanitize (c));
+  }
+
+  protected:
+  ArrayOf<GlyphID>
+                alternates;             /* Array of alternate GlyphIDs--in
                                          * arbitrary order */
+  public:
+  DEFINE_SIZE_ARRAY (2, alternates);
+};
 
 struct AlternateSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
     unsigned int count = alternateSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
-      if (c->glyphs->has (iter.get_glyph ())) {
-        const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
-        unsigned int count = alt_set.len;
-        for (unsigned int i = 0; i < count; i++)
-          c->glyphs->add (alt_set[i]);
-      }
+      if (c->glyphs->has (iter.get_glyph ()))
+        (this+alternateSet[iter.get_coverage ()]).closure (c);
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
     unsigned int count = alternateSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
-      const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
-      c->output->add_array (alt_set.arrayZ, alt_set.len);
+      (this+alternateSet[iter.get_coverage ()]).collect_glyphs (c);
     }
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
 
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
-    const AlternateSet &alt_set = this+alternateSet[index];
-
-    if (unlikely (!alt_set.len)) return_trace (false);
-
-    hb_mask_t glyph_mask = c->buffer->cur().mask;
-    hb_mask_t lookup_mask = c->lookup_mask;
-
-    /* Note: This breaks badly if two features enabled this lookup together. */
-    unsigned int shift = _hb_ctz (lookup_mask);
-    unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
-
-    if (unlikely (alt_index > alt_set.len || alt_index == 0)) return_trace (false);
-
-    glyph_id = alt_set[alt_index - 1];
-
-    c->replace_glyph (glyph_id);
-
-    return_trace (true);
+    return_trace ((this+alternateSet[index]).apply (c));
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         Supplier<unsigned int> &alternate_len_list,
-                         unsigned int num_glyphs,
-                         Supplier<GlyphID> &alternate_glyphs_list)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  hb_array_t<const unsigned int> alternate_len_list,
+                  hb_array_t<const GlyphID> alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!alternateSet.serialize (c, num_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      if (unlikely (!alternateSet[i].serialize (c, this).serialize (c,
-                                                                    alternate_glyphs_list,
-                                                                    alternate_len_list[i]))) return_trace (false);
-    alternate_len_list += num_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
+    if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      unsigned int alternate_len = alternate_len_list[i];
+      if (unlikely (!alternateSet[i].serialize (c, this)
+                                    .serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
+        return_trace (false);
+      alternate_glyphs_list += alternate_len;
+    }
+    return_trace (coverage.serialize (c, this).serialize (c, glyphs));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
@@ -561,24 +627,23 @@
 
 struct AlternateSubst
 {
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         Supplier<unsigned int> &alternate_len_list,
-                         unsigned int num_glyphs,
-                         Supplier<GlyphID> &alternate_glyphs_list)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  hb_array_t<const unsigned int> alternate_len_list,
+                  hb_array_t<const GlyphID> alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 1;
     u.format.set (format);
     switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, num_glyphs, alternate_glyphs_list));
+    case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list));
     default:return_trace (false);
     }
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -598,27 +663,34 @@
 
 struct Ligature
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_CLOSURE (this);
-    unsigned int count = component.len;
+    unsigned int count = component.lenP1;
+    for (unsigned int i = 1; i < count; i++)
+      if (!glyphs->has (component[i]))
+        return false;
+    return true;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    unsigned int count = component.lenP1;
     for (unsigned int i = 1; i < count; i++)
       if (!c->glyphs->has (component[i]))
         return;
-    c->glyphs->add (ligGlyph);
+    c->out->add (ligGlyph);
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
-    c->input->add_array (component.arrayZ, component.len ? component.len - 1 : 0);
+    c->input->add_array (component.arrayZ, component.lenP1 ? component.lenP1 - 1 : 0);
     c->output->add (ligGlyph);
   }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
-    if (c->len != component.len)
+    if (c->len != component.lenP1)
       return_trace (false);
 
     for (unsigned int i = 1; i < c->len; i++)
@@ -628,10 +700,10 @@
     return_trace (true);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    unsigned int count = component.len;
+    unsigned int count = component.lenP1;
 
     if (unlikely (!count)) return_trace (false);
 
@@ -643,7 +715,6 @@
       return_trace (true);
     }
 
-    bool is_mark_ligature = false;
     unsigned int total_component_count = 0;
 
     unsigned int match_length = 0;
@@ -655,7 +726,6 @@
                               nullptr,
                               &match_length,
                               match_positions,
-                              &is_mark_ligature,
                               &total_component_count)))
       return_trace (false);
 
@@ -664,26 +734,24 @@
                   match_positions,
                   match_length,
                   ligGlyph,
-                  is_mark_ligature,
                   total_component_count);
 
     return_trace (true);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         GlyphID ligature,
-                         Supplier<GlyphID> &components, /* Starting from second */
-                         unsigned int num_components /* Including first component */)
+  bool serialize (hb_serialize_context_t *c,
+                  GlyphID ligature,
+                  hb_array_t<const GlyphID> components /* Starting from second */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
     ligGlyph = ligature;
-    if (unlikely (!component.serialize (c, components, num_components))) return_trace (false);
+    if (unlikely (!component.serialize (c, components))) return_trace (false);
     return_trace (true);
   }
 
   public:
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (ligGlyph.sanitize (c) && component.sanitize (c));
@@ -701,23 +769,30 @@
 
 struct LigatureSet
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_CLOSURE (this);
+    unsigned int num_ligs = ligature.len;
+    for (unsigned int i = 0; i < num_ligs; i++)
+      if ((this+ligature[i]).intersects (glyphs))
+        return true;
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
     unsigned int num_ligs = ligature.len;
     for (unsigned int i = 0; i < num_ligs; i++)
       (this+ligature[i]).closure (c);
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     unsigned int num_ligs = ligature.len;
     for (unsigned int i = 0; i < num_ligs; i++)
       (this+ligature[i]).collect_glyphs (c);
   }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     unsigned int num_ligs = ligature.len;
@@ -730,7 +805,7 @@
     return_trace (false);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int num_ligs = ligature.len;
@@ -743,26 +818,28 @@
     return_trace (false);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &ligatures,
-                         Supplier<unsigned int> &component_count_list,
-                         unsigned int num_ligatures,
-                         Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> ligatures,
+                  hb_array_t<const unsigned int> component_count_list,
+                  hb_array_t<const GlyphID> &component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!ligature.serialize (c, num_ligatures))) return_trace (false);
-    for (unsigned int i = 0; i < num_ligatures; i++)
-      if (unlikely (!ligature[i].serialize (c, this).serialize (c,
-                                                                ligatures[i],
-                                                                component_list,
-                                                                component_count_list[i]))) return_trace (false);
-    ligatures += num_ligatures;
-    component_count_list += num_ligatures;
+    if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
+    for (unsigned int i = 0; i < ligatures.length; i++)
+    {
+      unsigned int component_count = MAX<int> (component_count_list[i] - 1, 0);
+      if (unlikely (!ligature[i].serialize (c, this)
+                                .serialize (c,
+                                            ligatures[i],
+                                            component_list.sub_array (0, component_count))))
+        return_trace (false);
+      component_list += component_count;
+    }
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (ligature.sanitize (c, this));
@@ -778,12 +855,24 @@
 
 struct LigatureSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
     unsigned int count = ligatureSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (glyphs->has (iter.get_glyph ()) &&
+          (this+ligatureSet[iter.get_coverage ()]).intersects (glyphs))
+        return true;
+    }
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    unsigned int count = ligatureSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -792,13 +881,11 @@
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
     unsigned int count = ligatureSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -806,12 +893,9 @@
     }
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
@@ -821,41 +905,49 @@
     return_trace (lig_set.would_apply (c));
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
 
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
     const LigatureSet &lig_set = this+ligatureSet[index];
     return_trace (lig_set.apply (c));
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &first_glyphs,
-                         Supplier<unsigned int> &ligature_per_first_glyph_count_list,
-                         unsigned int num_first_glyphs,
-                         Supplier<GlyphID> &ligatures_list,
-                         Supplier<unsigned int> &component_count_list,
-                         Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> first_glyphs,
+                  hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+                  hb_array_t<const GlyphID> ligatures_list,
+                  hb_array_t<const unsigned int> component_count_list,
+                  hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_first_glyphs; i++)
-      if (unlikely (!ligatureSet[i].serialize (c, this).serialize (c,
-                                                                   ligatures_list,
-                                                                   component_count_list,
-                                                                   ligature_per_first_glyph_count_list[i],
-                                                                   component_list))) return_trace (false);
-    ligature_per_first_glyph_count_list += num_first_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return_trace (false);
-    return_trace (true);
+    if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
+    for (unsigned int i = 0; i < first_glyphs.length; i++)
+    {
+      unsigned int ligature_count = ligature_per_first_glyph_count_list[i];
+      if (unlikely (!ligatureSet[i].serialize (c, this)
+                                   .serialize (c,
+                                               ligatures_list.sub_array (0, ligature_count),
+                                               component_count_list.sub_array (0, ligature_count),
+                                               component_list))) return_trace (false);
+      ligatures_list += ligature_count;
+      component_count_list += ligature_count;
+    }
+    return_trace (coverage.serialize (c, this).serialize (c, first_glyphs));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
@@ -875,13 +967,12 @@
 
 struct LigatureSubst
 {
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &first_glyphs,
-                         Supplier<unsigned int> &ligature_per_first_glyph_count_list,
-                         unsigned int num_first_glyphs,
-                         Supplier<GlyphID> &ligatures_list,
-                         Supplier<unsigned int> &component_count_list,
-                         Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> first_glyphs,
+                  hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+                  hb_array_t<const GlyphID> ligatures_list,
+                  hb_array_t<const unsigned int> component_count_list,
+                  hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
@@ -891,7 +982,6 @@
     case 1: return_trace (u.format1.serialize (c,
                                                first_glyphs,
                                                ligature_per_first_glyph_count_list,
-                                               num_first_glyphs,
                                                ligatures_list,
                                                component_count_list,
                                                component_list));
@@ -900,7 +990,7 @@
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -924,17 +1014,38 @@
 
 struct ExtensionSubst : Extension<ExtensionSubst>
 {
-  typedef struct SubstLookupSubTable LookupSubTable;
+  typedef struct SubstLookupSubTable SubTable;
 
-  inline bool is_reverse (void) const;
+  bool is_reverse () const;
 };
 
 
 struct ReverseChainSingleSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_CLOSURE (this);
+    if (!(this+coverage).intersects (glyphs))
+      return false;
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    unsigned int count;
+
+    count = backtrack.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!(this+backtrack[i]).intersects (glyphs))
+        return false;
+
+    count = lookahead.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!(this+lookahead[i]).intersects (glyphs))
+        return false;
+
+    return true;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
 
     unsigned int count;
@@ -950,20 +1061,18 @@
         return;
 
     const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
-    Coverage::Iter iter;
     count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       if (c->glyphs->has (iter.get_glyph ()))
-        c->glyphs->add (substitute[iter.get_coverage ()]);
+        c->out->add (substitute[iter.get_coverage ()]);
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
 
     unsigned int count;
@@ -982,18 +1091,15 @@
     c->output->add_array (substitute.arrayZ, substitute.len);
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
@@ -1026,7 +1132,14 @@
     return_trace (false);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
@@ -1045,7 +1158,7 @@
                                          * beginning of table */
   OffsetArrayOf<Coverage>
                 backtrack;              /* Array of coverage tables
-                                         * in backtracking sequence, in  glyph
+                                         * in backtracking sequence, in glyph
                                          * sequence order */
   OffsetArrayOf<Coverage>
                 lookaheadX;             /* Array of coverage tables
@@ -1061,7 +1174,7 @@
 struct ReverseChainSingleSubst
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1086,6 +1199,7 @@
 
 struct SubstLookupSubTable
 {
+  friend struct Lookup;
   friend struct SubstLookup;
 
   enum Type {
@@ -1100,10 +1214,9 @@
   };
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
+  typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
   {
     TRACE_DISPATCH (this, lookup_type);
-    if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ());
     switch (lookup_type) {
     case Single:                return_trace (u.single.dispatch (c));
     case Multiple:              return_trace (u.multiple.dispatch (c));
@@ -1119,7 +1232,6 @@
 
   protected:
   union {
-  HBUINT16                      sub_format;
   SingleSubst                   single;
   MultipleSubst                 multiple;
   AlternateSubst                alternate;
@@ -1130,58 +1242,69 @@
   ReverseChainSingleSubst       reverseChainContextSingle;
   } u;
   public:
-  DEFINE_SIZE_UNION (2, sub_format);
+  DEFINE_SIZE_MIN (0);
 };
 
 
 struct SubstLookup : Lookup
 {
-  inline const SubstLookupSubTable& get_subtable (unsigned int i) const
-  { return Lookup::get_subtable<SubstLookupSubTable> (i); }
+  typedef SubstLookupSubTable SubTable;
+
+  const SubTable& get_subtable (unsigned int i) const
+  { return Lookup::get_subtable<SubTable> (i); }
 
-  inline static bool lookup_type_is_reverse (unsigned int lookup_type)
-  { return lookup_type == SubstLookupSubTable::ReverseChainSingle; }
+  static bool lookup_type_is_reverse (unsigned int lookup_type)
+  { return lookup_type == SubTable::ReverseChainSingle; }
 
-  inline bool is_reverse (void) const
+  bool is_reverse () const
   {
     unsigned int type = get_type ();
-    if (unlikely (type == SubstLookupSubTable::Extension))
+    if (unlikely (type == SubTable::Extension))
       return CastR<ExtensionSubst> (get_subtable(0)).is_reverse ();
     return lookup_type_is_reverse (type);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     return_trace (dispatch (c));
   }
 
-  inline hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_CLOSURE (this);
+    hb_intersects_context_t c (glyphs);
+    return dispatch (&c);
+  }
+
+  hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
+  {
     if (!c->should_visit_lookup (this_index))
-      return_trace (HB_VOID);
+      return hb_closure_context_t::default_return_value ();
 
     c->set_recurse_func (dispatch_closure_recurse_func);
-    return_trace (dispatch (c));
+
+    hb_closure_context_t::return_t ret = dispatch (c);
+
+    c->flush ();
+
+    return ret;
   }
 
-  inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+  hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
-    return_trace (dispatch (c));
+    return dispatch (c);
   }
 
   template <typename set_t>
-  inline void add_coverage (set_t *glyphs) const
+  void add_coverage (set_t *glyphs) const
   {
     hb_add_coverage_context_t<set_t> c (glyphs);
     dispatch (&c);
   }
 
-  inline bool would_apply (hb_would_apply_context_t *c,
-                           const hb_ot_layout_lookup_accelerator_t *accel) const
+  bool would_apply (hb_would_apply_context_t *c,
+                    const hb_ot_layout_lookup_accelerator_t *accel) const
   {
     TRACE_WOULD_APPLY (this);
     if (unlikely (!c->len))  return_trace (false);
@@ -1191,111 +1314,95 @@
 
   static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
 
-  inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c,
-                                                  unsigned int i)
-  { return get_subtables<SubstLookupSubTable> ()[i].serialize (c, this); }
+  SubTable& serialize_subtable (hb_serialize_context_t *c,
+                                       unsigned int i)
+  { return get_subtables<SubTable> ()[i].serialize (c, this); }
 
-  inline bool serialize_single (hb_serialize_context_t *c,
-                                uint32_t lookup_props,
-                                Supplier<GlyphID> &glyphs,
-                                Supplier<GlyphID> &substitutes,
-                                unsigned int num_glyphs)
+  bool serialize_single (hb_serialize_context_t *c,
+                         uint32_t lookup_props,
+                         hb_array_t<const GlyphID> glyphs,
+                         hb_array_t<const GlyphID> substitutes)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_props, 1))) return_trace (false);
-    return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes, num_glyphs));
+    if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
+    return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes));
   }
 
-  inline bool serialize_multiple (hb_serialize_context_t *c,
-                                  uint32_t lookup_props,
-                                  Supplier<GlyphID> &glyphs,
-                                  Supplier<unsigned int> &substitute_len_list,
-                                  unsigned int num_glyphs,
-                                  Supplier<GlyphID> &substitute_glyphs_list)
+  bool serialize_multiple (hb_serialize_context_t *c,
+                           uint32_t lookup_props,
+                           hb_array_t<const GlyphID> glyphs,
+                           hb_array_t<const unsigned int> substitute_len_list,
+                           hb_array_t<const GlyphID> substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_props, 1))) return_trace (false);
+    if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
     return_trace (serialize_subtable (c, 0).u.multiple.serialize (c,
                                                                   glyphs,
                                                                   substitute_len_list,
-                                                                  num_glyphs,
                                                                   substitute_glyphs_list));
   }
 
-  inline bool serialize_alternate (hb_serialize_context_t *c,
-                                   uint32_t lookup_props,
-                                   Supplier<GlyphID> &glyphs,
-                                   Supplier<unsigned int> &alternate_len_list,
-                                   unsigned int num_glyphs,
-                                   Supplier<GlyphID> &alternate_glyphs_list)
+  bool serialize_alternate (hb_serialize_context_t *c,
+                            uint32_t lookup_props,
+                            hb_array_t<const GlyphID> glyphs,
+                            hb_array_t<const unsigned int> alternate_len_list,
+                            hb_array_t<const GlyphID> alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_props, 1))) return_trace (false);
+    if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
     return_trace (serialize_subtable (c, 0).u.alternate.serialize (c,
                                                                    glyphs,
                                                                    alternate_len_list,
-                                                                   num_glyphs,
                                                                    alternate_glyphs_list));
   }
 
-  inline bool serialize_ligature (hb_serialize_context_t *c,
-                                  uint32_t lookup_props,
-                                  Supplier<GlyphID> &first_glyphs,
-                                  Supplier<unsigned int> &ligature_per_first_glyph_count_list,
-                                  unsigned int num_first_glyphs,
-                                  Supplier<GlyphID> &ligatures_list,
-                                  Supplier<unsigned int> &component_count_list,
-                                  Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  bool serialize_ligature (hb_serialize_context_t *c,
+                           uint32_t lookup_props,
+                           hb_array_t<const GlyphID> first_glyphs,
+                           hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+                           hb_array_t<const GlyphID> ligatures_list,
+                           hb_array_t<const unsigned int> component_count_list,
+                           hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_props, 1))) return_trace (false);
+    if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
     return_trace (serialize_subtable (c, 0).u.ligature.serialize (c,
                                                                   first_glyphs,
                                                                   ligature_per_first_glyph_count_list,
-                                                                  num_first_glyphs,
                                                                   ligatures_list,
                                                                   component_count_list,
                                                                   component_list));
   }
 
   template <typename context_t>
-  static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+  static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
 
-  static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index)
+  static hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index)
   {
     if (!c->should_visit_lookup (lookup_index))
       return HB_VOID;
-    return dispatch_recurse_func (c, lookup_index);
+
+    hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index);
+
+    /* While in theory we should flush here, it will cause timeouts because a recursive
+     * lookup can keep growing the glyph set.  Skip, and outer loop will retry up to
+     * HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */
+    //c->flush ();
+
+    return ret;
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  { return Lookup::dispatch<SubstLookupSubTable> (c); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!Lookup::sanitize (c))) return_trace (false);
-    if (unlikely (!dispatch (c))) return_trace (false);
+  typename context_t::return_t dispatch (context_t *c) const
+  { return Lookup::dispatch<SubTable> (c); }
 
-    if (unlikely (get_type () == SubstLookupSubTable::Extension))
-    {
-      /* The spec says all subtables of an Extension lookup should
-       * have the same type, which shall not be the Extension type
-       * itself (but we already checked for that).
-       * This is specially important if one has a reverse type! */
-      unsigned int type = get_subtable (0).u.extension.get_type ();
-      unsigned int count = get_subtable_count ();
-      for (unsigned int i = 1; i < count; i++)
-        if (get_subtable (i).u.extension.get_type () != type)
-          return_trace (false);
-    }
-    return_trace (true);
-  }
+  bool subset (hb_subset_context_t *c) const
+  { return Lookup::subset<SubTable> (c); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return Lookup::sanitize<SubTable> (c); }
 };
 
-typedef OffsetListOf<SubstLookup> SubstLookupList;
-
 /*
  * GSUB -- Glyph Substitution
  * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub
@@ -1303,61 +1410,47 @@
 
 struct GSUB : GSUBGPOS
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_GSUB;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB;
 
-  inline const SubstLookup& get_lookup (unsigned int i) const
+  const SubstLookup& get_lookup (unsigned int i) const
   { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
 
-  static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer);
+  bool subset (hb_subset_context_t *c) const
+  { return GSUBGPOS::subset<SubstLookup> (c); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false);
-    const OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList);
-    return_trace (list.sanitize (c, this));
-  }
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return GSUBGPOS::sanitize<SubstLookup> (c); }
+
+  HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
+                                   hb_face_t *face) const;
+
+  typedef GSUBGPOS::accelerator_t<GSUB> accelerator_t;
 };
 
 
-void
-GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
-{
-  _hb_buffer_assert_gsubgpos_vars (buffer);
-
-  const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
-  unsigned int count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-  {
-    _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
-    _hb_glyph_info_clear_lig_props (&buffer->info[i]);
-    buffer->info[i].syllable() = 0;
-  }
-}
+struct GSUB_accelerator_t : GSUB::accelerator_t {};
 
 
 /* Out-of-class implementation for methods recursing */
 
-/*static*/ inline bool ExtensionSubst::is_reverse (void) const
+/*static*/ inline bool ExtensionSubst::is_reverse () const
 {
   unsigned int type = get_type ();
-  if (unlikely (type == SubstLookupSubTable::Extension))
-    return CastR<ExtensionSubst> (get_subtable<LookupSubTable>()).is_reverse ();
+  if (unlikely (type == SubTable::Extension))
+    return CastR<ExtensionSubst> (get_subtable<SubTable>()).is_reverse ();
   return SubstLookup::lookup_type_is_reverse (type);
 }
 
 template <typename context_t>
 /*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
 {
-  const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
-  const SubstLookup &l = gsub.get_lookup (lookup_index);
+  const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
   return l.dispatch (c);
 }
 
 /*static*/ inline bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
 {
-  const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
-  const SubstLookup &l = gsub.get_lookup (lookup_index);
+  const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
   unsigned int saved_lookup_props = c->lookup_props;
   unsigned int saved_lookup_index = c->lookup_index;
   c->set_lookup_index (lookup_index);
@@ -1368,7 +1461,6 @@
   return ret;
 }
 
-
 } /* namespace OT */
 
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsubgpos-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2394 +0,0 @@
-/*
- * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
- * Copyright © 2010,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): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
-#define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-buffer-private.hh"
-#include "hb-map-private.hh"
-#include "hb-ot-layout-gdef-table.hh"
-#include "hb-set-private.hh"
-
-
-namespace OT {
-
-
-struct hb_closure_context_t :
-       hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE>
-{
-  inline const char *get_name (void) { return "CLOSURE"; }
-  typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
-  template <typename T>
-  inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
-  static return_t default_return_value (void) { return HB_VOID; }
-  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
-  return_t recurse (unsigned int lookup_index)
-  {
-    if (unlikely (nesting_level_left == 0 || !recurse_func))
-      return default_return_value ();
-
-    nesting_level_left--;
-    recurse_func (this, lookup_index);
-    nesting_level_left++;
-    return HB_VOID;
-  }
-
-  bool should_visit_lookup (unsigned int lookup_index)
-  {
-    if (is_lookup_done (lookup_index))
-      return false;
-    done_lookups->set (lookup_index, glyphs->get_population ());
-    return true;
-  }
-
-  bool is_lookup_done (unsigned int lookup_index)
-  {
-    // Have we visited this lookup with the current set of glyphs?
-    return done_lookups->get (lookup_index) == glyphs->get_population ();
-  }
-
-  hb_face_t *face;
-  hb_set_t *glyphs;
-  recurse_func_t recurse_func;
-  unsigned int nesting_level_left;
-  unsigned int debug_depth;
-
-  hb_closure_context_t (hb_face_t *face_,
-                        hb_set_t *glyphs_,
-                        hb_map_t *done_lookups_,
-                        unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
-                          face (face_),
-                          glyphs (glyphs_),
-                          recurse_func (nullptr),
-                          nesting_level_left (nesting_level_left_),
-                          debug_depth (0),
-                          done_lookups (done_lookups_) {}
-
-  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
-
-  private:
-  hb_map_t *done_lookups;
-};
-
-
-struct hb_would_apply_context_t :
-       hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY>
-{
-  inline const char *get_name (void) { return "WOULD_APPLY"; }
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.would_apply (this); }
-  static return_t default_return_value (void) { return false; }
-  bool stop_sublookup_iteration (return_t r) const { return r; }
-
-  hb_face_t *face;
-  const hb_codepoint_t *glyphs;
-  unsigned int len;
-  bool zero_context;
-  unsigned int debug_depth;
-
-  hb_would_apply_context_t (hb_face_t *face_,
-                            const hb_codepoint_t *glyphs_,
-                            unsigned int len_,
-                            bool zero_context_) :
-                              face (face_),
-                              glyphs (glyphs_),
-                              len (len_),
-                              zero_context (zero_context_),
-                              debug_depth (0) {}
-};
-
-
-struct hb_collect_glyphs_context_t :
-       hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, HB_DEBUG_COLLECT_GLYPHS>
-{
-  inline const char *get_name (void) { return "COLLECT_GLYPHS"; }
-  typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
-  template <typename T>
-  inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
-  static return_t default_return_value (void) { return HB_VOID; }
-  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
-  return_t recurse (unsigned int lookup_index)
-  {
-    if (unlikely (nesting_level_left == 0 || !recurse_func))
-      return default_return_value ();
-
-    /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get
-     * past the previous check.  For GSUB, we only want to collect the output
-     * glyphs in the recursion.  If output is not requested, we can go home now.
-     *
-     * Note further, that the above is not exactly correct.  A recursed lookup
-     * is allowed to match input that is not matched in the context, but that's
-     * not how most fonts are built.  It's possible to relax that and recurse
-     * with all sets here if it proves to be an issue.
-     */
-
-    if (output == hb_set_get_empty ())
-      return HB_VOID;
-
-    /* Return if new lookup was recursed to before. */
-    if (recursed_lookups->has (lookup_index))
-      return HB_VOID;
-
-    hb_set_t *old_before = before;
-    hb_set_t *old_input  = input;
-    hb_set_t *old_after  = after;
-    before = input = after = hb_set_get_empty ();
-
-    nesting_level_left--;
-    recurse_func (this, lookup_index);
-    nesting_level_left++;
-
-    before = old_before;
-    input  = old_input;
-    after  = old_after;
-
-    recursed_lookups->add (lookup_index);
-
-    return HB_VOID;
-  }
-
-  hb_face_t *face;
-  hb_set_t *before;
-  hb_set_t *input;
-  hb_set_t *after;
-  hb_set_t *output;
-  recurse_func_t recurse_func;
-  hb_set_t *recursed_lookups;
-  unsigned int nesting_level_left;
-  unsigned int debug_depth;
-
-  hb_collect_glyphs_context_t (hb_face_t *face_,
-                               hb_set_t  *glyphs_before, /* OUT. May be nullptr */
-                               hb_set_t  *glyphs_input,  /* OUT. May be nullptr */
-                               hb_set_t  *glyphs_after,  /* OUT. May be nullptr */
-                               hb_set_t  *glyphs_output, /* OUT. May be nullptr */
-                               unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
-                              face (face_),
-                              before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
-                              input  (glyphs_input  ? glyphs_input  : hb_set_get_empty ()),
-                              after  (glyphs_after  ? glyphs_after  : hb_set_get_empty ()),
-                              output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
-                              recurse_func (nullptr),
-                              recursed_lookups (nullptr),
-                              nesting_level_left (nesting_level_left_),
-                              debug_depth (0)
-  {
-    recursed_lookups = hb_set_create ();
-  }
-  ~hb_collect_glyphs_context_t (void)
-  {
-    hb_set_destroy (recursed_lookups);
-  }
-
-  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
-};
-
-
-
-/* XXX Can we remove this? */
-
-template <typename set_t>
-struct hb_add_coverage_context_t :
-       hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
-{
-  inline const char *get_name (void) { return "GET_COVERAGE"; }
-  typedef const Coverage &return_t;
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
-  static return_t default_return_value (void) { return Null(Coverage); }
-  bool stop_sublookup_iteration (return_t r) const
-  {
-    r.add_coverage (set);
-    return false;
-  }
-
-  hb_add_coverage_context_t (set_t *set_) :
-                            set (set_),
-                            debug_depth (0) {}
-
-  set_t *set;
-  unsigned int debug_depth;
-};
-
-
-struct hb_ot_apply_context_t :
-       hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
-{
-  struct matcher_t
-  {
-    inline matcher_t (void) :
-             lookup_props (0),
-             ignore_zwnj (false),
-             ignore_zwj (false),
-             mask (-1),
-#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
-             syllable arg1(0),
-#undef arg1
-             match_func (nullptr),
-             match_data (nullptr) {};
-
-    typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
-
-    inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
-    inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
-    inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
-    inline void set_mask (hb_mask_t mask_) { mask = mask_; }
-    inline void set_syllable (uint8_t syllable_)  { syllable = syllable_; }
-    inline void set_match_func (match_func_t match_func_,
-                                const void *match_data_)
-    { match_func = match_func_; match_data = match_data_; }
-
-    enum may_match_t {
-      MATCH_NO,
-      MATCH_YES,
-      MATCH_MAYBE
-    };
-
-    inline may_match_t may_match (const hb_glyph_info_t &info,
-                                  const HBUINT16          *glyph_data) const
-    {
-      if (!(info.mask & mask) ||
-          (syllable && syllable != info.syllable ()))
-        return MATCH_NO;
-
-      if (match_func)
-        return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
-
-      return MATCH_MAYBE;
-    }
-
-    enum may_skip_t {
-      SKIP_NO,
-      SKIP_YES,
-      SKIP_MAYBE
-    };
-
-    inline may_skip_t
-    may_skip (const hb_ot_apply_context_t *c,
-              const hb_glyph_info_t    &info) const
-    {
-      if (!c->check_glyph_property (&info, lookup_props))
-        return SKIP_YES;
-
-      if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) &&
-                    (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
-                    (ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
-        return SKIP_MAYBE;
-
-      return SKIP_NO;
-    }
-
-    protected:
-    unsigned int lookup_props;
-    bool ignore_zwnj;
-    bool ignore_zwj;
-    hb_mask_t mask;
-    uint8_t syllable;
-    match_func_t match_func;
-    const void *match_data;
-  };
-
-  struct skipping_iterator_t
-  {
-    inline void init (hb_ot_apply_context_t *c_, bool context_match = false)
-    {
-      c = c_;
-      match_glyph_data = nullptr;
-      matcher.set_match_func (nullptr, nullptr);
-      matcher.set_lookup_props (c->lookup_props);
-      /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
-      matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj));
-      /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
-      matcher.set_ignore_zwj  (c->table_index == 1 || (context_match || c->auto_zwj));
-      matcher.set_mask (context_match ? -1 : c->lookup_mask);
-    }
-    inline void set_lookup_props (unsigned int lookup_props)
-    {
-      matcher.set_lookup_props (lookup_props);
-    }
-    inline void set_match_func (matcher_t::match_func_t match_func_,
-                                const void *match_data_,
-                                const HBUINT16 glyph_data[])
-    {
-      matcher.set_match_func (match_func_, match_data_);
-      match_glyph_data = glyph_data;
-    }
-
-    inline void reset (unsigned int start_index_,
-                       unsigned int num_items_)
-    {
-      idx = start_index_;
-      num_items = num_items_;
-      end = c->buffer->len;
-      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
-    }
-
-    inline void reject (void) { num_items++; match_glyph_data--; }
-
-    inline matcher_t::may_skip_t
-    may_skip (const hb_glyph_info_t    &info) const
-    {
-      return matcher.may_skip (c, info);
-    }
-
-    inline bool next (void)
-    {
-      assert (num_items > 0);
-      while (idx + num_items < end)
-      {
-        idx++;
-        const hb_glyph_info_t &info = c->buffer->info[idx];
-
-        matcher_t::may_skip_t skip = matcher.may_skip (c, info);
-        if (unlikely (skip == matcher_t::SKIP_YES))
-          continue;
-
-        matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
-        if (match == matcher_t::MATCH_YES ||
-            (match == matcher_t::MATCH_MAYBE &&
-             skip == matcher_t::SKIP_NO))
-        {
-          num_items--;
-          match_glyph_data++;
-          return true;
-        }
-
-        if (skip == matcher_t::SKIP_NO)
-          return false;
-      }
-      return false;
-    }
-    inline bool prev (void)
-    {
-      assert (num_items > 0);
-      while (idx >= num_items)
-      {
-        idx--;
-        const hb_glyph_info_t &info = c->buffer->out_info[idx];
-
-        matcher_t::may_skip_t skip = matcher.may_skip (c, info);
-        if (unlikely (skip == matcher_t::SKIP_YES))
-          continue;
-
-        matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
-        if (match == matcher_t::MATCH_YES ||
-            (match == matcher_t::MATCH_MAYBE &&
-             skip == matcher_t::SKIP_NO))
-        {
-          num_items--;
-          match_glyph_data++;
-          return true;
-        }
-
-        if (skip == matcher_t::SKIP_NO)
-          return false;
-      }
-      return false;
-    }
-
-    unsigned int idx;
-    protected:
-    hb_ot_apply_context_t *c;
-    matcher_t matcher;
-    const HBUINT16 *match_glyph_data;
-
-    unsigned int num_items;
-    unsigned int end;
-  };
-
-
-  inline const char *get_name (void) { return "APPLY"; }
-  typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.apply (this); }
-  static return_t default_return_value (void) { return false; }
-  bool stop_sublookup_iteration (return_t r) const { return r; }
-  return_t recurse (unsigned int sub_lookup_index)
-  {
-    if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
-      return default_return_value ();
-
-    nesting_level_left--;
-    bool ret = recurse_func (this, sub_lookup_index);
-    nesting_level_left++;
-    return ret;
-  }
-
-  skipping_iterator_t iter_input, iter_context;
-
-  hb_font_t *font;
-  hb_face_t *face;
-  hb_buffer_t *buffer;
-  recurse_func_t recurse_func;
-  const GDEF &gdef;
-  const VariationStore &var_store;
-
-  hb_direction_t direction;
-  hb_mask_t lookup_mask;
-  unsigned int table_index; /* GSUB/GPOS */
-  unsigned int lookup_index;
-  unsigned int lookup_props;
-  unsigned int nesting_level_left;
-  unsigned int debug_depth;
-
-  bool auto_zwnj;
-  bool auto_zwj;
-  bool has_glyph_classes;
-
-
-  hb_ot_apply_context_t (unsigned int table_index_,
-                      hb_font_t *font_,
-                      hb_buffer_t *buffer_) :
-                        iter_input (), iter_context (),
-                        font (font_), face (font->face), buffer (buffer_),
-                        recurse_func (nullptr),
-                        gdef (*hb_ot_layout_from_face (face)->gdef),
-                        var_store (gdef.get_var_store ()),
-                        direction (buffer_->props.direction),
-                        lookup_mask (1),
-                        table_index (table_index_),
-                        lookup_index ((unsigned int) -1),
-                        lookup_props (0),
-                        nesting_level_left (HB_MAX_NESTING_LEVEL),
-                        debug_depth (0),
-                        auto_zwnj (true),
-                        auto_zwj (true),
-                        has_glyph_classes (gdef.has_glyph_classes ()) {}
-
-  inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
-  inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
-  inline void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; }
-  inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
-  inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
-  inline void set_lookup_props (unsigned int lookup_props_)
-  {
-    lookup_props = lookup_props_;
-    iter_input.init (this, false);
-    iter_context.init (this, true);
-  }
-
-  inline bool
-  match_properties_mark (hb_codepoint_t  glyph,
-                         unsigned int    glyph_props,
-                         unsigned int    match_props) const
-  {
-    /* If using mark filtering sets, the high short of
-     * match_props has the set index.
-     */
-    if (match_props & LookupFlag::UseMarkFilteringSet)
-      return gdef.mark_set_covers (match_props >> 16, glyph);
-
-    /* The second byte of match_props has the meaning
-     * "ignore marks of attachment type different than
-     * the attachment type specified."
-     */
-    if (match_props & LookupFlag::MarkAttachmentType)
-      return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
-
-    return true;
-  }
-
-  inline bool
-  check_glyph_property (const hb_glyph_info_t *info,
-                        unsigned int  match_props) const
-  {
-    hb_codepoint_t glyph = info->codepoint;
-    unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
-
-    /* Not covered, if, for example, glyph class is ligature and
-     * match_props includes LookupFlags::IgnoreLigatures
-     */
-    if (glyph_props & match_props & LookupFlag::IgnoreFlags)
-      return false;
-
-    if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
-      return match_properties_mark (glyph, glyph_props, match_props);
-
-    return true;
-  }
-
-  inline void _set_glyph_props (hb_codepoint_t glyph_index,
-                          unsigned int class_guess = 0,
-                          bool ligature = false,
-                          bool component = false) const
-  {
-    unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
-                          HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
-    add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
-    if (ligature)
-    {
-      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
-      /* In the only place that the MULTIPLIED bit is used, Uniscribe
-       * seems to only care about the "last" transformation between
-       * Ligature and Multiple substitions.  Ie. if you ligate, expand,
-       * and ligate again, it forgives the multiplication and acts as
-       * if only ligation happened.  As such, clear MULTIPLIED bit.
-       */
-      add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
-    }
-    if (component)
-      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
-    if (likely (has_glyph_classes))
-      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
-    else if (class_guess)
-      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
-  }
-
-  inline void replace_glyph (hb_codepoint_t glyph_index) const
-  {
-    _set_glyph_props (glyph_index);
-    buffer->replace_glyph (glyph_index);
-  }
-  inline void replace_glyph_inplace (hb_codepoint_t glyph_index) const
-  {
-    _set_glyph_props (glyph_index);
-    buffer->cur().codepoint = glyph_index;
-  }
-  inline void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
-                                           unsigned int class_guess) const
-  {
-    _set_glyph_props (glyph_index, class_guess, true);
-    buffer->replace_glyph (glyph_index);
-  }
-  inline void output_glyph_for_component (hb_codepoint_t glyph_index,
-                                          unsigned int class_guess) const
-  {
-    _set_glyph_props (glyph_index, class_guess, false, true);
-    buffer->output_glyph (glyph_index);
-  }
-};
-
-
-
-typedef bool (*intersects_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
-typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
-typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
-
-struct ContextClosureFuncs
-{
-  intersects_func_t intersects;
-};
-struct ContextCollectGlyphsFuncs
-{
-  collect_glyphs_func_t collect;
-};
-struct ContextApplyFuncs
-{
-  match_func_t match;
-};
-
-
-static inline bool intersects_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
-{
-  return glyphs->has (value);
-}
-static inline bool intersects_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
-  return class_def.intersects_class (glyphs, value);
-}
-static inline bool intersects_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
-  return (data+coverage).intersects (glyphs);
-}
-
-static inline bool intersects_array (hb_closure_context_t *c,
-                                     unsigned int count,
-                                     const HBUINT16 values[],
-                                     intersects_func_t intersects_func,
-                                     const void *intersects_data)
-{
-  for (unsigned int i = 0; i < count; i++)
-    if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
-      return false;
-  return true;
-}
-
-
-static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
-{
-  glyphs->add (value);
-}
-static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
-  class_def.add_class (glyphs, value);
-}
-static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
-  (data+coverage).add_coverage (glyphs);
-}
-static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
-                                  hb_set_t *glyphs,
-                                  unsigned int count,
-                                  const HBUINT16 values[],
-                                  collect_glyphs_func_t collect_func,
-                                  const void *collect_data)
-{
-  for (unsigned int i = 0; i < count; i++)
-    collect_func (glyphs, values[i], collect_data);
-}
-
-
-static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
-{
-  return glyph_id == value;
-}
-static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
-{
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
-  return class_def.get_class (glyph_id) == value;
-}
-static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
-{
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
-  return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
-}
-
-static inline bool would_match_input (hb_would_apply_context_t *c,
-                                      unsigned int count, /* Including the first glyph (not matched) */
-                                      const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                      match_func_t match_func,
-                                      const void *match_data)
-{
-  if (count != c->len)
-    return false;
-
-  for (unsigned int i = 1; i < count; i++)
-    if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
-      return false;
-
-  return true;
-}
-static inline bool match_input (hb_ot_apply_context_t *c,
-                                unsigned int count, /* Including the first glyph (not matched) */
-                                const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                match_func_t match_func,
-                                const void *match_data,
-                                unsigned int *end_offset,
-                                unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
-                                bool *p_is_mark_ligature = nullptr,
-                                unsigned int *p_total_component_count = nullptr)
-{
-  TRACE_APPLY (nullptr);
-
-  if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
-
-  hb_buffer_t *buffer = c->buffer;
-
-  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
-  skippy_iter.reset (buffer->idx, count - 1);
-  skippy_iter.set_match_func (match_func, match_data, input);
-
-  /*
-   * This is perhaps the trickiest part of OpenType...  Remarks:
-   *
-   * - If all components of the ligature were marks, we call this a mark ligature.
-   *
-   * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
-   *   it as a ligature glyph.
-   *
-   * - Ligatures cannot be formed across glyphs attached to different components
-   *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
-   *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
-   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.
-   *   There are a couple of exceptions to this:
-   *
-   *   o If a ligature tries ligating with marks that belong to it itself, go ahead,
-   *     assuming that the font designer knows what they are doing (otherwise it can
-   *     break Indic stuff when a matra wants to ligate with a conjunct,
-   *
-   *   o If two marks want to ligate and they belong to different components of the
-   *     same ligature glyph, and said ligature glyph is to be ignored according to
-   *     mark-filtering rules, then allow.
-   *     https://github.com/harfbuzz/harfbuzz/issues/545
-   */
-
-  bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur());
-
-  unsigned int total_component_count = 0;
-  total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
-
-  unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-  unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
-
-  enum {
-    LIGBASE_NOT_CHECKED,
-    LIGBASE_MAY_NOT_SKIP,
-    LIGBASE_MAY_SKIP
-  } ligbase = LIGBASE_NOT_CHECKED;
-
-  match_positions[0] = buffer->idx;
-  for (unsigned int i = 1; i < count; i++)
-  {
-    if (!skippy_iter.next ()) return_trace (false);
-
-    match_positions[i] = skippy_iter.idx;
-
-    unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
-    unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
-
-    if (first_lig_id && first_lig_comp)
-    {
-      /* If first component was attached to a previous ligature component,
-       * all subsequent components should be attached to the same ligature
-       * component, otherwise we shouldn't ligate them... */
-      if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
-      {
-        /* ...unless, we are attached to a base ligature and that base
-         * ligature is ignorable. */
-        if (ligbase == LIGBASE_NOT_CHECKED)
-        {
-          bool found = false;
-          const hb_glyph_info_t *out = buffer->out_info;
-          unsigned int j = buffer->out_len;
-          while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
-          {
-            if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
-            {
-              j--;
-              found = true;
-              break;
-            }
-            j--;
-          }
-
-          if (found && skippy_iter.may_skip (out[j]) == hb_ot_apply_context_t::matcher_t::SKIP_YES)
-            ligbase = LIGBASE_MAY_SKIP;
-          else
-            ligbase = LIGBASE_MAY_NOT_SKIP;
-        }
-
-        if (ligbase == LIGBASE_MAY_NOT_SKIP)
-          return_trace (false);
-      }
-    }
-    else
-    {
-      /* If first component was NOT attached to a previous ligature component,
-       * all subsequent components should also NOT be attached to any ligature
-       * component, unless they are attached to the first component itself! */
-      if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
-        return_trace (false);
-    }
-
-    is_mark_ligature = is_mark_ligature && _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]);
-    total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
-  }
-
-  *end_offset = skippy_iter.idx - buffer->idx + 1;
-
-  if (p_is_mark_ligature)
-    *p_is_mark_ligature = is_mark_ligature;
-
-  if (p_total_component_count)
-    *p_total_component_count = total_component_count;
-
-  return_trace (true);
-}
-static inline bool ligate_input (hb_ot_apply_context_t *c,
-                                 unsigned int count, /* Including the first glyph */
-                                 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
-                                 unsigned int match_length,
-                                 hb_codepoint_t lig_glyph,
-                                 bool is_mark_ligature,
-                                 unsigned int total_component_count)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_buffer_t *buffer = c->buffer;
-
-  buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
-
-  /*
-   * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave
-   *   the ligature to keep its old ligature id.  This will allow it to attach to
-   *   a base ligature in GPOS.  Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
-   *   and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a
-   *   ligature id and component value of 2.  Then if SHADDA,FATHA form a ligature
-   *   later, we don't want them to lose their ligature id/component, otherwise
-   *   GPOS will fail to correctly position the mark ligature on top of the
-   *   LAM,LAM,HEH ligature.  See:
-   *     https://bugzilla.gnome.org/show_bug.cgi?id=676343
-   *
-   * - If a ligature is formed of components that some of which are also ligatures
-   *   themselves, and those ligature components had marks attached to *their*
-   *   components, we have to attach the marks to the new ligature component
-   *   positions!  Now *that*'s tricky!  And these marks may be following the
-   *   last component of the whole sequence, so we should loop forward looking
-   *   for them and update them.
-   *
-   *   Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
-   *   'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
-   *   id and component == 1.  Now, during 'liga', the LAM and the LAM-HEH ligature
-   *   form a LAM-LAM-HEH ligature.  We need to reassign the SHADDA and FATHA to
-   *   the new ligature with a component value of 2.
-   *
-   *   This in fact happened to a font...  See:
-   *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
-   */
-
-  unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
-  unsigned int lig_id = is_mark_ligature ? 0 : _hb_allocate_lig_id (buffer);
-  unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-  unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
-  unsigned int components_so_far = last_num_components;
-
-  if (!is_mark_ligature)
-  {
-    _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
-    if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
-    {
-      _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
-    }
-  }
-  c->replace_glyph_with_ligature (lig_glyph, klass);
-
-  for (unsigned int i = 1; i < count; i++)
-  {
-    while (buffer->idx < match_positions[i] && buffer->successful)
-    {
-      if (!is_mark_ligature) {
-        unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
-        if (this_comp == 0)
-          this_comp = last_num_components;
-        unsigned int new_lig_comp = components_so_far - last_num_components +
-                                    MIN (this_comp, last_num_components);
-          _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
-      }
-      buffer->next_glyph ();
-    }
-
-    last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-    last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
-    components_so_far += last_num_components;
-
-    /* Skip the base glyph */
-    buffer->idx++;
-  }
-
-  if (!is_mark_ligature && last_lig_id) {
-    /* Re-adjust components for any marks following. */
-    for (unsigned int i = buffer->idx; i < buffer->len; i++) {
-      if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
-        unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
-        if (!this_comp)
-          break;
-        unsigned int new_lig_comp = components_so_far - last_num_components +
-                                    MIN (this_comp, last_num_components);
-        _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
-      } else
-        break;
-    }
-  }
-  return_trace (true);
-}
-
-static inline bool match_backtrack (hb_ot_apply_context_t *c,
-                                    unsigned int count,
-                                    const HBUINT16 backtrack[],
-                                    match_func_t match_func,
-                                    const void *match_data,
-                                    unsigned int *match_start)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
-  skippy_iter.reset (c->buffer->backtrack_len (), count);
-  skippy_iter.set_match_func (match_func, match_data, backtrack);
-
-  for (unsigned int i = 0; i < count; i++)
-    if (!skippy_iter.prev ())
-      return_trace (false);
-
-  *match_start = skippy_iter.idx;
-
-  return_trace (true);
-}
-
-static inline bool match_lookahead (hb_ot_apply_context_t *c,
-                                    unsigned int count,
-                                    const HBUINT16 lookahead[],
-                                    match_func_t match_func,
-                                    const void *match_data,
-                                    unsigned int offset,
-                                    unsigned int *end_index)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
-  skippy_iter.reset (c->buffer->idx + offset - 1, count);
-  skippy_iter.set_match_func (match_func, match_data, lookahead);
-
-  for (unsigned int i = 0; i < count; i++)
-    if (!skippy_iter.next ())
-      return_trace (false);
-
-  *end_index = skippy_iter.idx + 1;
-
-  return_trace (true);
-}
-
-
-
-struct LookupRecord
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  HBUINT16      sequenceIndex;          /* Index into current glyph
-                                         * sequence--first glyph = 0 */
-  HBUINT16      lookupListIndex;        /* Lookup to apply to that
-                                         * position--zero--based */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-
-template <typename context_t>
-static inline void recurse_lookups (context_t *c,
-                                    unsigned int lookupCount,
-                                    const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
-{
-  for (unsigned int i = 0; i < lookupCount; i++)
-    c->recurse (lookupRecord[i].lookupListIndex);
-}
-
-static inline bool apply_lookup (hb_ot_apply_context_t *c,
-                                 unsigned int count, /* Including the first glyph */
-                                 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
-                                 unsigned int lookupCount,
-                                 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
-                                 unsigned int match_length)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_buffer_t *buffer = c->buffer;
-  int end;
-
-  /* All positions are distance from beginning of *output* buffer.
-   * Adjust. */
-  {
-    unsigned int bl = buffer->backtrack_len ();
-    end = bl + match_length;
-
-    int delta = bl - buffer->idx;
-    /* Convert positions to new indexing. */
-    for (unsigned int j = 0; j < count; j++)
-      match_positions[j] += delta;
-  }
-
-  for (unsigned int i = 0; i < lookupCount && buffer->successful; i++)
-  {
-    unsigned int idx = lookupRecord[i].sequenceIndex;
-    if (idx >= count)
-      continue;
-
-    /* Don't recurse to ourself at same position.
-     * Note that this test is too naive, it doesn't catch longer loops. */
-    if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
-      continue;
-
-    if (unlikely (!buffer->move_to (match_positions[idx])))
-      break;
-
-    if (unlikely (buffer->max_ops <= 0))
-      break;
-
-    unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
-    if (!c->recurse (lookupRecord[i].lookupListIndex))
-      continue;
-
-    unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
-    int delta = new_len - orig_len;
-
-    if (!delta)
-        continue;
-
-    /* Recursed lookup changed buffer len.  Adjust.
-     *
-     * TODO:
-     *
-     * Right now, if buffer length increased by n, we assume n new glyphs
-     * were added right after the current position, and if buffer length
-     * was decreased by n, we assume n match positions after the current
-     * one where removed.  The former (buffer length increased) case is
-     * fine, but the decrease case can be improved in at least two ways,
-     * both of which are significant:
-     *
-     *   - If recursed-to lookup is MultipleSubst and buffer length
-     *     decreased, then it's current match position that was deleted,
-     *     NOT the one after it.
-     *
-     *   - If buffer length was decreased by n, it does not necessarily
-     *     mean that n match positions where removed, as there might
-     *     have been marks and default-ignorables in the sequence.  We
-     *     should instead drop match positions between current-position
-     *     and current-position + n instead.
-     *
-     * It should be possible to construct tests for both of these cases.
-     */
-
-    end += delta;
-    if (end <= int (match_positions[idx]))
-    {
-      /* End might end up being smaller than match_positions[idx] if the recursed
-       * lookup ended up removing many items, more than we have had matched.
-       * Just never rewind end back and get out of here.
-       * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
-      end = match_positions[idx];
-      /* There can't be any further changes. */
-      break;
-    }
-
-    unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
-
-    if (delta > 0)
-    {
-      if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
-        break;
-    }
-    else
-    {
-      /* NOTE: delta is negative. */
-      delta = MAX (delta, (int) next - (int) count);
-      next -= delta;
-    }
-
-    /* Shift! */
-    memmove (match_positions + next + delta, match_positions + next,
-             (count - next) * sizeof (match_positions[0]));
-    next += delta;
-    count += delta;
-
-    /* Fill in new entries. */
-    for (unsigned int j = idx + 1; j < next; j++)
-      match_positions[j] = match_positions[j - 1] + 1;
-
-    /* And fixup the rest. */
-    for (; next < count; next++)
-      match_positions[next] += delta;
-  }
-
-  buffer->move_to (end);
-
-  return_trace (true);
-}
-
-
-
-/* Contextual lookups */
-
-struct ContextClosureLookupContext
-{
-  ContextClosureFuncs funcs;
-  const void *intersects_data;
-};
-
-struct ContextCollectGlyphsLookupContext
-{
-  ContextCollectGlyphsFuncs funcs;
-  const void *collect_data;
-};
-
-struct ContextApplyLookupContext
-{
-  ContextApplyFuncs funcs;
-  const void *match_data;
-};
-
-static inline void context_closure_lookup (hb_closure_context_t *c,
-                                           unsigned int inputCount, /* Including the first glyph (not matched) */
-                                           const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                           unsigned int lookupCount,
-                                           const LookupRecord lookupRecord[],
-                                           ContextClosureLookupContext &lookup_context)
-{
-  if (intersects_array (c,
-                        inputCount ? inputCount - 1 : 0, input,
-                        lookup_context.funcs.intersects, lookup_context.intersects_data))
-    recurse_lookups (c,
-                     lookupCount, lookupRecord);
-}
-
-static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
-                                                  unsigned int inputCount, /* Including the first glyph (not matched) */
-                                                  const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                                  unsigned int lookupCount,
-                                                  const LookupRecord lookupRecord[],
-                                                  ContextCollectGlyphsLookupContext &lookup_context)
-{
-  collect_array (c, c->input,
-                 inputCount ? inputCount - 1 : 0, input,
-                 lookup_context.funcs.collect, lookup_context.collect_data);
-  recurse_lookups (c,
-                   lookupCount, lookupRecord);
-}
-
-static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
-                                               unsigned int inputCount, /* Including the first glyph (not matched) */
-                                               const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                               unsigned int lookupCount HB_UNUSED,
-                                               const LookupRecord lookupRecord[] HB_UNUSED,
-                                               ContextApplyLookupContext &lookup_context)
-{
-  return would_match_input (c,
-                            inputCount, input,
-                            lookup_context.funcs.match, lookup_context.match_data);
-}
-static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
-                                         unsigned int inputCount, /* Including the first glyph (not matched) */
-                                         const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                         unsigned int lookupCount,
-                                         const LookupRecord lookupRecord[],
-                                         ContextApplyLookupContext &lookup_context)
-{
-  unsigned int match_length = 0;
-  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
-  return match_input (c,
-                      inputCount, input,
-                      lookup_context.funcs.match, lookup_context.match_data,
-                      &match_length, match_positions)
-      && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length),
-          apply_lookup (c,
-                       inputCount, match_positions,
-                       lookupCount, lookupRecord,
-                       match_length));
-}
-
-struct Rule
-{
-  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    context_closure_lookup (c,
-                            inputCount, inputZ,
-                            lookupCount, lookupRecord,
-                            lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    context_collect_glyphs_lookup (c,
-                                   inputCount, inputZ,
-                                   lookupCount, lookupRecord,
-                                   lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    return_trace (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    return_trace (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
-  }
-
-  public:
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (inputCount.sanitize (c) &&
-                  lookupCount.sanitize (c) &&
-                  c->check_range (inputZ,
-                                  inputZ[0].static_size * inputCount +
-                                  LookupRecord::static_size * lookupCount));
-  }
-
-  protected:
-  HBUINT16      inputCount;             /* Total number of glyphs in input
-                                         * glyph sequence--includes the first
-                                         * glyph */
-  HBUINT16      lookupCount;            /* Number of LookupRecords */
-  HBUINT16      inputZ[VAR];            /* Array of match inputs--start with
-                                         * second glyph */
-/*LookupRecord  lookupRecordX[VAR];*/   /* Array of LookupRecords--in
-                                         * design order */
-  public:
-  DEFINE_SIZE_ARRAY (4, inputZ);
-};
-
-struct RuleSet
-{
-  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).closure (c, lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-    {
-      if ((this+rule[i]).would_apply (c, lookup_context))
-        return_trace (true);
-    }
-    return_trace (false);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-    {
-      if ((this+rule[i]).apply (c, lookup_context))
-        return_trace (true);
-    }
-    return_trace (false);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rule.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<Rule>
-                rule;                   /* Array of Rule tables
-                                         * ordered by preference */
-  public:
-  DEFINE_SIZE_ARRAY (2, rule);
-};
-
-
-struct ContextFormat1
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-
-    const Coverage &cov = (this+coverage);
-
-    struct ContextClosureLookupContext lookup_context = {
-      {intersects_glyph},
-      nullptr
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (cov.intersects_coverage (c->glyphs, i)) {
-        const RuleSet &rule_set = this+ruleSet[i];
-        rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    struct ContextCollectGlyphsLookupContext lookup_context = {
-      {collect_glyph},
-      nullptr
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      nullptr
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED))
-      return_trace (false);
-
-    const RuleSet &rule_set = this+ruleSet[index];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      nullptr
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16      format;                 /* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-                coverage;               /* Offset to Coverage table--from
-                                         * beginning of table */
-  OffsetArrayOf<RuleSet>
-                ruleSet;                /* Array of RuleSet tables
-                                         * ordered by Coverage Index */
-  public:
-  DEFINE_SIZE_ARRAY (6, ruleSet);
-};
-
-
-struct ContextFormat2
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    if (!(this+coverage).intersects (c->glyphs))
-      return;
-
-    const ClassDef &class_def = this+classDef;
-
-    struct ContextClosureLookupContext lookup_context = {
-      {intersects_class},
-      &class_def
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (class_def.intersects_class (c->glyphs, i)) {
-        const RuleSet &rule_set = this+ruleSet[i];
-        rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    const ClassDef &class_def = this+classDef;
-    struct ContextCollectGlyphsLookupContext lookup_context = {
-      {collect_class},
-      &class_def
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const ClassDef &class_def = this+classDef;
-    unsigned int index = class_def.get_class (c->glyphs[0]);
-    const RuleSet &rule_set = this+ruleSet[index];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_class},
-      &class_def
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const ClassDef &class_def = this+classDef;
-    index = class_def.get_class (c->buffer->cur().codepoint);
-    const RuleSet &rule_set = this+ruleSet[index];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_class},
-      &class_def
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16      format;                 /* Format identifier--format = 2 */
-  OffsetTo<Coverage>
-                coverage;               /* Offset to Coverage table--from
-                                         * beginning of table */
-  OffsetTo<ClassDef>
-                classDef;               /* Offset to glyph ClassDef table--from
-                                         * beginning of table */
-  OffsetArrayOf<RuleSet>
-                ruleSet;                /* Array of RuleSet tables
-                                         * ordered by class */
-  public:
-  DEFINE_SIZE_ARRAY (8, ruleSet);
-};
-
-
-struct ContextFormat3
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    if (!(this+coverageZ[0]).intersects (c->glyphs))
-      return;
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextClosureLookupContext lookup_context = {
-      {intersects_coverage},
-      this
-    };
-    context_closure_lookup (c,
-                            glyphCount, (const HBUINT16 *) (coverageZ + 1),
-                            lookupCount, lookupRecord,
-                            lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverageZ[0]).add_coverage (c->input);
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextCollectGlyphsLookupContext lookup_context = {
-      {collect_coverage},
-      this
-    };
-
-    context_collect_glyphs_lookup (c,
-                                   glyphCount, (const HBUINT16 *) (coverageZ + 1),
-                                   lookupCount, lookupRecord,
-                                   lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      this
-    };
-    return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverageZ[0];
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      this
-    };
-    return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!c->check_struct (this)) return_trace (false);
-    unsigned int count = glyphCount;
-    if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
-    if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (!coverageZ[i].sanitize (c, this)) return_trace (false);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
-    return_trace (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
-  }
-
-  protected:
-  HBUINT16      format;                 /* Format identifier--format = 3 */
-  HBUINT16      glyphCount;             /* Number of glyphs in the input glyph
-                                         * sequence */
-  HBUINT16      lookupCount;            /* Number of LookupRecords */
-  OffsetTo<Coverage>
-                coverageZ[VAR];         /* Array of offsets to Coverage
-                                         * table in glyph sequence order */
-/*LookupRecord  lookupRecordX[VAR];*/   /* Array of LookupRecords--in
-                                         * design order */
-  public:
-  DEFINE_SIZE_ARRAY (6, coverageZ);
-};
-
-struct Context
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-    switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
-    case 2: return_trace (c->dispatch (u.format2));
-    case 3: return_trace (c->dispatch (u.format3));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16              format;         /* Format identifier */
-  ContextFormat1        format1;
-  ContextFormat2        format2;
-  ContextFormat3        format3;
-  } u;
-};
-
-
-/* Chaining Contextual lookups */
-
-struct ChainContextClosureLookupContext
-{
-  ContextClosureFuncs funcs;
-  const void *intersects_data[3];
-};
-
-struct ChainContextCollectGlyphsLookupContext
-{
-  ContextCollectGlyphsFuncs funcs;
-  const void *collect_data[3];
-};
-
-struct ChainContextApplyLookupContext
-{
-  ContextApplyFuncs funcs;
-  const void *match_data[3];
-};
-
-static inline void chain_context_closure_lookup (hb_closure_context_t *c,
-                                                 unsigned int backtrackCount,
-                                                 const HBUINT16 backtrack[],
-                                                 unsigned int inputCount, /* Including the first glyph (not matched) */
-                                                 const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                                 unsigned int lookaheadCount,
-                                                 const HBUINT16 lookahead[],
-                                                 unsigned int lookupCount,
-                                                 const LookupRecord lookupRecord[],
-                                                 ChainContextClosureLookupContext &lookup_context)
-{
-  if (intersects_array (c,
-                        backtrackCount, backtrack,
-                        lookup_context.funcs.intersects, lookup_context.intersects_data[0])
-   && intersects_array (c,
-                        inputCount ? inputCount - 1 : 0, input,
-                        lookup_context.funcs.intersects, lookup_context.intersects_data[1])
-   && intersects_array (c,
-                       lookaheadCount, lookahead,
-                       lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
-    recurse_lookups (c,
-                     lookupCount, lookupRecord);
-}
-
-static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
-                                                        unsigned int backtrackCount,
-                                                        const HBUINT16 backtrack[],
-                                                        unsigned int inputCount, /* Including the first glyph (not matched) */
-                                                        const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                                        unsigned int lookaheadCount,
-                                                        const HBUINT16 lookahead[],
-                                                        unsigned int lookupCount,
-                                                        const LookupRecord lookupRecord[],
-                                                        ChainContextCollectGlyphsLookupContext &lookup_context)
-{
-  collect_array (c, c->before,
-                 backtrackCount, backtrack,
-                 lookup_context.funcs.collect, lookup_context.collect_data[0]);
-  collect_array (c, c->input,
-                 inputCount ? inputCount - 1 : 0, input,
-                 lookup_context.funcs.collect, lookup_context.collect_data[1]);
-  collect_array (c, c->after,
-                 lookaheadCount, lookahead,
-                 lookup_context.funcs.collect, lookup_context.collect_data[2]);
-  recurse_lookups (c,
-                   lookupCount, lookupRecord);
-}
-
-static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
-                                                     unsigned int backtrackCount,
-                                                     const HBUINT16 backtrack[] HB_UNUSED,
-                                                     unsigned int inputCount, /* Including the first glyph (not matched) */
-                                                     const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                                     unsigned int lookaheadCount,
-                                                     const HBUINT16 lookahead[] HB_UNUSED,
-                                                     unsigned int lookupCount HB_UNUSED,
-                                                     const LookupRecord lookupRecord[] HB_UNUSED,
-                                                     ChainContextApplyLookupContext &lookup_context)
-{
-  return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
-      && would_match_input (c,
-                            inputCount, input,
-                            lookup_context.funcs.match, lookup_context.match_data[1]);
-}
-
-static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
-                                               unsigned int backtrackCount,
-                                               const HBUINT16 backtrack[],
-                                               unsigned int inputCount, /* Including the first glyph (not matched) */
-                                               const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                               unsigned int lookaheadCount,
-                                               const HBUINT16 lookahead[],
-                                               unsigned int lookupCount,
-                                               const LookupRecord lookupRecord[],
-                                               ChainContextApplyLookupContext &lookup_context)
-{
-  unsigned int start_index = 0, match_length = 0, end_index = 0;
-  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
-  return match_input (c,
-                      inputCount, input,
-                      lookup_context.funcs.match, lookup_context.match_data[1],
-                      &match_length, match_positions)
-      && match_backtrack (c,
-                          backtrackCount, backtrack,
-                          lookup_context.funcs.match, lookup_context.match_data[0],
-                          &start_index)
-      && match_lookahead (c,
-                          lookaheadCount, lookahead,
-                          lookup_context.funcs.match, lookup_context.match_data[2],
-                          match_length, &end_index)
-      && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index),
-          apply_lookup (c,
-                       inputCount, match_positions,
-                       lookupCount, lookupRecord,
-                       match_length));
-}
-
-struct ChainRule
-{
-  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    chain_context_closure_lookup (c,
-                                  backtrack.len, backtrack.arrayZ,
-                                  input.len, input.arrayZ,
-                                  lookahead.len, lookahead.arrayZ,
-                                  lookup.len, lookup.arrayZ,
-                                  lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    chain_context_collect_glyphs_lookup (c,
-                                         backtrack.len, backtrack.arrayZ,
-                                         input.len, input.arrayZ,
-                                         lookahead.len, lookahead.arrayZ,
-                                         lookup.len, lookup.arrayZ,
-                                         lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (chain_context_would_apply_lookup (c,
-                                                    backtrack.len, backtrack.arrayZ,
-                                                    input.len, input.arrayZ,
-                                                    lookahead.len, lookahead.arrayZ, lookup.len,
-                                                    lookup.arrayZ, lookup_context));
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (chain_context_apply_lookup (c,
-                                              backtrack.len, backtrack.arrayZ,
-                                              input.len, input.arrayZ,
-                                              lookahead.len, lookahead.arrayZ, lookup.len,
-                                              lookup.arrayZ, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!backtrack.sanitize (c)) return_trace (false);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    if (!input.sanitize (c)) return_trace (false);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    if (!lookahead.sanitize (c)) return_trace (false);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (lookup.sanitize (c));
-  }
-
-  protected:
-  ArrayOf<HBUINT16>
-                backtrack;              /* Array of backtracking values
-                                         * (to be matched before the input
-                                         * sequence) */
-  HeadlessArrayOf<HBUINT16>
-                inputX;                 /* Array of input values (start with
-                                         * second glyph) */
-  ArrayOf<HBUINT16>
-                lookaheadX;             /* Array of lookahead values's (to be
-                                         * matched after the input sequence) */
-  ArrayOf<LookupRecord>
-                lookupX;                /* Array of LookupRecords--in
-                                         * design order) */
-  public:
-  DEFINE_SIZE_MIN (8);
-};
-
-struct ChainRuleSet
-{
-  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).closure (c, lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      if ((this+rule[i]).would_apply (c, lookup_context))
-        return_trace (true);
-
-    return_trace (false);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      if ((this+rule[i]).apply (c, lookup_context))
-        return_trace (true);
-
-    return_trace (false);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rule.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<ChainRule>
-                rule;                   /* Array of ChainRule tables
-                                         * ordered by preference */
-  public:
-  DEFINE_SIZE_ARRAY (2, rule);
-};
-
-struct ChainContextFormat1
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    const Coverage &cov = (this+coverage);
-
-    struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (cov.intersects_coverage (c->glyphs, i)) {
-        const ChainRuleSet &rule_set = this+ruleSet[i];
-        rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    struct ChainContextCollectGlyphsLookupContext lookup_context = {
-      {collect_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const ChainRuleSet &rule_set = this+ruleSet[index];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16      format;                 /* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-                coverage;               /* Offset to Coverage table--from
-                                         * beginning of table */
-  OffsetArrayOf<ChainRuleSet>
-                ruleSet;                /* Array of ChainRuleSet tables
-                                         * ordered by Coverage Index */
-  public:
-  DEFINE_SIZE_ARRAY (6, ruleSet);
-};
-
-struct ChainContextFormat2
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    if (!(this+coverage).intersects (c->glyphs))
-      return;
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (input_class_def.intersects_class (c->glyphs, i)) {
-        const ChainRuleSet &rule_set = this+ruleSet[i];
-        rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    struct ChainContextCollectGlyphsLookupContext lookup_context = {
-      {collect_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    unsigned int index = input_class_def.get_class (c->glyphs[0]);
-    const ChainRuleSet &rule_set = this+ruleSet[index];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    index = input_class_def.get_class (c->buffer->cur().codepoint);
-    const ChainRuleSet &rule_set = this+ruleSet[index];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) &&
-                  backtrackClassDef.sanitize (c, this) &&
-                  inputClassDef.sanitize (c, this) &&
-                  lookaheadClassDef.sanitize (c, this) &&
-                  ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16      format;                 /* Format identifier--format = 2 */
-  OffsetTo<Coverage>
-                coverage;               /* Offset to Coverage table--from
-                                         * beginning of table */
-  OffsetTo<ClassDef>
-                backtrackClassDef;      /* Offset to glyph ClassDef table
-                                         * containing backtrack sequence
-                                         * data--from beginning of table */
-  OffsetTo<ClassDef>
-                inputClassDef;          /* Offset to glyph ClassDef
-                                         * table containing input sequence
-                                         * data--from beginning of table */
-  OffsetTo<ClassDef>
-                lookaheadClassDef;      /* Offset to glyph ClassDef table
-                                         * containing lookahead sequence
-                                         * data--from beginning of table */
-  OffsetArrayOf<ChainRuleSet>
-                ruleSet;                /* Array of ChainRuleSet tables
-                                         * ordered by class */
-  public:
-  DEFINE_SIZE_ARRAY (12, ruleSet);
-};
-
-struct ChainContextFormat3
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-
-    if (!(this+input[0]).intersects (c->glyphs))
-      return;
-
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_coverage},
-      {this, this, this}
-    };
-    chain_context_closure_lookup (c,
-                                  backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
-                                  input.len, (const HBUINT16 *) input.arrayZ + 1,
-                                  lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
-                                  lookup.len, lookup.arrayZ,
-                                  lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-
-    (this+input[0]).add_coverage (c->input);
-
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextCollectGlyphsLookupContext lookup_context = {
-      {collect_coverage},
-      {this, this, this}
-    };
-    chain_context_collect_glyphs_lookup (c,
-                                         backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
-                                         input.len, (const HBUINT16 *) input.arrayZ + 1,
-                                         lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
-                                         lookup.len, lookup.arrayZ,
-                                         lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      {this, this, this}
-    };
-    return_trace (chain_context_would_apply_lookup (c,
-                                                    backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
-                                                    input.len, (const HBUINT16 *) input.arrayZ + 1,
-                                                    lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
-                                                    lookup.len, lookup.arrayZ, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    return this+input[0];
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-
-    unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      {this, this, this}
-    };
-    return_trace (chain_context_apply_lookup (c,
-                                              backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
-                                              input.len, (const HBUINT16 *) input.arrayZ + 1,
-                                              lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
-                                              lookup.len, lookup.arrayZ, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!backtrack.sanitize (c, this)) return_trace (false);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    if (!input.sanitize (c, this)) return_trace (false);
-    if (!input.len) return_trace (false); /* To be consistent with Context. */
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    if (!lookahead.sanitize (c, this)) return_trace (false);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (lookup.sanitize (c));
-  }
-
-  protected:
-  HBUINT16      format;                 /* Format identifier--format = 3 */
-  OffsetArrayOf<Coverage>
-                backtrack;              /* Array of coverage tables
-                                         * in backtracking sequence, in  glyph
-                                         * sequence order */
-  OffsetArrayOf<Coverage>
-                inputX          ;       /* Array of coverage
-                                         * tables in input sequence, in glyph
-                                         * sequence order */
-  OffsetArrayOf<Coverage>
-                lookaheadX;             /* Array of coverage tables
-                                         * in lookahead sequence, in glyph
-                                         * sequence order */
-  ArrayOf<LookupRecord>
-                lookupX;                /* Array of LookupRecords--in
-                                         * design order) */
-  public:
-  DEFINE_SIZE_MIN (10);
-};
-
-struct ChainContext
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-    switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
-    case 2: return_trace (c->dispatch (u.format2));
-    case 3: return_trace (c->dispatch (u.format3));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16              format; /* Format identifier */
-  ChainContextFormat1   format1;
-  ChainContextFormat2   format2;
-  ChainContextFormat3   format3;
-  } u;
-};
-
-
-template <typename T>
-struct ExtensionFormat1
-{
-  inline unsigned int get_type (void) const { return extensionLookupType; }
-
-  template <typename X>
-  inline const X& get_subtable (void) const
-  {
-    unsigned int offset = extensionOffset;
-    if (unlikely (!offset)) return Null(typename T::LookupSubTable);
-    return StructAtOffset<typename T::LookupSubTable> (this, offset);
-  }
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, format);
-    if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
-    return_trace (get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ()));
-  }
-
-  /* This is called from may_dispatch() above with hb_sanitize_context_t. */
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  extensionOffset != 0 &&
-                  extensionLookupType != T::LookupSubTable::Extension);
-  }
-
-  protected:
-  HBUINT16      format;                 /* Format identifier. Set to 1. */
-  HBUINT16      extensionLookupType;    /* Lookup type of subtable referenced
-                                         * by ExtensionOffset (i.e. the
-                                         * extension subtable). */
-  HBUINT32      extensionOffset;        /* Offset to the extension subtable,
-                                         * of lookup type subtable. */
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-template <typename T>
-struct Extension
-{
-  inline unsigned int get_type (void) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.get_type ();
-    default:return 0;
-    }
-  }
-  template <typename X>
-  inline const X& get_subtable (void) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.template get_subtable<typename T::LookupSubTable> ();
-    default:return Null(typename T::LookupSubTable);
-    }
-  }
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-    switch (u.format) {
-    case 1: return_trace (u.format1.dispatch (c));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16              format;         /* Format identifier */
-  ExtensionFormat1<T>   format1;
-  } u;
-};
-
-
-/*
- * GSUB/GPOS Common
- */
-
-struct GSUBGPOS
-{
-  inline unsigned int get_script_count (void) const
-  { return (this+scriptList).len; }
-  inline const Tag& get_script_tag (unsigned int i) const
-  { return (this+scriptList).get_tag (i); }
-  inline unsigned int get_script_tags (unsigned int start_offset,
-                                       unsigned int *script_count /* IN/OUT */,
-                                       hb_tag_t     *script_tags /* OUT */) const
-  { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
-  inline const Script& get_script (unsigned int i) const
-  { return (this+scriptList)[i]; }
-  inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
-  { return (this+scriptList).find_index (tag, index); }
-
-  inline unsigned int get_feature_count (void) const
-  { return (this+featureList).len; }
-  inline hb_tag_t get_feature_tag (unsigned int i) const
-  { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
-  inline unsigned int get_feature_tags (unsigned int start_offset,
-                                        unsigned int *feature_count /* IN/OUT */,
-                                        hb_tag_t     *feature_tags /* OUT */) const
-  { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
-  inline const Feature& get_feature (unsigned int i) const
-  { return (this+featureList)[i]; }
-  inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
-  { return (this+featureList).find_index (tag, index); }
-
-  inline unsigned int get_lookup_count (void) const
-  { return (this+lookupList).len; }
-  inline const Lookup& get_lookup (unsigned int i) const
-  { return (this+lookupList)[i]; }
-
-  inline bool find_variations_index (const int *coords, unsigned int num_coords,
-                                     unsigned int *index) const
-  { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
-           .find_index (coords, num_coords, index); }
-  inline const Feature& get_feature_variation (unsigned int feature_index,
-                                               unsigned int variations_index) const
-  {
-    if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
-        version.to_int () >= 0x00010001u)
-    {
-      const Feature *feature = (this+featureVars).find_substitute (variations_index,
-                                                                   feature_index);
-      if (feature)
-        return *feature;
-    }
-    return get_feature (feature_index);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-                  likely (version.major == 1) &&
-                  scriptList.sanitize (c, this) &&
-                  featureList.sanitize (c, this) &&
-                  lookupList.sanitize (c, this) &&
-                  (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
-  }
-
-  protected:
-  FixedVersion<>version;        /* Version of the GSUB/GPOS table--initially set
-                                 * to 0x00010000u */
-  OffsetTo<ScriptList>
-                scriptList;     /* ScriptList table */
-  OffsetTo<FeatureList>
-                featureList;    /* FeatureList table */
-  OffsetTo<LookupList>
-                lookupList;     /* LookupList table */
-  LOffsetTo<FeatureVariations>
-                featureVars;    /* Offset to Feature Variations
-                                   table--from beginning of table
-                                 * (may be NULL).  Introduced
-                                 * in version 0x00010001. */
-  public:
-  DEFINE_SIZE_MIN (10);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsubgpos.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,2779 @@
+/*
+ * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
+ * Copyright © 2010,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): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_LAYOUT_GSUBGPOS_HH
+#define HB_OT_LAYOUT_GSUBGPOS_HH
+
+#include "hb.hh"
+#include "hb-buffer.hh"
+#include "hb-map.hh"
+#include "hb-set.hh"
+#include "hb-ot-map.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-ot-layout-gdef-table.hh"
+
+
+namespace OT {
+
+
+struct hb_intersects_context_t :
+       hb_dispatch_context_t<hb_intersects_context_t, bool, 0>
+{
+  const char *get_name () { return "INTERSECTS"; }
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.intersects (this->glyphs); }
+  static return_t default_return_value () { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+
+  const hb_set_t *glyphs;
+  unsigned int debug_depth;
+
+  hb_intersects_context_t (const hb_set_t *glyphs_) :
+                             glyphs (glyphs_),
+                             debug_depth (0) {}
+};
+
+struct hb_closure_context_t :
+       hb_dispatch_context_t<hb_closure_context_t, hb_void_t, 0>
+{
+  const char *get_name () { return "CLOSURE"; }
+  typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
+  template <typename T>
+  return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
+  static return_t default_return_value () { return HB_VOID; }
+  void recurse (unsigned int lookup_index)
+  {
+    if (unlikely (nesting_level_left == 0 || !recurse_func))
+      return;
+
+    nesting_level_left--;
+    recurse_func (this, lookup_index);
+    nesting_level_left++;
+  }
+
+  bool should_visit_lookup (unsigned int lookup_index)
+  {
+    if (is_lookup_done (lookup_index))
+      return false;
+    done_lookups->set (lookup_index, glyphs->get_population ());
+    return true;
+  }
+
+  bool is_lookup_done (unsigned int lookup_index)
+  {
+    /* Have we visited this lookup with the current set of glyphs? */
+    return done_lookups->get (lookup_index) == glyphs->get_population ();
+  }
+
+  hb_face_t *face;
+  hb_set_t *glyphs;
+  hb_set_t out[1];
+  recurse_func_t recurse_func;
+  unsigned int nesting_level_left;
+  unsigned int debug_depth;
+
+  hb_closure_context_t (hb_face_t *face_,
+                        hb_set_t *glyphs_,
+                        hb_map_t *done_lookups_,
+                        unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
+                          face (face_),
+                          glyphs (glyphs_),
+                          recurse_func (nullptr),
+                          nesting_level_left (nesting_level_left_),
+                          debug_depth (0),
+                          done_lookups (done_lookups_) {}
+
+  ~hb_closure_context_t () { flush (); }
+
+  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
+
+  void flush ()
+  {
+    hb_set_union (glyphs, out);
+    hb_set_clear (out);
+  }
+
+  private:
+  hb_map_t *done_lookups;
+};
+
+
+struct hb_would_apply_context_t :
+       hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY>
+{
+  const char *get_name () { return "WOULD_APPLY"; }
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.would_apply (this); }
+  static return_t default_return_value () { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+
+  hb_face_t *face;
+  const hb_codepoint_t *glyphs;
+  unsigned int len;
+  bool zero_context;
+  unsigned int debug_depth;
+
+  hb_would_apply_context_t (hb_face_t *face_,
+                            const hb_codepoint_t *glyphs_,
+                            unsigned int len_,
+                            bool zero_context_) :
+                              face (face_),
+                              glyphs (glyphs_),
+                              len (len_),
+                              zero_context (zero_context_),
+                              debug_depth (0) {}
+};
+
+
+struct hb_collect_glyphs_context_t :
+       hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, 0>
+{
+  const char *get_name () { return "COLLECT_GLYPHS"; }
+  typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
+  template <typename T>
+  return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
+  static return_t default_return_value () { return HB_VOID; }
+  void recurse (unsigned int lookup_index)
+  {
+    if (unlikely (nesting_level_left == 0 || !recurse_func))
+      return;
+
+    /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get
+     * past the previous check.  For GSUB, we only want to collect the output
+     * glyphs in the recursion.  If output is not requested, we can go home now.
+     *
+     * Note further, that the above is not exactly correct.  A recursed lookup
+     * is allowed to match input that is not matched in the context, but that's
+     * not how most fonts are built.  It's possible to relax that and recurse
+     * with all sets here if it proves to be an issue.
+     */
+
+    if (output == hb_set_get_empty ())
+      return;
+
+    /* Return if new lookup was recursed to before. */
+    if (recursed_lookups->has (lookup_index))
+      return;
+
+    hb_set_t *old_before = before;
+    hb_set_t *old_input  = input;
+    hb_set_t *old_after  = after;
+    before = input = after = hb_set_get_empty ();
+
+    nesting_level_left--;
+    recurse_func (this, lookup_index);
+    nesting_level_left++;
+
+    before = old_before;
+    input  = old_input;
+    after  = old_after;
+
+    recursed_lookups->add (lookup_index);
+  }
+
+  hb_face_t *face;
+  hb_set_t *before;
+  hb_set_t *input;
+  hb_set_t *after;
+  hb_set_t *output;
+  recurse_func_t recurse_func;
+  hb_set_t *recursed_lookups;
+  unsigned int nesting_level_left;
+  unsigned int debug_depth;
+
+  hb_collect_glyphs_context_t (hb_face_t *face_,
+                               hb_set_t  *glyphs_before, /* OUT.  May be NULL */
+                               hb_set_t  *glyphs_input,  /* OUT.  May be NULL */
+                               hb_set_t  *glyphs_after,  /* OUT.  May be NULL */
+                               hb_set_t  *glyphs_output, /* OUT.  May be NULL */
+                               unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
+                              face (face_),
+                              before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
+                              input  (glyphs_input  ? glyphs_input  : hb_set_get_empty ()),
+                              after  (glyphs_after  ? glyphs_after  : hb_set_get_empty ()),
+                              output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
+                              recurse_func (nullptr),
+                              recursed_lookups (hb_set_create ()),
+                              nesting_level_left (nesting_level_left_),
+                              debug_depth (0) {}
+  ~hb_collect_glyphs_context_t () { hb_set_destroy (recursed_lookups); }
+
+  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
+};
+
+
+
+template <typename set_t>
+struct hb_add_coverage_context_t :
+       hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
+{
+  const char *get_name () { return "GET_COVERAGE"; }
+  typedef const Coverage &return_t;
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.get_coverage (); }
+  static return_t default_return_value () { return Null(Coverage); }
+  bool stop_sublookup_iteration (return_t r) const
+  {
+    r.add_coverage (set);
+    return false;
+  }
+
+  hb_add_coverage_context_t (set_t *set_) :
+                            set (set_),
+                            debug_depth (0) {}
+
+  set_t *set;
+  unsigned int debug_depth;
+};
+
+
+struct hb_ot_apply_context_t :
+       hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
+{
+  struct matcher_t
+  {
+    matcher_t () :
+             lookup_props (0),
+             ignore_zwnj (false),
+             ignore_zwj (false),
+             mask (-1),
+#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
+             syllable arg1(0),
+#undef arg1
+             match_func (nullptr),
+             match_data (nullptr) {}
+
+    typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
+
+    void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
+    void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
+    void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
+    void set_mask (hb_mask_t mask_) { mask = mask_; }
+    void set_syllable (uint8_t syllable_)  { syllable = syllable_; }
+    void set_match_func (match_func_t match_func_,
+                                const void *match_data_)
+    { match_func = match_func_; match_data = match_data_; }
+
+    enum may_match_t {
+      MATCH_NO,
+      MATCH_YES,
+      MATCH_MAYBE
+    };
+
+    may_match_t may_match (const hb_glyph_info_t &info,
+                                  const HBUINT16        *glyph_data) const
+    {
+      if (!(info.mask & mask) ||
+          (syllable && syllable != info.syllable ()))
+        return MATCH_NO;
+
+      if (match_func)
+        return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
+
+      return MATCH_MAYBE;
+    }
+
+    enum may_skip_t {
+      SKIP_NO,
+      SKIP_YES,
+      SKIP_MAYBE
+    };
+
+    may_skip_t may_skip (const hb_ot_apply_context_t *c,
+                         const hb_glyph_info_t       &info) const
+    {
+      if (!c->check_glyph_property (&info, lookup_props))
+        return SKIP_YES;
+
+      if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) &&
+                    (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
+                    (ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
+        return SKIP_MAYBE;
+
+      return SKIP_NO;
+    }
+
+    protected:
+    unsigned int lookup_props;
+    bool ignore_zwnj;
+    bool ignore_zwj;
+    hb_mask_t mask;
+    uint8_t syllable;
+    match_func_t match_func;
+    const void *match_data;
+  };
+
+  struct skipping_iterator_t
+  {
+    void init (hb_ot_apply_context_t *c_, bool context_match = false)
+    {
+      c = c_;
+      match_glyph_data = nullptr;
+      matcher.set_match_func (nullptr, nullptr);
+      matcher.set_lookup_props (c->lookup_props);
+      /* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */
+      matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj));
+      /* Ignore ZWJ if we are matching context, or asked to. */
+      matcher.set_ignore_zwj  (context_match || c->auto_zwj);
+      matcher.set_mask (context_match ? -1 : c->lookup_mask);
+    }
+    void set_lookup_props (unsigned int lookup_props)
+    {
+      matcher.set_lookup_props (lookup_props);
+    }
+    void set_match_func (matcher_t::match_func_t match_func_,
+                         const void *match_data_,
+                         const HBUINT16 glyph_data[])
+    {
+      matcher.set_match_func (match_func_, match_data_);
+      match_glyph_data = glyph_data;
+    }
+
+    void reset (unsigned int start_index_,
+                       unsigned int num_items_)
+    {
+      idx = start_index_;
+      num_items = num_items_;
+      end = c->buffer->len;
+      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
+    }
+
+    void reject () { num_items++; match_glyph_data--; }
+
+    matcher_t::may_skip_t
+    may_skip (const hb_glyph_info_t &info) const
+    { return matcher.may_skip (c, info); }
+
+    bool next ()
+    {
+      assert (num_items > 0);
+      while (idx + num_items < end)
+      {
+        idx++;
+        const hb_glyph_info_t &info = c->buffer->info[idx];
+
+        matcher_t::may_skip_t skip = matcher.may_skip (c, info);
+        if (unlikely (skip == matcher_t::SKIP_YES))
+          continue;
+
+        matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
+        if (match == matcher_t::MATCH_YES ||
+            (match == matcher_t::MATCH_MAYBE &&
+             skip == matcher_t::SKIP_NO))
+        {
+          num_items--;
+          match_glyph_data++;
+          return true;
+        }
+
+        if (skip == matcher_t::SKIP_NO)
+          return false;
+      }
+      return false;
+    }
+    bool prev ()
+    {
+      assert (num_items > 0);
+      while (idx > num_items - 1)
+      {
+        idx--;
+        const hb_glyph_info_t &info = c->buffer->out_info[idx];
+
+        matcher_t::may_skip_t skip = matcher.may_skip (c, info);
+        if (unlikely (skip == matcher_t::SKIP_YES))
+          continue;
+
+        matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
+        if (match == matcher_t::MATCH_YES ||
+            (match == matcher_t::MATCH_MAYBE &&
+             skip == matcher_t::SKIP_NO))
+        {
+          num_items--;
+          match_glyph_data++;
+          return true;
+        }
+
+        if (skip == matcher_t::SKIP_NO)
+          return false;
+      }
+      return false;
+    }
+
+    unsigned int idx;
+    protected:
+    hb_ot_apply_context_t *c;
+    matcher_t matcher;
+    const HBUINT16 *match_glyph_data;
+
+    unsigned int num_items;
+    unsigned int end;
+  };
+
+
+  const char *get_name () { return "APPLY"; }
+  typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
+  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; }
+  return_t recurse (unsigned int sub_lookup_index)
+  {
+    if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
+      return default_return_value ();
+
+    nesting_level_left--;
+    bool ret = recurse_func (this, sub_lookup_index);
+    nesting_level_left++;
+    return ret;
+  }
+
+  skipping_iterator_t iter_input, iter_context;
+
+  hb_font_t *font;
+  hb_face_t *face;
+  hb_buffer_t *buffer;
+  recurse_func_t recurse_func;
+  const GDEF &gdef;
+  const VariationStore &var_store;
+
+  hb_direction_t direction;
+  hb_mask_t lookup_mask;
+  unsigned int table_index; /* GSUB/GPOS */
+  unsigned int lookup_index;
+  unsigned int lookup_props;
+  unsigned int nesting_level_left;
+  unsigned int debug_depth;
+
+  bool has_glyph_classes;
+  bool auto_zwnj;
+  bool auto_zwj;
+  bool random;
+
+  uint32_t random_state;
+
+
+  hb_ot_apply_context_t (unsigned int table_index_,
+                      hb_font_t *font_,
+                      hb_buffer_t *buffer_) :
+                        iter_input (), iter_context (),
+                        font (font_), face (font->face), buffer (buffer_),
+                        recurse_func (nullptr),
+                        gdef (*face->table.GDEF->table),
+                        var_store (gdef.get_var_store ()),
+                        direction (buffer_->props.direction),
+                        lookup_mask (1),
+                        table_index (table_index_),
+                        lookup_index ((unsigned int) -1),
+                        lookup_props (0),
+                        nesting_level_left (HB_MAX_NESTING_LEVEL),
+                        debug_depth (0),
+                        has_glyph_classes (gdef.has_glyph_classes ()),
+                        auto_zwnj (true),
+                        auto_zwj (true),
+                        random (false),
+                        random_state (1) { init_iters (); }
+
+  void init_iters ()
+  {
+    iter_input.init (this, false);
+    iter_context.init (this, true);
+  }
+
+  void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; init_iters (); }
+  void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); }
+  void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); }
+  void set_random (bool random_) { random = random_; }
+  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
+  void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
+  void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; init_iters (); }
+
+  uint32_t random_number ()
+  {
+    /* http://www.cplusplus.com/reference/random/minstd_rand/ */
+    random_state = random_state * 48271 % 2147483647;
+    return random_state;
+  }
+
+  bool match_properties_mark (hb_codepoint_t  glyph,
+                              unsigned int    glyph_props,
+                              unsigned int    match_props) const
+  {
+    /* If using mark filtering sets, the high short of
+     * match_props has the set index.
+     */
+    if (match_props & LookupFlag::UseMarkFilteringSet)
+      return gdef.mark_set_covers (match_props >> 16, glyph);
+
+    /* The second byte of match_props has the meaning
+     * "ignore marks of attachment type different than
+     * the attachment type specified."
+     */
+    if (match_props & LookupFlag::MarkAttachmentType)
+      return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
+
+    return true;
+  }
+
+  bool check_glyph_property (const hb_glyph_info_t *info,
+                             unsigned int  match_props) const
+  {
+    hb_codepoint_t glyph = info->codepoint;
+    unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
+
+    /* Not covered, if, for example, glyph class is ligature and
+     * match_props includes LookupFlags::IgnoreLigatures
+     */
+    if (glyph_props & match_props & LookupFlag::IgnoreFlags)
+      return false;
+
+    if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
+      return match_properties_mark (glyph, glyph_props, match_props);
+
+    return true;
+  }
+
+  void _set_glyph_props (hb_codepoint_t glyph_index,
+                          unsigned int class_guess = 0,
+                          bool ligature = false,
+                          bool component = false) const
+  {
+    unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
+                          HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
+    add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
+    if (ligature)
+    {
+      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
+      /* In the only place that the MULTIPLIED bit is used, Uniscribe
+       * seems to only care about the "last" transformation between
+       * Ligature and Multiple substitutions.  Ie. if you ligate, expand,
+       * and ligate again, it forgives the multiplication and acts as
+       * if only ligation happened.  As such, clear MULTIPLIED bit.
+       */
+      add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
+    }
+    if (component)
+      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
+    if (likely (has_glyph_classes))
+      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
+    else if (class_guess)
+      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
+  }
+
+  void replace_glyph (hb_codepoint_t glyph_index) const
+  {
+    _set_glyph_props (glyph_index);
+    buffer->replace_glyph (glyph_index);
+  }
+  void replace_glyph_inplace (hb_codepoint_t glyph_index) const
+  {
+    _set_glyph_props (glyph_index);
+    buffer->cur().codepoint = glyph_index;
+  }
+  void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
+                                           unsigned int class_guess) const
+  {
+    _set_glyph_props (glyph_index, class_guess, true);
+    buffer->replace_glyph (glyph_index);
+  }
+  void output_glyph_for_component (hb_codepoint_t glyph_index,
+                                          unsigned int class_guess) const
+  {
+    _set_glyph_props (glyph_index, class_guess, false, true);
+    buffer->output_glyph (glyph_index);
+  }
+};
+
+
+struct hb_get_subtables_context_t :
+       hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
+{
+  template <typename Type>
+  static bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
+  {
+    const Type *typed_obj = (const Type *) obj;
+    return typed_obj->apply (c);
+  }
+
+  typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
+
+  struct hb_applicable_t
+  {
+    template <typename T>
+    void init (const T &obj_, hb_apply_func_t apply_func_)
+    {
+      obj = &obj_;
+      apply_func = apply_func_;
+      digest.init ();
+      obj_.get_coverage ().add_coverage (&digest);
+    }
+
+    bool apply (OT::hb_ot_apply_context_t *c) const
+    {
+      return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c);
+    }
+
+    private:
+    const void *obj;
+    hb_apply_func_t apply_func;
+    hb_set_digest_t digest;
+  };
+
+  typedef hb_vector_t<hb_applicable_t> array_t;
+
+  /* Dispatch interface. */
+  const char *get_name () { return "GET_SUBTABLES"; }
+  template <typename T>
+  return_t dispatch (const T &obj)
+  {
+    hb_applicable_t *entry = array.push();
+    entry->init (obj, apply_to<T>);
+    return HB_VOID;
+  }
+  static return_t default_return_value () { return HB_VOID; }
+
+  hb_get_subtables_context_t (array_t &array_) :
+                              array (array_),
+                              debug_depth (0) {}
+
+  array_t &array;
+  unsigned int debug_depth;
+};
+
+
+
+
+typedef bool (*intersects_func_t) (const hb_set_t *glyphs, const HBUINT16 &value, const void *data);
+typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
+typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
+
+struct ContextClosureFuncs
+{
+  intersects_func_t intersects;
+};
+struct ContextCollectGlyphsFuncs
+{
+  collect_glyphs_func_t collect;
+};
+struct ContextApplyFuncs
+{
+  match_func_t match;
+};
+
+
+static inline bool intersects_glyph (const hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
+{
+  return glyphs->has (value);
+}
+static inline bool intersects_class (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+{
+  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+  return class_def.intersects_class (glyphs, value);
+}
+static inline bool intersects_coverage (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+{
+  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
+  return (data+coverage).intersects (glyphs);
+}
+
+static inline bool intersects_array (const hb_set_t *glyphs,
+                                     unsigned int count,
+                                     const HBUINT16 values[],
+                                     intersects_func_t intersects_func,
+                                     const void *intersects_data)
+{
+  for (unsigned int i = 0; i < count; i++)
+    if (likely (!intersects_func (glyphs, values[i], intersects_data)))
+      return false;
+  return true;
+}
+
+
+static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
+{
+  glyphs->add (value);
+}
+static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+{
+  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+  class_def.add_class (glyphs, value);
+}
+static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+{
+  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
+  (data+coverage).add_coverage (glyphs);
+}
+static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
+                                  hb_set_t *glyphs,
+                                  unsigned int count,
+                                  const HBUINT16 values[],
+                                  collect_glyphs_func_t collect_func,
+                                  const void *collect_data)
+{
+  for (unsigned int i = 0; i < count; i++)
+    collect_func (glyphs, values[i], collect_data);
+}
+
+
+static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
+{
+  return glyph_id == value;
+}
+static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
+{
+  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+  return class_def.get_class (glyph_id) == value;
+}
+static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
+{
+  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
+  return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
+}
+
+static inline bool would_match_input (hb_would_apply_context_t *c,
+                                      unsigned int count, /* Including the first glyph (not matched) */
+                                      const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                      match_func_t match_func,
+                                      const void *match_data)
+{
+  if (count != c->len)
+    return false;
+
+  for (unsigned int i = 1; i < count; i++)
+    if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
+      return false;
+
+  return true;
+}
+static inline bool match_input (hb_ot_apply_context_t *c,
+                                unsigned int count, /* Including the first glyph (not matched) */
+                                const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                match_func_t match_func,
+                                const void *match_data,
+                                unsigned int *end_offset,
+                                unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
+                                unsigned int *p_total_component_count = nullptr)
+{
+  TRACE_APPLY (nullptr);
+
+  if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
+
+  hb_buffer_t *buffer = c->buffer;
+
+  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+  skippy_iter.reset (buffer->idx, count - 1);
+  skippy_iter.set_match_func (match_func, match_data, input);
+
+  /*
+   * This is perhaps the trickiest part of OpenType...  Remarks:
+   *
+   * - If all components of the ligature were marks, we call this a mark ligature.
+   *
+   * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
+   *   it as a ligature glyph.
+   *
+   * - Ligatures cannot be formed across glyphs attached to different components
+   *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
+   *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
+   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.
+   *   There are a couple of exceptions to this:
+   *
+   *   o If a ligature tries ligating with marks that belong to it itself, go ahead,
+   *     assuming that the font designer knows what they are doing (otherwise it can
+   *     break Indic stuff when a matra wants to ligate with a conjunct,
+   *
+   *   o If two marks want to ligate and they belong to different components of the
+   *     same ligature glyph, and said ligature glyph is to be ignored according to
+   *     mark-filtering rules, then allow.
+   *     https://github.com/harfbuzz/harfbuzz/issues/545
+   */
+
+  unsigned int total_component_count = 0;
+  total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
+
+  unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
+  unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
+
+  enum {
+    LIGBASE_NOT_CHECKED,
+    LIGBASE_MAY_NOT_SKIP,
+    LIGBASE_MAY_SKIP
+  } ligbase = LIGBASE_NOT_CHECKED;
+
+  match_positions[0] = buffer->idx;
+  for (unsigned int i = 1; i < count; i++)
+  {
+    if (!skippy_iter.next ()) return_trace (false);
+
+    match_positions[i] = skippy_iter.idx;
+
+    unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
+    unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
+
+    if (first_lig_id && first_lig_comp)
+    {
+      /* If first component was attached to a previous ligature component,
+       * all subsequent components should be attached to the same ligature
+       * component, otherwise we shouldn't ligate them... */
+      if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
+      {
+        /* ...unless, we are attached to a base ligature and that base
+         * ligature is ignorable. */
+        if (ligbase == LIGBASE_NOT_CHECKED)
+        {
+          bool found = false;
+          const hb_glyph_info_t *out = buffer->out_info;
+          unsigned int j = buffer->out_len;
+          while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
+          {
+            if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
+            {
+              j--;
+              found = true;
+              break;
+            }
+            j--;
+          }
+
+          if (found && skippy_iter.may_skip (out[j]) == hb_ot_apply_context_t::matcher_t::SKIP_YES)
+            ligbase = LIGBASE_MAY_SKIP;
+          else
+            ligbase = LIGBASE_MAY_NOT_SKIP;
+        }
+
+        if (ligbase == LIGBASE_MAY_NOT_SKIP)
+          return_trace (false);
+      }
+    }
+    else
+    {
+      /* If first component was NOT attached to a previous ligature component,
+       * all subsequent components should also NOT be attached to any ligature
+       * component, unless they are attached to the first component itself! */
+      if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
+        return_trace (false);
+    }
+
+    total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
+  }
+
+  *end_offset = skippy_iter.idx - buffer->idx + 1;
+
+  if (p_total_component_count)
+    *p_total_component_count = total_component_count;
+
+  return_trace (true);
+}
+static inline bool ligate_input (hb_ot_apply_context_t *c,
+                                 unsigned int count, /* Including the first glyph */
+                                 const unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
+                                 unsigned int match_length,
+                                 hb_codepoint_t lig_glyph,
+                                 unsigned int total_component_count)
+{
+  TRACE_APPLY (nullptr);
+
+  hb_buffer_t *buffer = c->buffer;
+
+  buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
+
+  /* - If a base and one or more marks ligate, consider that as a base, NOT
+   *   ligature, such that all following marks can still attach to it.
+   *   https://github.com/harfbuzz/harfbuzz/issues/1109
+   *
+   * - If all components of the ligature were marks, we call this a mark ligature.
+   *   If it *is* a mark ligature, we don't allocate a new ligature id, and leave
+   *   the ligature to keep its old ligature id.  This will allow it to attach to
+   *   a base ligature in GPOS.  Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
+   *   and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA with a
+   *   ligature id and component value of 2.  Then if SHADDA,FATHA form a ligature
+   *   later, we don't want them to lose their ligature id/component, otherwise
+   *   GPOS will fail to correctly position the mark ligature on top of the
+   *   LAM,LAM,HEH ligature.  See:
+   *     https://bugzilla.gnome.org/show_bug.cgi?id=676343
+   *
+   * - If a ligature is formed of components that some of which are also ligatures
+   *   themselves, and those ligature components had marks attached to *their*
+   *   components, we have to attach the marks to the new ligature component
+   *   positions!  Now *that*'s tricky!  And these marks may be following the
+   *   last component of the whole sequence, so we should loop forward looking
+   *   for them and update them.
+   *
+   *   Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
+   *   'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
+   *   id and component == 1.  Now, during 'liga', the LAM and the LAM-HEH ligature
+   *   form a LAM-LAM-HEH ligature.  We need to reassign the SHADDA and FATHA to
+   *   the new ligature with a component value of 2.
+   *
+   *   This in fact happened to a font...  See:
+   *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
+   */
+
+  bool is_base_ligature = _hb_glyph_info_is_base_glyph (&buffer->info[match_positions[0]]);
+  bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->info[match_positions[0]]);
+  for (unsigned int i = 1; i < count; i++)
+    if (!_hb_glyph_info_is_mark (&buffer->info[match_positions[i]]))
+    {
+      is_base_ligature = false;
+      is_mark_ligature = false;
+      break;
+    }
+  bool is_ligature = !is_base_ligature && !is_mark_ligature;
+
+  unsigned int klass = is_ligature ? HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE : 0;
+  unsigned int lig_id = is_ligature ? _hb_allocate_lig_id (buffer) : 0;
+  unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
+  unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
+  unsigned int components_so_far = last_num_components;
+
+  if (is_ligature)
+  {
+    _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
+    if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
+    {
+      _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
+    }
+  }
+  c->replace_glyph_with_ligature (lig_glyph, klass);
+
+  for (unsigned int i = 1; i < count; i++)
+  {
+    while (buffer->idx < match_positions[i] && buffer->successful)
+    {
+      if (is_ligature)
+      {
+        unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
+        if (this_comp == 0)
+          this_comp = last_num_components;
+        unsigned int new_lig_comp = components_so_far - last_num_components +
+                                    MIN (this_comp, last_num_components);
+          _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
+      }
+      buffer->next_glyph ();
+    }
+
+    last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
+    last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
+    components_so_far += last_num_components;
+
+    /* Skip the base glyph */
+    buffer->idx++;
+  }
+
+  if (!is_mark_ligature && last_lig_id) {
+    /* Re-adjust components for any marks following. */
+    for (unsigned int i = buffer->idx; i < buffer->len; i++) {
+      if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
+        unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
+        if (!this_comp)
+          break;
+        unsigned int new_lig_comp = components_so_far - last_num_components +
+                                    MIN (this_comp, last_num_components);
+        _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
+      } else
+        break;
+    }
+  }
+  return_trace (true);
+}
+
+static inline bool match_backtrack (hb_ot_apply_context_t *c,
+                                    unsigned int count,
+                                    const HBUINT16 backtrack[],
+                                    match_func_t match_func,
+                                    const void *match_data,
+                                    unsigned int *match_start)
+{
+  TRACE_APPLY (nullptr);
+
+  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
+  skippy_iter.reset (c->buffer->backtrack_len (), count);
+  skippy_iter.set_match_func (match_func, match_data, backtrack);
+
+  for (unsigned int i = 0; i < count; i++)
+    if (!skippy_iter.prev ())
+      return_trace (false);
+
+  *match_start = skippy_iter.idx;
+
+  return_trace (true);
+}
+
+static inline bool match_lookahead (hb_ot_apply_context_t *c,
+                                    unsigned int count,
+                                    const HBUINT16 lookahead[],
+                                    match_func_t match_func,
+                                    const void *match_data,
+                                    unsigned int offset,
+                                    unsigned int *end_index)
+{
+  TRACE_APPLY (nullptr);
+
+  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
+  skippy_iter.reset (c->buffer->idx + offset - 1, count);
+  skippy_iter.set_match_func (match_func, match_data, lookahead);
+
+  for (unsigned int i = 0; i < count; i++)
+    if (!skippy_iter.next ())
+      return_trace (false);
+
+  *end_index = skippy_iter.idx + 1;
+
+  return_trace (true);
+}
+
+
+
+struct LookupRecord
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT16      sequenceIndex;          /* Index into current glyph
+                                         * sequence--first glyph = 0 */
+  HBUINT16      lookupListIndex;        /* Lookup to apply to that
+                                         * position--zero--based */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+template <typename context_t>
+static inline void recurse_lookups (context_t *c,
+                                    unsigned int lookupCount,
+                                    const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
+{
+  for (unsigned int i = 0; i < lookupCount; i++)
+    c->recurse (lookupRecord[i].lookupListIndex);
+}
+
+static inline bool apply_lookup (hb_ot_apply_context_t *c,
+                                 unsigned int count, /* Including the first glyph */
+                                 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
+                                 unsigned int lookupCount,
+                                 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
+                                 unsigned int match_length)
+{
+  TRACE_APPLY (nullptr);
+
+  hb_buffer_t *buffer = c->buffer;
+  int end;
+
+  /* All positions are distance from beginning of *output* buffer.
+   * Adjust. */
+  {
+    unsigned int bl = buffer->backtrack_len ();
+    end = bl + match_length;
+
+    int delta = bl - buffer->idx;
+    /* Convert positions to new indexing. */
+    for (unsigned int j = 0; j < count; j++)
+      match_positions[j] += delta;
+  }
+
+  for (unsigned int i = 0; i < lookupCount && buffer->successful; i++)
+  {
+    unsigned int idx = lookupRecord[i].sequenceIndex;
+    if (idx >= count)
+      continue;
+
+    /* Don't recurse to ourself at same position.
+     * Note that this test is too naive, it doesn't catch longer loops. */
+    if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
+      continue;
+
+    if (unlikely (!buffer->move_to (match_positions[idx])))
+      break;
+
+    if (unlikely (buffer->max_ops <= 0))
+      break;
+
+    unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
+    if (!c->recurse (lookupRecord[i].lookupListIndex))
+      continue;
+
+    unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
+    int delta = new_len - orig_len;
+
+    if (!delta)
+      continue;
+
+    /* Recursed lookup changed buffer len.  Adjust.
+     *
+     * TODO:
+     *
+     * Right now, if buffer length increased by n, we assume n new glyphs
+     * were added right after the current position, and if buffer length
+     * was decreased by n, we assume n match positions after the current
+     * one where removed.  The former (buffer length increased) case is
+     * fine, but the decrease case can be improved in at least two ways,
+     * both of which are significant:
+     *
+     *   - If recursed-to lookup is MultipleSubst and buffer length
+     *     decreased, then it's current match position that was deleted,
+     *     NOT the one after it.
+     *
+     *   - If buffer length was decreased by n, it does not necessarily
+     *     mean that n match positions where removed, as there might
+     *     have been marks and default-ignorables in the sequence.  We
+     *     should instead drop match positions between current-position
+     *     and current-position + n instead.
+     *
+     * It should be possible to construct tests for both of these cases.
+     */
+
+    end += delta;
+    if (end <= int (match_positions[idx]))
+    {
+      /* End might end up being smaller than match_positions[idx] if the recursed
+       * lookup ended up removing many items, more than we have had matched.
+       * Just never rewind end back and get out of here.
+       * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
+      end = match_positions[idx];
+      /* There can't be any further changes. */
+      break;
+    }
+
+    unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
+
+    if (delta > 0)
+    {
+      if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
+        break;
+    }
+    else
+    {
+      /* NOTE: delta is negative. */
+      delta = MAX (delta, (int) next - (int) count);
+      next -= delta;
+    }
+
+    /* Shift! */
+    memmove (match_positions + next + delta, match_positions + next,
+             (count - next) * sizeof (match_positions[0]));
+    next += delta;
+    count += delta;
+
+    /* Fill in new entries. */
+    for (unsigned int j = idx + 1; j < next; j++)
+      match_positions[j] = match_positions[j - 1] + 1;
+
+    /* And fixup the rest. */
+    for (; next < count; next++)
+      match_positions[next] += delta;
+  }
+
+  buffer->move_to (end);
+
+  return_trace (true);
+}
+
+
+
+/* Contextual lookups */
+
+struct ContextClosureLookupContext
+{
+  ContextClosureFuncs funcs;
+  const void *intersects_data;
+};
+
+struct ContextCollectGlyphsLookupContext
+{
+  ContextCollectGlyphsFuncs funcs;
+  const void *collect_data;
+};
+
+struct ContextApplyLookupContext
+{
+  ContextApplyFuncs funcs;
+  const void *match_data;
+};
+
+static inline bool context_intersects (const hb_set_t *glyphs,
+                                       unsigned int inputCount, /* Including the first glyph (not matched) */
+                                       const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                       ContextClosureLookupContext &lookup_context)
+{
+  return intersects_array (glyphs,
+                           inputCount ? inputCount - 1 : 0, input,
+                           lookup_context.funcs.intersects, lookup_context.intersects_data);
+}
+
+static inline void context_closure_lookup (hb_closure_context_t *c,
+                                           unsigned int inputCount, /* Including the first glyph (not matched) */
+                                           const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                           unsigned int lookupCount,
+                                           const LookupRecord lookupRecord[],
+                                           ContextClosureLookupContext &lookup_context)
+{
+  if (context_intersects (c->glyphs,
+                          inputCount, input,
+                          lookup_context))
+    recurse_lookups (c,
+                     lookupCount, lookupRecord);
+}
+
+static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
+                                                  unsigned int inputCount, /* Including the first glyph (not matched) */
+                                                  const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                                  unsigned int lookupCount,
+                                                  const LookupRecord lookupRecord[],
+                                                  ContextCollectGlyphsLookupContext &lookup_context)
+{
+  collect_array (c, c->input,
+                 inputCount ? inputCount - 1 : 0, input,
+                 lookup_context.funcs.collect, lookup_context.collect_data);
+  recurse_lookups (c,
+                   lookupCount, lookupRecord);
+}
+
+static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
+                                               unsigned int inputCount, /* Including the first glyph (not matched) */
+                                               const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                               unsigned int lookupCount HB_UNUSED,
+                                               const LookupRecord lookupRecord[] HB_UNUSED,
+                                               ContextApplyLookupContext &lookup_context)
+{
+  return would_match_input (c,
+                            inputCount, input,
+                            lookup_context.funcs.match, lookup_context.match_data);
+}
+static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
+                                         unsigned int inputCount, /* Including the first glyph (not matched) */
+                                         const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                         unsigned int lookupCount,
+                                         const LookupRecord lookupRecord[],
+                                         ContextApplyLookupContext &lookup_context)
+{
+  unsigned int match_length = 0;
+  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
+  return match_input (c,
+                      inputCount, input,
+                      lookup_context.funcs.match, lookup_context.match_data,
+                      &match_length, match_positions)
+      && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length),
+          apply_lookup (c,
+                       inputCount, match_positions,
+                       lookupCount, lookupRecord,
+                       match_length));
+}
+
+struct Rule
+{
+  bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const
+  {
+    return context_intersects (glyphs,
+                               inputCount, inputZ.arrayZ,
+                               lookup_context);
+  }
+
+  void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
+  {
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+                                                       (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
+    context_closure_lookup (c,
+                            inputCount, inputZ.arrayZ,
+                            lookupCount, lookupRecord.arrayZ,
+                            lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c,
+                       ContextCollectGlyphsLookupContext &lookup_context) const
+  {
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+                                                       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+    context_collect_glyphs_lookup (c,
+                                   inputCount, inputZ.arrayZ,
+                                   lookupCount, lookupRecord.arrayZ,
+                                   lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c,
+                    ContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_WOULD_APPLY (this);
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+                                                       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+    return_trace (context_would_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
+  }
+
+  bool apply (hb_ot_apply_context_t *c,
+              ContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_APPLY (this);
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+                                                       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+    return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
+  }
+
+  public:
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (inputCount.sanitize (c) &&
+                  lookupCount.sanitize (c) &&
+                  c->check_range (inputZ.arrayZ,
+                                  inputZ.item_size * (inputCount ? inputCount - 1 : 0) +
+                                  LookupRecord::static_size * lookupCount));
+  }
+
+  protected:
+  HBUINT16      inputCount;             /* Total number of glyphs in input
+                                         * glyph sequence--includes the first
+                                         * glyph */
+  HBUINT16      lookupCount;            /* Number of LookupRecords */
+  UnsizedArrayOf<HBUINT16>
+                inputZ;                 /* Array of match inputs--start with
+                                         * second glyph */
+/*UnsizedArrayOf<LookupRecord>
+                lookupRecordX;*/        /* Array of LookupRecords--in
+                                         * design order */
+  public:
+  DEFINE_SIZE_ARRAY (4, inputZ);
+};
+
+struct RuleSet
+{
+  bool intersects (const hb_set_t *glyphs,
+                   ContextClosureLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      if ((this+rule[i]).intersects (glyphs, lookup_context))
+        return true;
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c,
+                ContextClosureLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      (this+rule[i]).closure (c, lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c,
+                       ContextCollectGlyphsLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      (this+rule[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c,
+                    ContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_WOULD_APPLY (this);
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+    {
+      if ((this+rule[i]).would_apply (c, lookup_context))
+        return_trace (true);
+    }
+    return_trace (false);
+  }
+
+  bool apply (hb_ot_apply_context_t *c,
+              ContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_APPLY (this);
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+    {
+      if ((this+rule[i]).apply (c, lookup_context))
+        return_trace (true);
+    }
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (rule.sanitize (c, this));
+  }
+
+  protected:
+  OffsetArrayOf<Rule>
+                rule;                   /* Array of Rule tables
+                                         * ordered by preference */
+  public:
+  DEFINE_SIZE_ARRAY (2, rule);
+};
+
+
+struct ContextFormat1
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_glyph},
+      nullptr
+    };
+
+    unsigned int count = ruleSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (glyphs->has (iter.get_glyph ()) &&
+          (this+ruleSet[iter.get_coverage ()]).intersects (glyphs, lookup_context))
+        return true;
+    }
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_glyph},
+      nullptr
+    };
+
+    unsigned int count = ruleSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (c->glyphs->has (iter.get_glyph ()))
+        (this+ruleSet[iter.get_coverage ()]).closure (c, lookup_context);
+    }
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverage).add_coverage (c->input);
+
+    struct ContextCollectGlyphsLookupContext lookup_context = {
+      {collect_glyph},
+      nullptr
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
+    struct ContextApplyLookupContext lookup_context = {
+      {match_glyph},
+      nullptr
+    };
+    return_trace (rule_set.would_apply (c, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED))
+      return_trace (false);
+
+    const RuleSet &rule_set = this+ruleSet[index];
+    struct ContextApplyLookupContext lookup_context = {
+      {match_glyph},
+      nullptr
+    };
+    return_trace (rule_set.apply (c, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 1 */
+  OffsetTo<Coverage>
+                coverage;               /* Offset to Coverage table--from
+                                         * beginning of table */
+  OffsetArrayOf<RuleSet>
+                ruleSet;                /* Array of RuleSet tables
+                                         * ordered by Coverage Index */
+  public:
+  DEFINE_SIZE_ARRAY (6, ruleSet);
+};
+
+
+struct ContextFormat2
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    if (!(this+coverage).intersects (glyphs))
+      return false;
+
+    const ClassDef &class_def = this+classDef;
+
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_class},
+      &class_def
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (class_def.intersects_class (glyphs, i) &&
+          (this+ruleSet[i]).intersects (glyphs, lookup_context))
+        return true;
+
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    if (!(this+coverage).intersects (c->glyphs))
+      return;
+
+    const ClassDef &class_def = this+classDef;
+
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_class},
+      &class_def
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (class_def.intersects_class (c->glyphs, i)) {
+        const RuleSet &rule_set = this+ruleSet[i];
+        rule_set.closure (c, lookup_context);
+      }
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverage).add_coverage (c->input);
+
+    const ClassDef &class_def = this+classDef;
+    struct ContextCollectGlyphsLookupContext lookup_context = {
+      {collect_class},
+      &class_def
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const ClassDef &class_def = this+classDef;
+    unsigned int index = class_def.get_class (c->glyphs[0]);
+    const RuleSet &rule_set = this+ruleSet[index];
+    struct ContextApplyLookupContext lookup_context = {
+      {match_class},
+      &class_def
+    };
+    return_trace (rule_set.would_apply (c, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const ClassDef &class_def = this+classDef;
+    index = class_def.get_class (c->buffer->cur().codepoint);
+    const RuleSet &rule_set = this+ruleSet[index];
+    struct ContextApplyLookupContext lookup_context = {
+      {match_class},
+      &class_def
+    };
+    return_trace (rule_set.apply (c, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 2 */
+  OffsetTo<Coverage>
+                coverage;               /* Offset to Coverage table--from
+                                         * beginning of table */
+  OffsetTo<ClassDef>
+                classDef;               /* Offset to glyph ClassDef table--from
+                                         * beginning of table */
+  OffsetArrayOf<RuleSet>
+                ruleSet;                /* Array of RuleSet tables
+                                         * ordered by class */
+  public:
+  DEFINE_SIZE_ARRAY (8, ruleSet);
+};
+
+
+struct ContextFormat3
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    if (!(this+coverageZ[0]).intersects (glyphs))
+      return false;
+
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_coverage},
+      this
+    };
+    return context_intersects (glyphs,
+                               glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
+                               lookup_context);
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    if (!(this+coverageZ[0]).intersects (c->glyphs))
+      return;
+
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_coverage},
+      this
+    };
+    context_closure_lookup (c,
+                            glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
+                            lookupCount, lookupRecord,
+                            lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverageZ[0]).add_coverage (c->input);
+
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    struct ContextCollectGlyphsLookupContext lookup_context = {
+      {collect_coverage},
+      this
+    };
+
+    context_collect_glyphs_lookup (c,
+                                   glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
+                                   lookupCount, lookupRecord,
+                                   lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    struct ContextApplyLookupContext lookup_context = {
+      {match_coverage},
+      this
+    };
+    return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverageZ[0]; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    struct ContextApplyLookupContext lookup_context = {
+      {match_coverage},
+      this
+    };
+    return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!c->check_struct (this)) return_trace (false);
+    unsigned int count = glyphCount;
+    if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
+    if (!c->check_array (coverageZ.arrayZ, count)) return_trace (false);
+    for (unsigned int i = 0; i < count; i++)
+      if (!coverageZ[i].sanitize (c, this)) return_trace (false);
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    return_trace (c->check_array (lookupRecord, lookupCount));
+  }
+
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 3 */
+  HBUINT16      glyphCount;             /* Number of glyphs in the input glyph
+                                         * sequence */
+  HBUINT16      lookupCount;            /* Number of LookupRecords */
+  UnsizedArrayOf<OffsetTo<Coverage> >
+                coverageZ;              /* Array of offsets to Coverage
+                                         * table in glyph sequence order */
+/*UnsizedArrayOf<LookupRecord>
+                lookupRecordX;*/        /* Array of LookupRecords--in
+                                         * design order */
+  public:
+  DEFINE_SIZE_ARRAY (6, coverageZ);
+};
+
+struct Context
+{
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+    switch (u.format) {
+    case 1: return_trace (c->dispatch (u.format1));
+    case 2: return_trace (c->dispatch (u.format2));
+    case 3: return_trace (c->dispatch (u.format3));
+    default:return_trace (c->default_return_value ());
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16              format;         /* Format identifier */
+  ContextFormat1        format1;
+  ContextFormat2        format2;
+  ContextFormat3        format3;
+  } u;
+};
+
+
+/* Chaining Contextual lookups */
+
+struct ChainContextClosureLookupContext
+{
+  ContextClosureFuncs funcs;
+  const void *intersects_data[3];
+};
+
+struct ChainContextCollectGlyphsLookupContext
+{
+  ContextCollectGlyphsFuncs funcs;
+  const void *collect_data[3];
+};
+
+struct ChainContextApplyLookupContext
+{
+  ContextApplyFuncs funcs;
+  const void *match_data[3];
+};
+
+static inline bool chain_context_intersects (const hb_set_t *glyphs,
+                                             unsigned int backtrackCount,
+                                             const HBUINT16 backtrack[],
+                                             unsigned int inputCount, /* Including the first glyph (not matched) */
+                                             const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                             unsigned int lookaheadCount,
+                                             const HBUINT16 lookahead[],
+                                             ChainContextClosureLookupContext &lookup_context)
+{
+  return intersects_array (glyphs,
+                           backtrackCount, backtrack,
+                           lookup_context.funcs.intersects, lookup_context.intersects_data[0])
+      && intersects_array (glyphs,
+                           inputCount ? inputCount - 1 : 0, input,
+                           lookup_context.funcs.intersects, lookup_context.intersects_data[1])
+      && intersects_array (glyphs,
+                          lookaheadCount, lookahead,
+                          lookup_context.funcs.intersects, lookup_context.intersects_data[2]);
+}
+
+static inline void chain_context_closure_lookup (hb_closure_context_t *c,
+                                                 unsigned int backtrackCount,
+                                                 const HBUINT16 backtrack[],
+                                                 unsigned int inputCount, /* Including the first glyph (not matched) */
+                                                 const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                                 unsigned int lookaheadCount,
+                                                 const HBUINT16 lookahead[],
+                                                 unsigned int lookupCount,
+                                                 const LookupRecord lookupRecord[],
+                                                 ChainContextClosureLookupContext &lookup_context)
+{
+  if (chain_context_intersects (c->glyphs,
+                                backtrackCount, backtrack,
+                                inputCount, input,
+                                lookaheadCount, lookahead,
+                                lookup_context))
+    recurse_lookups (c,
+                     lookupCount, lookupRecord);
+}
+
+static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
+                                                        unsigned int backtrackCount,
+                                                        const HBUINT16 backtrack[],
+                                                        unsigned int inputCount, /* Including the first glyph (not matched) */
+                                                        const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                                        unsigned int lookaheadCount,
+                                                        const HBUINT16 lookahead[],
+                                                        unsigned int lookupCount,
+                                                        const LookupRecord lookupRecord[],
+                                                        ChainContextCollectGlyphsLookupContext &lookup_context)
+{
+  collect_array (c, c->before,
+                 backtrackCount, backtrack,
+                 lookup_context.funcs.collect, lookup_context.collect_data[0]);
+  collect_array (c, c->input,
+                 inputCount ? inputCount - 1 : 0, input,
+                 lookup_context.funcs.collect, lookup_context.collect_data[1]);
+  collect_array (c, c->after,
+                 lookaheadCount, lookahead,
+                 lookup_context.funcs.collect, lookup_context.collect_data[2]);
+  recurse_lookups (c,
+                   lookupCount, lookupRecord);
+}
+
+static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
+                                                     unsigned int backtrackCount,
+                                                     const HBUINT16 backtrack[] HB_UNUSED,
+                                                     unsigned int inputCount, /* Including the first glyph (not matched) */
+                                                     const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                                     unsigned int lookaheadCount,
+                                                     const HBUINT16 lookahead[] HB_UNUSED,
+                                                     unsigned int lookupCount HB_UNUSED,
+                                                     const LookupRecord lookupRecord[] HB_UNUSED,
+                                                     ChainContextApplyLookupContext &lookup_context)
+{
+  return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
+      && would_match_input (c,
+                            inputCount, input,
+                            lookup_context.funcs.match, lookup_context.match_data[1]);
+}
+
+static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
+                                               unsigned int backtrackCount,
+                                               const HBUINT16 backtrack[],
+                                               unsigned int inputCount, /* Including the first glyph (not matched) */
+                                               const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                               unsigned int lookaheadCount,
+                                               const HBUINT16 lookahead[],
+                                               unsigned int lookupCount,
+                                               const LookupRecord lookupRecord[],
+                                               ChainContextApplyLookupContext &lookup_context)
+{
+  unsigned int start_index = 0, match_length = 0, end_index = 0;
+  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
+  return match_input (c,
+                      inputCount, input,
+                      lookup_context.funcs.match, lookup_context.match_data[1],
+                      &match_length, match_positions)
+      && match_backtrack (c,
+                          backtrackCount, backtrack,
+                          lookup_context.funcs.match, lookup_context.match_data[0],
+                          &start_index)
+      && match_lookahead (c,
+                          lookaheadCount, lookahead,
+                          lookup_context.funcs.match, lookup_context.match_data[2],
+                          match_length, &end_index)
+      && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index),
+          apply_lookup (c,
+                        inputCount, match_positions,
+                        lookupCount, lookupRecord,
+                        match_length));
+}
+
+struct ChainRule
+{
+  bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
+  {
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    return chain_context_intersects (glyphs,
+                                     backtrack.len, backtrack.arrayZ,
+                                     input.lenP1, input.arrayZ,
+                                     lookahead.len, lookahead.arrayZ,
+                                     lookup_context);
+  }
+
+  void closure (hb_closure_context_t *c,
+                ChainContextClosureLookupContext &lookup_context) const
+  {
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    chain_context_closure_lookup (c,
+                                  backtrack.len, backtrack.arrayZ,
+                                  input.lenP1, input.arrayZ,
+                                  lookahead.len, lookahead.arrayZ,
+                                  lookup.len, lookup.arrayZ,
+                                  lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c,
+                       ChainContextCollectGlyphsLookupContext &lookup_context) const
+  {
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    chain_context_collect_glyphs_lookup (c,
+                                         backtrack.len, backtrack.arrayZ,
+                                         input.lenP1, input.arrayZ,
+                                         lookahead.len, lookahead.arrayZ,
+                                         lookup.len, lookup.arrayZ,
+                                         lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c,
+                    ChainContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_WOULD_APPLY (this);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    return_trace (chain_context_would_apply_lookup (c,
+                                                    backtrack.len, backtrack.arrayZ,
+                                                    input.lenP1, input.arrayZ,
+                                                    lookahead.len, lookahead.arrayZ, lookup.len,
+                                                    lookup.arrayZ, lookup_context));
+  }
+
+  bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_APPLY (this);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    return_trace (chain_context_apply_lookup (c,
+                                              backtrack.len, backtrack.arrayZ,
+                                              input.lenP1, input.arrayZ,
+                                              lookahead.len, lookahead.arrayZ, lookup.len,
+                                              lookup.arrayZ, lookup_context));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!backtrack.sanitize (c)) return_trace (false);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    if (!input.sanitize (c)) return_trace (false);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    if (!lookahead.sanitize (c)) return_trace (false);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    return_trace (lookup.sanitize (c));
+  }
+
+  protected:
+  ArrayOf<HBUINT16>
+                backtrack;              /* Array of backtracking values
+                                         * (to be matched before the input
+                                         * sequence) */
+  HeadlessArrayOf<HBUINT16>
+                inputX;                 /* Array of input values (start with
+                                         * second glyph) */
+  ArrayOf<HBUINT16>
+                lookaheadX;             /* Array of lookahead values's (to be
+                                         * matched after the input sequence) */
+  ArrayOf<LookupRecord>
+                lookupX;                /* Array of LookupRecords--in
+                                         * design order) */
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+struct ChainRuleSet
+{
+  bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      if ((this+rule[i]).intersects (glyphs, lookup_context))
+        return true;
+    return false;
+  }
+  void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      (this+rule[i]).closure (c, lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      (this+rule[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_WOULD_APPLY (this);
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      if ((this+rule[i]).would_apply (c, lookup_context))
+        return_trace (true);
+
+    return_trace (false);
+  }
+
+  bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_APPLY (this);
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      if ((this+rule[i]).apply (c, lookup_context))
+        return_trace (true);
+
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (rule.sanitize (c, this));
+  }
+
+  protected:
+  OffsetArrayOf<ChainRule>
+                rule;                   /* Array of ChainRule tables
+                                         * ordered by preference */
+  public:
+  DEFINE_SIZE_ARRAY (2, rule);
+};
+
+struct ChainContextFormat1
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (glyphs->has (iter.get_glyph ()) &&
+          (this+ruleSet[iter.get_coverage ()]).intersects (glyphs, lookup_context))
+        return true;
+    }
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (c->glyphs->has (iter.get_glyph ()))
+        (this+ruleSet[iter.get_coverage ()]).closure (c, lookup_context);
+    }
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverage).add_coverage (c->input);
+
+    struct ChainContextCollectGlyphsLookupContext lookup_context = {
+      {collect_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+    return_trace (rule_set.would_apply (c, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const ChainRuleSet &rule_set = this+ruleSet[index];
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+    return_trace (rule_set.apply (c, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 1 */
+  OffsetTo<Coverage>
+                coverage;               /* Offset to Coverage table--from
+                                         * beginning of table */
+  OffsetArrayOf<ChainRuleSet>
+                ruleSet;                /* Array of ChainRuleSet tables
+                                         * ordered by Coverage Index */
+  public:
+  DEFINE_SIZE_ARRAY (6, ruleSet);
+};
+
+struct ChainContextFormat2
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    if (!(this+coverage).intersects (glyphs))
+      return false;
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (input_class_def.intersects_class (glyphs, i) &&
+          (this+ruleSet[i]).intersects (glyphs, lookup_context))
+        return true;
+
+    return false;
+  }
+  void closure (hb_closure_context_t *c) const
+  {
+    if (!(this+coverage).intersects (c->glyphs))
+      return;
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (input_class_def.intersects_class (c->glyphs, i)) {
+        const ChainRuleSet &rule_set = this+ruleSet[i];
+        rule_set.closure (c, lookup_context);
+      }
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverage).add_coverage (c->input);
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    struct ChainContextCollectGlyphsLookupContext lookup_context = {
+      {collect_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    unsigned int index = input_class_def.get_class (c->glyphs[0]);
+    const ChainRuleSet &rule_set = this+ruleSet[index];
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+    return_trace (rule_set.would_apply (c, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    index = input_class_def.get_class (c->buffer->cur().codepoint);
+    const ChainRuleSet &rule_set = this+ruleSet[index];
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+    return_trace (rule_set.apply (c, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (coverage.sanitize (c, this) &&
+                  backtrackClassDef.sanitize (c, this) &&
+                  inputClassDef.sanitize (c, this) &&
+                  lookaheadClassDef.sanitize (c, this) &&
+                  ruleSet.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 2 */
+  OffsetTo<Coverage>
+                coverage;               /* Offset to Coverage table--from
+                                         * beginning of table */
+  OffsetTo<ClassDef>
+                backtrackClassDef;      /* Offset to glyph ClassDef table
+                                         * containing backtrack sequence
+                                         * data--from beginning of table */
+  OffsetTo<ClassDef>
+                inputClassDef;          /* Offset to glyph ClassDef
+                                         * table containing input sequence
+                                         * data--from beginning of table */
+  OffsetTo<ClassDef>
+                lookaheadClassDef;      /* Offset to glyph ClassDef table
+                                         * containing lookahead sequence
+                                         * data--from beginning of table */
+  OffsetArrayOf<ChainRuleSet>
+                ruleSet;                /* Array of ChainRuleSet tables
+                                         * ordered by class */
+  public:
+  DEFINE_SIZE_ARRAY (12, ruleSet);
+};
+
+struct ChainContextFormat3
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    if (!(this+input[0]).intersects (glyphs))
+      return false;
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_coverage},
+      {this, this, this}
+    };
+    return chain_context_intersects (glyphs,
+                                     backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                     input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                     lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                     lookup_context);
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    if (!(this+input[0]).intersects (c->glyphs))
+      return;
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_coverage},
+      {this, this, this}
+    };
+    chain_context_closure_lookup (c,
+                                  backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                  input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                  lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                  lookup.len, lookup.arrayZ,
+                                  lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    (this+input[0]).add_coverage (c->input);
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    struct ChainContextCollectGlyphsLookupContext lookup_context = {
+      {collect_coverage},
+      {this, this, this}
+    };
+    chain_context_collect_glyphs_lookup (c,
+                                         backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                         input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                         lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                         lookup.len, lookup.arrayZ,
+                                         lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_coverage},
+      {this, this, this}
+    };
+    return_trace (chain_context_would_apply_lookup (c,
+                                                    backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                                    input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                                    lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                                    lookup.len, lookup.arrayZ, lookup_context));
+  }
+
+  const Coverage &get_coverage () const
+  {
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    return this+input[0];
+  }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_coverage},
+      {this, this, this}
+    };
+    return_trace (chain_context_apply_lookup (c,
+                                              backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                              input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                              lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                              lookup.len, lookup.arrayZ, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!backtrack.sanitize (c, this)) return_trace (false);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    if (!input.sanitize (c, this)) return_trace (false);
+    if (!input.len) return_trace (false); /* To be consistent with Context. */
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    if (!lookahead.sanitize (c, this)) return_trace (false);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    return_trace (lookup.sanitize (c));
+  }
+
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 3 */
+  OffsetArrayOf<Coverage>
+                backtrack;              /* Array of coverage tables
+                                         * in backtracking sequence, in  glyph
+                                         * sequence order */
+  OffsetArrayOf<Coverage>
+                inputX          ;       /* Array of coverage
+                                         * tables in input sequence, in glyph
+                                         * sequence order */
+  OffsetArrayOf<Coverage>
+                lookaheadX;             /* Array of coverage tables
+                                         * in lookahead sequence, in glyph
+                                         * sequence order */
+  ArrayOf<LookupRecord>
+                lookupX;                /* Array of LookupRecords--in
+                                         * design order) */
+  public:
+  DEFINE_SIZE_MIN (10);
+};
+
+struct ChainContext
+{
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+    switch (u.format) {
+    case 1: return_trace (c->dispatch (u.format1));
+    case 2: return_trace (c->dispatch (u.format2));
+    case 3: return_trace (c->dispatch (u.format3));
+    default:return_trace (c->default_return_value ());
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16              format; /* Format identifier */
+  ChainContextFormat1   format1;
+  ChainContextFormat2   format2;
+  ChainContextFormat3   format3;
+  } u;
+};
+
+
+template <typename T>
+struct ExtensionFormat1
+{
+  unsigned int get_type () const { return extensionLookupType; }
+
+  template <typename X>
+  const X& get_subtable () const
+  {
+    unsigned int offset = extensionOffset;
+    if (unlikely (!offset)) return Null(typename T::SubTable);
+    return StructAtOffset<typename T::SubTable> (this, offset);
+  }
+
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    TRACE_DISPATCH (this, format);
+    if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
+    return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type ()));
+  }
+
+  /* This is called from may_dispatch() above with hb_sanitize_context_t. */
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  extensionOffset != 0 &&
+                  extensionLookupType != T::SubTable::Extension);
+  }
+
+  protected:
+  HBUINT16      format;                 /* Format identifier. Set to 1. */
+  HBUINT16      extensionLookupType;    /* Lookup type of subtable referenced
+                                         * by ExtensionOffset (i.e. the
+                                         * extension subtable). */
+  HBUINT32      extensionOffset;        /* Offset to the extension subtable,
+                                         * of lookup type subtable. */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+template <typename T>
+struct Extension
+{
+  unsigned int get_type () const
+  {
+    switch (u.format) {
+    case 1: return u.format1.get_type ();
+    default:return 0;
+    }
+  }
+  template <typename X>
+  const X& get_subtable () const
+  {
+    switch (u.format) {
+    case 1: return u.format1.template get_subtable<typename T::SubTable> ();
+    default:return Null(typename T::SubTable);
+    }
+  }
+
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+    switch (u.format) {
+    case 1: return_trace (u.format1.dispatch (c));
+    default:return_trace (c->default_return_value ());
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16              format;         /* Format identifier */
+  ExtensionFormat1<T>   format1;
+  } u;
+};
+
+
+/*
+ * GSUB/GPOS Common
+ */
+
+struct hb_ot_layout_lookup_accelerator_t
+{
+  template <typename TLookup>
+  void init (const TLookup &lookup)
+  {
+    digest.init ();
+    lookup.add_coverage (&digest);
+
+    subtables.init ();
+    OT::hb_get_subtables_context_t c_get_subtables (subtables);
+    lookup.dispatch (&c_get_subtables);
+  }
+  void fini () { subtables.fini (); }
+
+  bool may_have (hb_codepoint_t g) const
+  { return digest.may_have (g); }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    for (unsigned int i = 0; i < subtables.length; i++)
+      if (subtables[i].apply (c))
+        return true;
+    return false;
+  }
+
+  private:
+  hb_set_digest_t digest;
+  hb_get_subtables_context_t::array_t subtables;
+};
+
+struct GSUBGPOS
+{
+  bool has_data () const { return version.to_int (); }
+  unsigned int get_script_count () const
+  { return (this+scriptList).len; }
+  const Tag& get_script_tag (unsigned int i) const
+  { return (this+scriptList).get_tag (i); }
+  unsigned int get_script_tags (unsigned int start_offset,
+                                unsigned int *script_count /* IN/OUT */,
+                                hb_tag_t     *script_tags /* OUT */) const
+  { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
+  const Script& get_script (unsigned int i) const
+  { return (this+scriptList)[i]; }
+  bool find_script_index (hb_tag_t tag, unsigned int *index) const
+  { return (this+scriptList).find_index (tag, index); }
+
+  unsigned int get_feature_count () const
+  { return (this+featureList).len; }
+  hb_tag_t get_feature_tag (unsigned int i) const
+  { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
+  unsigned int get_feature_tags (unsigned int start_offset,
+                                 unsigned int *feature_count /* IN/OUT */,
+                                 hb_tag_t     *feature_tags /* OUT */) const
+  { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
+  const Feature& get_feature (unsigned int i) const
+  { return (this+featureList)[i]; }
+  bool find_feature_index (hb_tag_t tag, unsigned int *index) const
+  { return (this+featureList).find_index (tag, index); }
+
+  unsigned int get_lookup_count () const
+  { return (this+lookupList).len; }
+  const Lookup& get_lookup (unsigned int i) const
+  { return (this+lookupList)[i]; }
+
+  bool find_variations_index (const int *coords, unsigned int num_coords,
+                              unsigned int *index) const
+  { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
+           .find_index (coords, num_coords, index); }
+  const Feature& get_feature_variation (unsigned int feature_index,
+                                        unsigned int variations_index) const
+  {
+    if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
+        version.to_int () >= 0x00010001u)
+    {
+      const Feature *feature = (this+featureVars).find_substitute (variations_index,
+                                                                   feature_index);
+      if (feature)
+        return *feature;
+    }
+    return get_feature (feature_index);
+  }
+
+  template <typename TLookup>
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct GSUBGPOS *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+
+    out->scriptList.serialize_subset (c, this+scriptList, out);
+    out->featureList.serialize_subset (c, this+featureList, out);
+
+    typedef OffsetListOf<TLookup> TLookupList;
+    /* TODO Use intersects() to count how many subtables survive? */
+    CastR<OffsetTo<TLookupList> > (out->lookupList)
+      .serialize_subset (c,
+                         this+CastR<const OffsetTo<TLookupList> > (lookupList),
+                         out);
+
+    if (version.to_int () >= 0x00010001u)
+     out->featureVars.serialize_subset (c, this+featureVars, out);
+
+    return_trace (true);
+  }
+
+  unsigned int get_size () const
+  {
+    return min_size +
+           (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
+  }
+
+  template <typename TLookup>
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    typedef OffsetListOf<TLookup> TLookupList;
+    return_trace (version.sanitize (c) &&
+                  likely (version.major == 1) &&
+                  scriptList.sanitize (c, this) &&
+                  featureList.sanitize (c, this) &&
+                  CastR<OffsetTo<TLookupList> > (lookupList).sanitize (c, this) &&
+                  (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
+  }
+
+  template <typename T>
+  struct accelerator_t
+  {
+    void init (hb_face_t *face)
+    {
+      this->table = hb_sanitize_context_t().reference_table<T> (face);
+      if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face)))
+      {
+        hb_blob_destroy (this->table.get_blob ());
+        this->table = hb_blob_get_empty ();
+      }
+
+      this->lookup_count = table->get_lookup_count ();
+
+      this->accels = (hb_ot_layout_lookup_accelerator_t *) calloc (this->lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t));
+      if (unlikely (!this->accels))
+        this->lookup_count = 0;
+
+      for (unsigned int i = 0; i < this->lookup_count; i++)
+        this->accels[i].init (table->get_lookup (i));
+    }
+
+    void fini ()
+    {
+      for (unsigned int i = 0; i < this->lookup_count; i++)
+        this->accels[i].fini ();
+      free (this->accels);
+      this->table.destroy ();
+    }
+
+    hb_blob_ptr_t<T> table;
+    unsigned int lookup_count;
+    hb_ot_layout_lookup_accelerator_t *accels;
+  };
+
+  protected:
+  FixedVersion<>version;        /* Version of the GSUB/GPOS table--initially set
+                                 * to 0x00010000u */
+  OffsetTo<ScriptList>
+                scriptList;     /* ScriptList table */
+  OffsetTo<FeatureList>
+                featureList;    /* FeatureList table */
+  OffsetTo<LookupList>
+                lookupList;     /* LookupList table */
+  LOffsetTo<FeatureVariations>
+                featureVars;    /* Offset to Feature Variations
+                                   table--from beginning of table
+                                 * (may be NULL).  Introduced
+                                 * in version 0x00010001. */
+  public:
+  DEFINE_SIZE_MIN (10);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_LAYOUT_GSUBGPOS_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-jstf-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-jstf-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,7 +27,7 @@
 #ifndef HB_OT_LAYOUT_JSTF_TABLE_HH
 #define HB_OT_LAYOUT_JSTF_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 #include "hb-ot-layout-gpos-table.hh"
 
 
@@ -54,7 +54,7 @@
 
 struct JstfPriority
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -123,8 +123,8 @@
 
 struct JstfLangSys : OffsetListOf<JstfPriority>
 {
-  inline bool sanitize (hb_sanitize_context_t *c,
-                        const Record<JstfLangSys>::sanitize_closure_t * = nullptr) const
+  bool sanitize (hb_sanitize_context_t *c,
+                 const Record_sanitize_closure_t * = nullptr) const
   {
     TRACE_SANITIZE (this);
     return_trace (OffsetListOf<JstfPriority>::sanitize (c));
@@ -145,27 +145,27 @@
 
 struct JstfScript
 {
-  inline unsigned int get_lang_sys_count (void) const
+  unsigned int get_lang_sys_count () const
   { return langSys.len; }
-  inline const Tag& get_lang_sys_tag (unsigned int i) const
+  const Tag& get_lang_sys_tag (unsigned int i) const
   { return langSys.get_tag (i); }
-  inline unsigned int get_lang_sys_tags (unsigned int start_offset,
-                                         unsigned int *lang_sys_count /* IN/OUT */,
-                                         hb_tag_t     *lang_sys_tags /* OUT */) const
+  unsigned int get_lang_sys_tags (unsigned int start_offset,
+                                  unsigned int *lang_sys_count /* IN/OUT */,
+                                  hb_tag_t     *lang_sys_tags /* OUT */) const
   { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
-  inline const JstfLangSys& get_lang_sys (unsigned int i) const
+  const JstfLangSys& get_lang_sys (unsigned int i) const
   {
     if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
     return this+langSys[i].offset;
   }
-  inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
+  bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
   { return langSys.find_index (tag, index); }
 
-  inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
-  inline const JstfLangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
+  bool has_default_lang_sys () const               { return defaultLangSys != 0; }
+  const JstfLangSys& get_default_lang_sys () const { return this+defaultLangSys; }
 
-  inline bool sanitize (hb_sanitize_context_t *c,
-                        const Record<JstfScript>::sanitize_closure_t * = nullptr) const
+  bool sanitize (hb_sanitize_context_t *c,
+                 const Record_sanitize_closure_t * = nullptr) const
   {
     TRACE_SANITIZE (this);
     return_trace (extenderGlyphs.sanitize (c, this) &&
@@ -195,22 +195,22 @@
 
 struct JSTF
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_JSTF;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_JSTF;
 
-  inline unsigned int get_script_count (void) const
+  unsigned int get_script_count () const
   { return scriptList.len; }
-  inline const Tag& get_script_tag (unsigned int i) const
+  const Tag& get_script_tag (unsigned int i) const
   { return scriptList.get_tag (i); }
-  inline unsigned int get_script_tags (unsigned int start_offset,
-                                       unsigned int *script_count /* IN/OUT */,
-                                       hb_tag_t     *script_tags /* OUT */) const
+  unsigned int get_script_tags (unsigned int start_offset,
+                                unsigned int *script_count /* IN/OUT */,
+                                hb_tag_t     *script_tags /* OUT */) const
   { return scriptList.get_tags (start_offset, script_count, script_tags); }
-  inline const JstfScript& get_script (unsigned int i) const
+  const JstfScript& get_script (unsigned int i) const
   { return this+scriptList[i].offset; }
-  inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
+  bool find_script_index (hb_tag_t tag, unsigned int *index) const
   { return scriptList.find_index (tag, index); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,677 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2012,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
- */
-
-#ifndef HB_OT_LAYOUT_PRIVATE_HH
-#define HB_OT_LAYOUT_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-font-private.hh"
-#include "hb-buffer-private.hh"
-#include "hb-set-digest-private.hh"
-#include "hb-open-type-private.hh"
-
-
-/* Private API corresponding to hb-ot-layout.h: */
-
-HB_INTERNAL hb_bool_t
-hb_ot_layout_table_find_feature (hb_face_t    *face,
-                                 hb_tag_t      table_tag,
-                                 hb_tag_t      feature_tag,
-                                 unsigned int *feature_index);
-
-
-/*
- * GDEF
- */
-
-enum hb_ot_layout_glyph_props_flags_t
-{
-  /* The following three match LookupFlags::Ignore* numbers. */
-  HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH   = 0x02u,
-  HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE     = 0x04u,
-  HB_OT_LAYOUT_GLYPH_PROPS_MARK         = 0x08u,
-
-  /* The following are used internally; not derived from GDEF. */
-  HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED  = 0x10u,
-  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED      = 0x20u,
-  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED   = 0x40u,
-
-  HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE     = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
-                                          HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
-                                          HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
-};
-HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t);
-
-
-/*
- * GSUB/GPOS
- */
-
-HB_INTERNAL hb_bool_t
-hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
-                                           unsigned int          lookup_index,
-                                           const hb_codepoint_t *glyphs,
-                                           unsigned int          glyphs_length,
-                                           hb_bool_t             zero_context);
-
-
-/* Should be called before all the substitute_lookup's are done. */
-HB_INTERNAL void
-hb_ot_layout_substitute_start (hb_font_t    *font,
-                               hb_buffer_t  *buffer);
-
-
-struct hb_ot_layout_lookup_accelerator_t;
-
-namespace OT {
-  struct hb_ot_apply_context_t;
-  struct SubstLookup;
-}
-
-HB_INTERNAL void
-hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
-                                const OT::SubstLookup &lookup,
-                                const hb_ot_layout_lookup_accelerator_t &accel);
-
-
-/* Should be called before all the position_lookup's are done. */
-HB_INTERNAL void
-hb_ot_layout_position_start (hb_font_t    *font,
-                             hb_buffer_t  *buffer);
-
-/* Should be called after all the position_lookup's are done, to fini advances. */
-HB_INTERNAL void
-hb_ot_layout_position_finish_advances (hb_font_t    *font,
-                                       hb_buffer_t  *buffer);
-
-/* Should be called after hb_ot_layout_position_finish_advances, to fini offsets. */
-HB_INTERNAL void
-hb_ot_layout_position_finish_offsets (hb_font_t    *font,
-                                      hb_buffer_t  *buffer);
-
-
-
-/*
- * hb_ot_layout_t
- */
-
-namespace OT {
-  struct BASE;
-  struct COLR;
-  struct CPAL;
-  struct GDEF;
-  struct GSUB;
-  struct GPOS;
-  struct MATH;
-  struct fvar;
-  struct avar;
-}
-
-namespace AAT {
-  struct ankr;
-  struct kerx;
-  struct morx;
-  struct trak;
-}
-
-struct hb_ot_layout_lookup_accelerator_t
-{
-  template <typename TLookup>
-  inline void init (const TLookup &lookup)
-  {
-    digest.init ();
-    lookup.add_coverage (&digest);
-  }
-
-  inline void fini (void)
-  {
-  }
-
-  inline bool may_have (hb_codepoint_t g) const {
-    return digest.may_have (g);
-  }
-
-  private:
-  hb_set_digest_t digest;
-};
-
-struct hb_ot_layout_t
-{
-  hb_blob_t *gdef_blob;
-  hb_blob_t *gsub_blob;
-  hb_blob_t *gpos_blob;
-
-  const struct OT::GDEF *gdef;
-  const struct OT::GSUB *gsub;
-  const struct OT::GPOS *gpos;
-
-  /* TODO Move the following out of this struct. */
-  OT::hb_table_lazy_loader_t<struct OT::BASE> base;
-  OT::hb_table_lazy_loader_t<struct OT::MATH> math;
-  OT::hb_table_lazy_loader_t<struct OT::fvar> fvar;
-  OT::hb_table_lazy_loader_t<struct OT::avar> avar;
-
-  unsigned int gsub_lookup_count;
-  unsigned int gpos_lookup_count;
-
-  hb_ot_layout_lookup_accelerator_t *gsub_accels;
-  hb_ot_layout_lookup_accelerator_t *gpos_accels;
-};
-
-
-HB_INTERNAL hb_ot_layout_t *
-_hb_ot_layout_create (hb_face_t *face);
-
-HB_INTERNAL void
-_hb_ot_layout_destroy (hb_ot_layout_t *layout);
-
-
-#define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot)
-
-
-/*
- * Buffer var routines.
- */
-
-/* buffer var allocations, used during the entire shaping process */
-#define unicode_props()         var2.u16[0]
-
-/* buffer var allocations, used during the GSUB/GPOS processing */
-#define glyph_props()           var1.u16[0] /* GDEF glyph properties */
-#define lig_props()             var1.u8[2] /* GSUB/GPOS ligature tracking */
-#define syllable()              var1.u8[3] /* GSUB/GPOS shaping boundaries */
-
-
-/* Loop over syllables. Based on foreach_cluster(). */
-#define foreach_syllable(buffer, start, end) \
-  for (unsigned int \
-       _count = buffer->len, \
-       start = 0, end = _count ? _next_syllable (buffer, 0) : 0; \
-       start < _count; \
-       start = end, end = _next_syllable (buffer, start))
-
-static inline unsigned int
-_next_syllable (hb_buffer_t *buffer, unsigned int start)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  unsigned int syllable = info[start].syllable();
-  while (++start < count && syllable == info[start].syllable())
-    ;
-
-  return start;
-}
-
-
-/* unicode_props */
-
-/* Design:
- * unicode_props() is a two-byte number.  The low byte includes:
- * - General_Category: 5 bits.
- * - A bit each for:
- *   * Is it Default_Ignorable(); we have a modified Default_Ignorable().
- *   * Whether it's one of the three Mongolian Free Variation Selectors,
- *     CGJ, or other characters that are hidden but should not be ignored
- *     like most other Default_Ignorable()s do during matching.
- *   * One free bit right now.
- *
- * The high-byte has different meanings, switched by the Gen-Cat:
- * - For Mn,Mc,Me: the modified Combining_Class.
- * - For Cf: whether it's ZWJ, ZWNJ, or something else.
- * - For Ws: index of which space character this is, if space fallback
- *   is needed, ie. we don't set this by default, only if asked to.
- */
-
-enum hb_unicode_props_flags_t {
-  UPROPS_MASK_GEN_CAT   = 0x001Fu,
-  UPROPS_MASK_IGNORABLE = 0x0020u,
-  UPROPS_MASK_HIDDEN    = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3,
-                                    * or TAG characters */
-
-  /* If GEN_CAT=FORMAT, top byte masks: */
-  UPROPS_MASK_Cf_ZWJ    = 0x0100u,
-  UPROPS_MASK_Cf_ZWNJ   = 0x0200u
-};
-HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
-
-static inline void
-_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
-{
-  hb_unicode_funcs_t *unicode = buffer->unicode;
-  unsigned int u = info->codepoint;
-  unsigned int gen_cat = (unsigned int) unicode->general_category (u);
-  unsigned int props = gen_cat;
-
-  if (u >= 0x80)
-  {
-    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII;
-    if (unlikely (unicode->is_default_ignorable (u)))
-    {
-      buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
-      props |=  UPROPS_MASK_IGNORABLE;
-      if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ;
-      else if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ;
-      /* Mongolian Free Variation Selectors need to be remembered
-       * because although we need to hide them like default-ignorables,
-       * they need to non-ignorable during shaping.  This is similar to
-       * what we do for joiners in Indic-like shapers, but since the
-       * FVSes are GC=Mn, we have use a separate bit to remember them.
-       * Fixes:
-       * https://github.com/harfbuzz/harfbuzz/issues/234 */
-      else if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN;
-      /* TAG characters need similar treatment. Fixes:
-       * https://github.com/harfbuzz/harfbuzz/issues/463 */
-      else if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
-      /* COMBINING GRAPHEME JOINER should not be skipped; at least some times.
-       * https://github.com/harfbuzz/harfbuzz/issues/554 */
-      else if (unlikely (u == 0x034Fu))
-      {
-        buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CGJ;
-        props |= UPROPS_MASK_HIDDEN;
-      }
-    }
-    else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat)))
-    {
-      /* The above check is just an optimization to let in only things we need further
-       * processing on. */
-
-      /* Only Mn and Mc can have non-zero ccc:
-       * https://unicode.org/policies/stability_policy.html#Property_Value
-       * """
-       * Canonical_Combining_Class, General_Category
-       * All characters other than those with General_Category property values
-       * Spacing_Mark (Mc) and Nonspacing_Mark (Mn) have the Canonical_Combining_Class
-       * property value 0.
-       * 1.1.5+
-       * """
-       *
-       * Also, all Mn's that are Default_Ignorable, have ccc=0, hence
-       * the "else if".
-       */
-      props |= unicode->modified_combining_class (info->codepoint)<<8;
-
-      /* Recategorize emoji skin-tone modifiers as Unicode mark, so they
-       * behave correctly in non-native directionality.  They originally
-       * are MODIFIER_SYMBOL.  Fixes:
-       * https://github.com/harfbuzz/harfbuzz/issues/169
-       */
-      if (unlikely (hb_in_range (u, 0x1F3FBu, 0x1F3FFu)))
-      {
-        props = gen_cat = HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
-      }
-    }
-  }
-
-  info->unicode_props() = props;
-}
-
-static inline void
-_hb_glyph_info_set_general_category (hb_glyph_info_t *info,
-                                     hb_unicode_general_category_t gen_cat)
-{
-  /* Clears top-byte. */
-  info->unicode_props() = (unsigned int) gen_cat | (info->unicode_props() & (0xFF & ~UPROPS_MASK_GEN_CAT));
-}
-
-static inline hb_unicode_general_category_t
-_hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
-{
-  return (hb_unicode_general_category_t) (info->unicode_props() & UPROPS_MASK_GEN_CAT);
-}
-
-static inline bool
-_hb_glyph_info_is_unicode_mark (const hb_glyph_info_t *info)
-{
-  return HB_UNICODE_GENERAL_CATEGORY_IS_MARK (info->unicode_props() & UPROPS_MASK_GEN_CAT);
-}
-static inline void
-_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
-                                             unsigned int modified_class)
-{
-  if (unlikely (!_hb_glyph_info_is_unicode_mark (info)))
-    return;
-  info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF);
-}
-static inline unsigned int
-_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
-}
-
-
-/* Loop over grapheme. Based on foreach_cluster(). */
-#define foreach_grapheme(buffer, start, end) \
-  for (unsigned int \
-       _count = buffer->len, \
-       start = 0, end = _count ? _next_grapheme (buffer, 0) : 0; \
-       start < _count; \
-       start = end, end = _next_grapheme (buffer, start))
-
-static inline unsigned int
-_next_grapheme (hb_buffer_t *buffer, unsigned int start)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  while (++start < count && _hb_glyph_info_is_unicode_mark (&info[start]))
-    ;
-
-  return start;
-}
-
-
-#define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info)))
-
-static inline bool
-_hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_get_general_category (info) ==
-         HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
-}
-static inline void
-_hb_glyph_info_set_unicode_space_fallback_type (hb_glyph_info_t *info, hb_unicode_funcs_t::space_t s)
-{
-  if (unlikely (!_hb_glyph_info_is_unicode_space (info)))
-    return;
-  info->unicode_props() = (((unsigned int) s)<<8) | (info->unicode_props() & 0xFF);
-}
-static inline hb_unicode_funcs_t::space_t
-_hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_space (info) ?
-         (hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) :
-         hb_unicode_funcs_t::NOT_SPACE;
-}
-
-static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
-
-static inline hb_bool_t
-_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
-{
-  return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
-         !_hb_glyph_info_ligated (info);
-}
-static inline hb_bool_t
-_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
-{
-  return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
-          == UPROPS_MASK_IGNORABLE) &&
-         !_hb_glyph_info_ligated (info);
-}
-static inline void
-_hb_glyph_info_unhide (hb_glyph_info_t *info)
-{
-  info->unicode_props() &= ~ UPROPS_MASK_HIDDEN;
-}
-
-static inline bool
-_hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_get_general_category (info) ==
-         HB_UNICODE_GENERAL_CATEGORY_FORMAT;
-}
-static inline hb_bool_t
-_hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ);
-}
-static inline hb_bool_t
-_hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ);
-}
-static inline hb_bool_t
-_hb_glyph_info_is_joiner (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & (UPROPS_MASK_Cf_ZWNJ|UPROPS_MASK_Cf_ZWJ));
-}
-static inline void
-_hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
-{
-  if (!_hb_glyph_info_is_unicode_format (info))
-    return;
-  info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ;
-}
-
-/* lig_props: aka lig_id / lig_comp
- *
- * When a ligature is formed:
- *
- *   - The ligature glyph and any marks in between all the same newly allocated
- *     lig_id,
- *   - The ligature glyph will get lig_num_comps set to the number of components
- *   - The marks get lig_comp > 0, reflecting which component of the ligature
- *     they were applied to.
- *   - This is used in GPOS to attach marks to the right component of a ligature
- *     in MarkLigPos,
- *   - Note that when marks are ligated together, much of the above is skipped
- *     and the current lig_id reused.
- *
- * When a multiple-substitution is done:
- *
- *   - All resulting glyphs will have lig_id = 0,
- *   - The resulting glyphs will have lig_comp = 0, 1, 2, ... respectively.
- *   - This is used in GPOS to attach marks to the first component of a
- *     multiple substitution in MarkBasePos.
- *
- * The numbers are also used in GPOS to do mark-to-mark positioning only
- * to marks that belong to the same component of the same ligature.
- */
-
-static inline void
-_hb_glyph_info_clear_lig_props (hb_glyph_info_t *info)
-{
-  info->lig_props() = 0;
-}
-
-#define IS_LIG_BASE 0x10
-
-static inline void
-_hb_glyph_info_set_lig_props_for_ligature (hb_glyph_info_t *info,
-                                           unsigned int lig_id,
-                                           unsigned int lig_num_comps)
-{
-  info->lig_props() = (lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F);
-}
-
-static inline void
-_hb_glyph_info_set_lig_props_for_mark (hb_glyph_info_t *info,
-                                       unsigned int lig_id,
-                                       unsigned int lig_comp)
-{
-  info->lig_props() = (lig_id << 5) | (lig_comp & 0x0F);
-}
-
-static inline void
-_hb_glyph_info_set_lig_props_for_component (hb_glyph_info_t *info, unsigned int comp)
-{
-  _hb_glyph_info_set_lig_props_for_mark (info, 0, comp);
-}
-
-static inline unsigned int
-_hb_glyph_info_get_lig_id (const hb_glyph_info_t *info)
-{
-  return info->lig_props() >> 5;
-}
-
-static inline bool
-_hb_glyph_info_ligated_internal (const hb_glyph_info_t *info)
-{
-  return !!(info->lig_props() & IS_LIG_BASE);
-}
-
-static inline unsigned int
-_hb_glyph_info_get_lig_comp (const hb_glyph_info_t *info)
-{
-  if (_hb_glyph_info_ligated_internal (info))
-    return 0;
-  else
-    return info->lig_props() & 0x0F;
-}
-
-static inline unsigned int
-_hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info)
-{
-  if ((info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE) &&
-      _hb_glyph_info_ligated_internal (info))
-    return info->lig_props() & 0x0F;
-  else
-    return 1;
-}
-
-static inline uint8_t
-_hb_allocate_lig_id (hb_buffer_t *buffer) {
-  uint8_t lig_id = buffer->next_serial () & 0x07;
-  if (unlikely (!lig_id))
-    lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
-  return lig_id;
-}
-
-/* glyph_props: */
-
-static inline void
-_hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props)
-{
-  info->glyph_props() = props;
-}
-
-static inline unsigned int
-_hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info)
-{
-  return info->glyph_props();
-}
-
-static inline bool
-_hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
-}
-
-static inline bool
-_hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE);
-}
-
-static inline bool
-_hb_glyph_info_is_mark (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
-}
-
-static inline bool
-_hb_glyph_info_substituted (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
-}
-
-static inline bool
-_hb_glyph_info_ligated (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
-}
-
-static inline bool
-_hb_glyph_info_multiplied (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
-}
-
-static inline bool
-_hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
-}
-
-static inline void
-_hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
-{
-  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
-                           HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
-}
-
-static inline void
-_hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
-{
-  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
-}
-
-
-/* Allocation / deallocation. */
-
-static inline void
-_hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props);
-}
-
-static inline void
-_hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props);
-}
-
-static inline void
-_hb_buffer_assert_unicode_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ASSERT_VAR (buffer, unicode_props);
-}
-
-static inline void
-_hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
-  HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
-  HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
-}
-
-static inline void
-_hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
-}
-
-static inline void
-_hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
-  HB_BUFFER_ASSERT_VAR (buffer, lig_props);
-  HB_BUFFER_ASSERT_VAR (buffer, syllable);
-}
-
-/* Make sure no one directly touches our props... */
-#undef unicode_props0
-#undef unicode_props1
-#undef lig_props
-#undef glyph_props
-
-#endif /* HB_OT_LAYOUT_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -28,232 +28,201 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-open-type-private.hh"
-#include "hb-ot-layout-private.hh"
-#include "hb-ot-map-private.hh"
+#include "hb-open-type.hh"
+#include "hb-ot-layout.hh"
+#include "hb-ot-face.hh"
+#include "hb-ot-map.hh"
+#include "hb-map.hh"
 
+#include "hb-ot-kern-table.hh"
+#include "hb-ot-gasp-table.hh" // Just so we compile it; unused otherwise.
 #include "hb-ot-layout-gdef-table.hh"
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
+#include "hb-ot-layout-base-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-name-table.hh"
+#include "hb-ot-os2-table.hh"
 
-// Just so we compile them; unused otherwise:
-#include "hb-ot-layout-base-table.hh"
-#include "hb-ot-layout-jstf-table.hh"
-#include "hb-ot-color-colr-table.hh"
-#include "hb-ot-color-cpal-table.hh"
-#include "hb-ot-color-sbix-table.hh"
-#include "hb-ot-color-svg-table.hh"
-#include "hb-ot-name-table.hh"
-#include "hb-map-private.hh"
+#include "hb-aat-layout-lcar-table.hh"
+#include "hb-aat-layout-morx-table.hh"
+
+
+/**
+ * SECTION:hb-ot-layout
+ * @title: hb-ot-layout
+ * @short_description: OpenType Layout
+ * @include: hb-ot.h
+ *
+ * Functions for querying OpenType Layout features in the font face.
+ **/
 
 
-hb_ot_layout_t *
-_hb_ot_layout_create (hb_face_t *face)
-{
-  hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
-  if (unlikely (!layout))
-    return nullptr;
-
-  layout->gdef_blob = OT::Sanitizer<OT::GDEF>().sanitize (face->reference_table (HB_OT_TAG_GDEF));
-  layout->gdef = layout->gdef_blob->as<OT::GDEF> ();
+/*
+ * kern
+ */
 
-  layout->gsub_blob = OT::Sanitizer<OT::GSUB>().sanitize (face->reference_table (HB_OT_TAG_GSUB));
-  layout->gsub = layout->gsub_blob->as<OT::GSUB> ();
-
-  layout->gpos_blob = OT::Sanitizer<OT::GPOS>().sanitize (face->reference_table (HB_OT_TAG_GPOS));
-  layout->gpos = layout->gpos_blob->as<OT::GPOS> ();
-
-  layout->math.init (face);
-  layout->fvar.init (face);
-  layout->avar.init (face);
+bool
+hb_ot_layout_has_kerning (hb_face_t *face)
+{
+  return face->table.kern->has_data ();
+}
 
-  {
-    /*
-     * The ugly business of blacklisting individual fonts' tables happen here!
-     * See this thread for why we finally had to bend in and do this:
-     * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
-     */
-    unsigned int gdef_len = layout->gdef_blob->length;
-    unsigned int gsub_len = layout->gsub_blob->length;
-    unsigned int gpos_len = layout->gpos_blob->length;
-    if (0
-      /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
-      || (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
-      || (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
-      || (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
-      || (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
-      || (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len)
-      /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
-      || (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len)
-    )
-    {
-      /* In certain versions of Times New Roman Italic and Bold Italic,
-       * ASCII double quotation mark U+0022, mapped to glyph 5, has wrong
-       * glyph class 3 (mark) in GDEF.  Nuke the GDEF to avoid zero-width
-       * double-quote.  See:
-       * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
-       */
-     if (3 == layout->gdef->get_glyph_class (5))
-       layout->gdef = &Null(OT::GDEF);
-    }
-    else if (0
-      /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c  tahoma.ttf from Windows 8 */
-      || (898 == gdef_len && 46470 == gpos_len && 12554 == gsub_len)
-      /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc  tahomabd.ttf from Windows 8 */
-      || (910 == gdef_len && 47732 == gpos_len && 12566 == gsub_len)
-      /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e  tahoma.ttf from Windows 8.1 */
-      || (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len)
-      /* sha1sum:6d400781948517c3c0441ba42acb309584b73033  tahomabd.ttf from Windows 8.1 */
-      || (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len)
-      /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (964 == gdef_len && 60072 == gpos_len && 23836 == gsub_len)
-      /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (976 == gdef_len && 61456 == gpos_len && 23832 == gsub_len)
-      /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846  tahoma.ttf from Windows 10 */
-      || (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len)
-      /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343  tahomabd.ttf from Windows 10 */
-      || (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len)
-      /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (1006 == gdef_len && 61346 == gpos_len && 24576 == gsub_len)
-      /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (1018 == gdef_len && 62828 == gpos_len && 24572 == gsub_len)
-      /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5  tahoma.ttf from Windows 10 AU */
-      || (1006 == gdef_len && 61352 == gpos_len && 24576 == gsub_len)
-      /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2  tahomabd.ttf from Windows 10 AU */
-      || (1018 == gdef_len && 62834 == gpos_len && 24572 == gsub_len)
-      /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7  Tahoma.ttf from Mac OS X 10.9 */
-      || (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len)
-      /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba  Tahoma Bold.ttf from Mac OS X 10.9 */
-      || (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len)
-      /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc  himalaya.ttf from Windows 7 */
-      || (180 == gdef_len && 7254 == gpos_len && 13054 == gsub_len)
-      /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0  himalaya.ttf from Windows 8 */
-      || (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len)
-      /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427  himalaya.ttf from Windows 8.1 */
-      || (192 == gdef_len && 7254 == gpos_len && 12690 == gsub_len)
-      /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44  cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
-      /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371  cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
-      || (188 == gdef_len && 3852 == gpos_len && 248 == gsub_len)
-      /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f  cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
-      /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b  cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
-      || (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len)
-      /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
-      || (1058 == gdef_len && 11818 == gpos_len && 47032 == gsub_len)
-      /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
-      || (1046 == gdef_len && 12600 == gpos_len && 47030 == gsub_len)
-      /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
-      || (1058 == gdef_len && 16770 == gpos_len && 71796 == gsub_len)
-      /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
-      || (1046 == gdef_len && 17862 == gpos_len && 71790 == gsub_len)
-      /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
-      || (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len)
-      /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
-      || (1058 == gdef_len && 17514 == gpos_len && 71794 == gsub_len)
-      /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
-      || (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len)
-      /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
-      || (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len)
-      /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85  Padauk.ttf
-       *  "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
-      || (1004 == gdef_len && 14836 == gpos_len && 59092 == gsub_len)
-    )
-    {
-      /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks
-       * such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya,
-       * and the version of Cantarell shipped by Ubuntu 16.04.
-       * Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing.
-       * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
-       *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
-       *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
-       */
-      layout->gdef = &Null(OT::GDEF);
-    }
-  }
+bool
+hb_ot_layout_has_machine_kerning (hb_face_t *face)
+{
+  return face->table.kern->has_state_machine ();
+}
 
-  layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
-  layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
-
-  layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
-  layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
-
-  if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) ||
-                (layout->gpos_lookup_count && !layout->gpos_accels)))
-  {
-    _hb_ot_layout_destroy (layout);
-    return nullptr;
-  }
-
-  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
-    layout->gsub_accels[i].init (layout->gsub->get_lookup (i));
-  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
-    layout->gpos_accels[i].init (layout->gpos->get_lookup (i));
-
-  return layout;
+bool
+hb_ot_layout_has_cross_kerning (hb_face_t *face)
+{
+  return face->table.kern->has_cross_stream ();
 }
 
 void
-_hb_ot_layout_destroy (hb_ot_layout_t *layout)
+hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
+                   hb_font_t *font,
+                   hb_buffer_t  *buffer)
 {
-  if (layout->gsub_accels)
-    for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
-      layout->gsub_accels[i].fini ();
-  if (layout->gpos_accels)
-    for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
-      layout->gpos_accels[i].fini ();
+  hb_blob_t *blob = font->face->table.kern.get_blob ();
+  const AAT::kern& kern = *blob->as<AAT::kern> ();
 
-  free (layout->gsub_accels);
-  free (layout->gpos_accels);
+  AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
 
-  hb_blob_destroy (layout->gdef_blob);
-  hb_blob_destroy (layout->gsub_blob);
-  hb_blob_destroy (layout->gpos_blob);
-
-  layout->math.fini ();
-  layout->fvar.fini ();
-  layout->avar.fini ();
-
-  free (layout);
+  kern.apply (&c);
 }
 
-// static inline const OT::BASE&
-// _get_base (hb_face_t *face)
-// {
-//   if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::BASE);
-//   hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-//   return *(layout->base.get ());
-// }
-
-static inline const OT::GDEF&
-_get_gdef (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GDEF);
-  return *hb_ot_layout_from_face (face)->gdef;
-}
-static inline const OT::GSUB&
-_get_gsub (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GSUB);
-  return *hb_ot_layout_from_face (face)->gsub;
-}
-static inline const OT::GPOS&
-_get_gpos (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GPOS);
-  return *hb_ot_layout_from_face (face)->gpos;
-}
 
 /*
  * GDEF
  */
 
+bool
+OT::GDEF::is_blacklisted (hb_blob_t *blob,
+                          hb_face_t *face) const
+{
+  /* The ugly business of blacklisting individual fonts' tables happen here!
+   * See this thread for why we finally had to bend in and do this:
+   * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
+   *
+   * In certain versions of Times New Roman Italic and Bold Italic,
+   * ASCII double quotation mark U+0022 has wrong glyph class 3 (mark)
+   * in GDEF.  Many versions of Tahoma have bad GDEF tables that
+   * incorrectly classify some spacing marks such as certain IPA
+   * symbols as glyph class 3. So do older versions of Microsoft
+   * Himalaya, and the version of Cantarell shipped by Ubuntu 16.04.
+   *
+   * Nuke the GDEF tables of to avoid unwanted width-zeroing.
+   *
+   * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
+   *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
+   *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
+   */
+#define ENCODE(x,y,z) (((uint64_t) (x) << 48) | ((uint64_t) (y) << 24) | (uint64_t) (z))
+  switch ENCODE(blob->length,
+                face->table.GSUB->table.get_length (),
+                face->table.GPOS->table.get_length ())
+  {
+    /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
+    case ENCODE (442, 2874, 42038):
+    /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
+    case ENCODE (430, 2874, 40662):
+    /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
+    case ENCODE (442, 2874, 39116):
+    /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
+    case ENCODE (430, 2874, 39374):
+    /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
+    case ENCODE (490, 3046, 41638):
+    /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
+    case ENCODE (478, 3046, 41902):
+    /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c  tahoma.ttf from Windows 8 */
+    case ENCODE (898, 12554, 46470):
+    /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc  tahomabd.ttf from Windows 8 */
+    case ENCODE (910, 12566, 47732):
+    /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e  tahoma.ttf from Windows 8.1 */
+    case ENCODE (928, 23298, 59332):
+    /* sha1sum:6d400781948517c3c0441ba42acb309584b73033  tahomabd.ttf from Windows 8.1 */
+    case ENCODE (940, 23310, 60732):
+    /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+    case ENCODE (964, 23836, 60072):
+    /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+    case ENCODE (976, 23832, 61456):
+    /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846  tahoma.ttf from Windows 10 */
+    case ENCODE (994, 24474, 60336):
+    /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343  tahomabd.ttf from Windows 10 */
+    case ENCODE (1006, 24470, 61740):
+    /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+    case ENCODE (1006, 24576, 61346):
+    /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+    case ENCODE (1018, 24572, 62828):
+    /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5  tahoma.ttf from Windows 10 AU */
+    case ENCODE (1006, 24576, 61352):
+    /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2  tahomabd.ttf from Windows 10 AU */
+    case ENCODE (1018, 24572, 62834):
+    /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7  Tahoma.ttf from Mac OS X 10.9 */
+    case ENCODE (832, 7324, 47162):
+    /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba  Tahoma Bold.ttf from Mac OS X 10.9 */
+    case ENCODE (844, 7302, 45474):
+    /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc  himalaya.ttf from Windows 7 */
+    case ENCODE (180, 13054, 7254):
+    /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0  himalaya.ttf from Windows 8 */
+    case ENCODE (192, 12638, 7254):
+    /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427  himalaya.ttf from Windows 8.1 */
+    case ENCODE (192, 12690, 7254):
+    /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44  cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
+    /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371  cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
+    case ENCODE (188, 248, 3852):
+    /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f  cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
+    /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b  cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
+    case ENCODE (188, 264, 3426):
+    /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
+    case ENCODE (1058, 47032, 11818):
+    /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
+    case ENCODE (1046, 47030, 12600):
+    /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
+    case ENCODE (1058, 71796, 16770):
+    /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
+    case ENCODE (1046, 71790, 17862):
+    /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
+    case ENCODE (1046, 71788, 17112):
+    /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
+    case ENCODE (1058, 71794, 17514):
+    /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
+    case ENCODE (1330, 109904, 57938):
+    /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
+    case ENCODE (1330, 109904, 58972):
+    /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85  Padauk.ttf
+     *  "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
+    case ENCODE (1004, 59092, 14836):
+      return true;
+#undef ENCODE
+  }
+  return false;
+}
+
+static void
+_hb_ot_layout_set_glyph_props (hb_font_t *font,
+                               hb_buffer_t *buffer)
+{
+  _hb_buffer_assert_gsubgpos_vars (buffer);
+
+  const OT::GDEF &gdef = *font->face->table.GDEF->table;
+  unsigned int count = buffer->len;
+  for (unsigned int i = 0; i < count; i++)
+  {
+    _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
+    _hb_glyph_info_clear_lig_props (&buffer->info[i]);
+    buffer->info[i].syllable() = 0;
+  }
+}
+
+/* Public API */
+
 hb_bool_t
 hb_ot_layout_has_glyph_classes (hb_face_t *face)
 {
-  return _get_gdef (face).has_glyph_classes ();
+  return face->table.GDEF->table->has_glyph_classes ();
 }
 
 /**
@@ -265,7 +234,7 @@
 hb_ot_layout_get_glyph_class (hb_face_t      *face,
                               hb_codepoint_t  glyph)
 {
-  return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph);
+  return (hb_ot_layout_glyph_class_t) face->table.GDEF->table->get_glyph_class (glyph);
 }
 
 /**
@@ -278,7 +247,7 @@
                                   hb_ot_layout_glyph_class_t  klass,
                                   hb_set_t                   *glyphs /* OUT */)
 {
-  return _get_gdef (face).get_glyphs_in_class (klass, glyphs);
+  return face->table.GDEF->table->get_glyphs_in_class (klass, glyphs);
 }
 
 unsigned int
@@ -288,7 +257,10 @@
                                 unsigned int   *point_count /* IN/OUT */,
                                 unsigned int   *point_array /* OUT */)
 {
-  return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, point_array);
+  return face->table.GDEF->table->get_attach_points (glyph,
+                                                     start_offset,
+                                                     point_count,
+                                                     point_array);
 }
 
 unsigned int
@@ -299,7 +271,15 @@
                                   unsigned int   *caret_count /* IN/OUT */,
                                   hb_position_t  *caret_array /* OUT */)
 {
-  return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
+  unsigned int result_caret_count = 0;
+  unsigned int result = font->face->table.GDEF->table->get_lig_carets (font, direction, glyph, start_offset, &result_caret_count, caret_array);
+  if (result)
+  {
+    if (caret_count) *caret_count = result_caret_count;
+  }
+  else
+    result = font->face->table.lcar->get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
+  return result;
 }
 
 
@@ -307,13 +287,45 @@
  * GSUB/GPOS
  */
 
+bool
+OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED,
+                          hb_face_t *face) const
+{
+  /* Mac OS X prefers morx over GSUB.  It also ships with various Indic fonts,
+   * all by 'MUTF' foundry (Tamil MN, Tamil Sangam MN, etc.), that have broken
+   * GSUB/GPOS tables.  Some have GSUB with zero scripts, those are ignored by
+   * our morx/GSUB preference code.  But if GSUB has non-zero scripts, we tend
+   * to prefer it over morx because we want to be consistent with other OpenType
+   * shapers.
+   *
+   * To work around broken Indic Mac system fonts, we ignore GSUB table if
+   * OS/2 VendorId is 'MUTF' and font has morx table as well.
+   *
+   * https://github.com/harfbuzz/harfbuzz/issues/1410
+   * https://github.com/harfbuzz/harfbuzz/issues/1348
+   * https://github.com/harfbuzz/harfbuzz/issues/1391
+   */
+  if (unlikely (face->table.OS2->achVendID == HB_TAG ('M','U','T','F') &&
+                face->table.morx->has_data ()))
+    return true;
+
+  return false;
+}
+
+bool
+OT::GPOS::is_blacklisted (hb_blob_t *blob HB_UNUSED,
+                          hb_face_t *face HB_UNUSED) const
+{
+  return false;
+}
+
 static const OT::GSUBGPOS&
 get_gsubgpos_table (hb_face_t *face,
                     hb_tag_t   table_tag)
 {
   switch (table_tag) {
-    case HB_OT_TAG_GSUB: return _get_gsub (face);
-    case HB_OT_TAG_GPOS: return _get_gpos (face);
+    case HB_OT_TAG_GSUB: return *face->table.GSUB->table;
+    case HB_OT_TAG_GPOS: return *face->table.GPOS->table;
     default:             return Null(OT::GSUBGPOS);
   }
 }
@@ -324,7 +336,7 @@
                                     hb_tag_t      table_tag,
                                     unsigned int  start_offset,
                                     unsigned int *script_count /* IN/OUT */,
-                                    hb_tag_t     *script_tags /* OUT */)
+                                    hb_tag_t     *script_tags  /* OUT */)
 {
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
 
@@ -370,17 +382,36 @@
                                   unsigned int   *script_index,
                                   hb_tag_t       *chosen_script)
 {
+  const hb_tag_t *t;
+  for (t = script_tags; *t; t++);
+  return hb_ot_layout_table_select_script (face, table_tag, t - script_tags, script_tags, script_index, chosen_script);
+}
+
+/**
+ * hb_ot_layout_table_select_script:
+ *
+ * Since: 2.0.0
+ **/
+hb_bool_t
+hb_ot_layout_table_select_script (hb_face_t      *face,
+                                  hb_tag_t        table_tag,
+                                  unsigned int    script_count,
+                                  const hb_tag_t *script_tags,
+                                  unsigned int   *script_index  /* OUT */,
+                                  hb_tag_t       *chosen_script /* OUT */)
+{
   static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX), "");
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+  unsigned int i;
 
-  while (*script_tags)
+  for (i = 0; i < script_count; i++)
   {
-    if (g.find_script_index (*script_tags, script_index)) {
+    if (g.find_script_index (script_tags[i], script_index))
+    {
       if (chosen_script)
-        *chosen_script = *script_tags;
+        *chosen_script = script_tags[i];
       return true;
     }
-    script_tags++;
   }
 
   /* try finding 'DFLT' */
@@ -416,14 +447,14 @@
                                      hb_tag_t      table_tag,
                                      unsigned int  start_offset,
                                      unsigned int *feature_count /* IN/OUT */,
-                                     hb_tag_t     *feature_tags /* OUT */)
+                                     hb_tag_t     *feature_tags  /* OUT */)
 {
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
 
   return g.get_feature_tags (start_offset, feature_count, feature_tags);
 }
 
-hb_bool_t
+bool
 hb_ot_layout_table_find_feature (hb_face_t    *face,
                                  hb_tag_t      table_tag,
                                  hb_tag_t      feature_tag,
@@ -452,7 +483,7 @@
                                        unsigned int  script_index,
                                        unsigned int  start_offset,
                                        unsigned int *language_count /* IN/OUT */,
-                                       hb_tag_t     *language_tags /* OUT */)
+                                       hb_tag_t     *language_tags  /* OUT */)
 {
   const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
 
@@ -466,13 +497,38 @@
                                    hb_tag_t      language_tag,
                                    unsigned int *language_index)
 {
+  return hb_ot_layout_script_select_language (face,
+                                              table_tag,
+                                              script_index,
+                                              1,
+                                              &language_tag,
+                                              language_index);
+}
+
+/**
+ * hb_ot_layout_script_select_language:
+ *
+ * Since: 2.0.0
+ **/
+hb_bool_t
+hb_ot_layout_script_select_language (hb_face_t      *face,
+                                     hb_tag_t        table_tag,
+                                     unsigned int    script_index,
+                                     unsigned int    language_count,
+                                     const hb_tag_t *language_tags,
+                                     unsigned int   *language_index /* OUT */)
+{
   static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX), "");
   const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
+  unsigned int i;
 
-  if (s.find_lang_sys_index (language_tag, language_index))
-    return true;
+  for (i = 0; i < language_count; i++)
+  {
+    if (s.find_lang_sys_index (language_tags[i], language_index))
+      return true;
+  }
 
-  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
+  /* try finding 'dflt' */
   if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
     return false;
 
@@ -524,7 +580,7 @@
                                            unsigned int  script_index,
                                            unsigned int  language_index,
                                            unsigned int  start_offset,
-                                           unsigned int *feature_count /* IN/OUT */,
+                                           unsigned int *feature_count   /* IN/OUT */,
                                            unsigned int *feature_indexes /* OUT */)
 {
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
@@ -540,7 +596,7 @@
                                         unsigned int  language_index,
                                         unsigned int  start_offset,
                                         unsigned int *feature_count /* IN/OUT */,
-                                        hb_tag_t     *feature_tags /* OUT */)
+                                        hb_tag_t     *feature_tags  /* OUT */)
 {
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
   const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
@@ -594,7 +650,7 @@
                                   hb_tag_t      table_tag,
                                   unsigned int  feature_index,
                                   unsigned int  start_offset,
-                                  unsigned int *lookup_count /* IN/OUT */,
+                                  unsigned int *lookup_count   /* IN/OUT */,
                                   unsigned int *lookup_indexes /* OUT */)
 {
   return hb_ot_layout_feature_with_variations_get_lookups (face,
@@ -615,156 +671,174 @@
 hb_ot_layout_table_get_lookup_count (hb_face_t    *face,
                                      hb_tag_t      table_tag)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return 0;
-  switch (table_tag)
-  {
-    case HB_OT_TAG_GSUB:
-    {
-      return hb_ot_layout_from_face (face)->gsub_lookup_count;
-    }
-    case HB_OT_TAG_GPOS:
-    {
-      return hb_ot_layout_from_face (face)->gpos_lookup_count;
-    }
-  }
-  return 0;
+  return get_gsubgpos_table (face, table_tag).get_lookup_count ();
 }
 
-static void
-_hb_ot_layout_collect_lookups_lookups (hb_face_t      *face,
-                                       hb_tag_t        table_tag,
-                                       unsigned int    feature_index,
-                                       hb_set_t       *lookup_indexes /* OUT */)
+
+struct hb_collect_features_context_t
 {
-  unsigned int lookup_indices[32];
-  unsigned int offset, len;
+  hb_collect_features_context_t (hb_face_t       *face,
+                                 hb_tag_t         table_tag,
+                                 hb_set_t        *feature_indexes_)
+    : g (get_gsubgpos_table (face, table_tag)),
+      feature_indexes (feature_indexes_),
+      script_count(0),langsys_count(0) {}
+
+  bool visited (const OT::Script &s)
+  {
+    /* We might have Null() object here.  Don't want to involve
+     * that in the memoize.  So, detect empty objects and return. */
+    if (unlikely (!s.has_default_lang_sys () &&
+                  !s.get_lang_sys_count ()))
+      return true;
+
+    if (script_count++ > HB_MAX_SCRIPTS)
+      return true;
 
-  offset = 0;
-  do {
-    len = ARRAY_LENGTH (lookup_indices);
-    hb_ot_layout_feature_get_lookups (face,
-                                      table_tag,
-                                      feature_index,
-                                      offset, &len,
-                                      lookup_indices);
+    return visited (s, visited_script);
+  }
+  bool visited (const OT::LangSys &l)
+  {
+    /* We might have Null() object here.  Don't want to involve
+     * that in the memoize.  So, detect empty objects and return. */
+    if (unlikely (!l.has_required_feature () &&
+                  !l.get_feature_count ()))
+      return true;
+
+    if (langsys_count++ > HB_MAX_LANGSYS)
+      return true;
+
+    return visited (l, visited_langsys);
+  }
 
-    for (unsigned int i = 0; i < len; i++)
-      lookup_indexes->add (lookup_indices[i]);
+  private:
+  template <typename T>
+  bool visited (const T &p, hb_set_t &visited_set)
+  {
+    hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) &p - (uintptr_t) &g);
+     if (visited_set.has (delta))
+      return true;
 
-    offset += len;
-  } while (len == ARRAY_LENGTH (lookup_indices));
-}
+    visited_set.add (delta);
+    return false;
+  }
+
+  public:
+  const OT::GSUBGPOS &g;
+  hb_set_t           *feature_indexes;
+
+  private:
+  hb_set_t visited_script;
+  hb_set_t visited_langsys;
+  unsigned int script_count;
+  unsigned int langsys_count;
+};
 
 static void
-_hb_ot_layout_collect_lookups_features (hb_face_t      *face,
-                                        hb_tag_t        table_tag,
-                                        unsigned int    script_index,
-                                        unsigned int    language_index,
-                                        const hb_tag_t *features,
-                                        hb_set_t       *lookup_indexes /* OUT */)
+langsys_collect_features (hb_collect_features_context_t *c,
+                          const OT::LangSys  &l,
+                          const hb_tag_t     *features)
 {
+  if (c->visited (l)) return;
+
   if (!features)
   {
-    unsigned int required_feature_index;
-    if (hb_ot_layout_language_get_required_feature (face,
-                                                    table_tag,
-                                                    script_index,
-                                                    language_index,
-                                                    &required_feature_index,
-                                                    nullptr))
-      _hb_ot_layout_collect_lookups_lookups (face,
-                                             table_tag,
-                                             required_feature_index,
-                                             lookup_indexes);
-
-    /* All features */
-    unsigned int feature_indices[32];
-    unsigned int offset, len;
+    /* All features. */
+    if (l.has_required_feature ())
+      c->feature_indexes->add (l.get_required_feature_index ());
 
-    offset = 0;
-    do {
-      len = ARRAY_LENGTH (feature_indices);
-      hb_ot_layout_language_get_feature_indexes (face,
-                                                 table_tag,
-                                                 script_index,
-                                                 language_index,
-                                                 offset, &len,
-                                                 feature_indices);
-
-      for (unsigned int i = 0; i < len; i++)
-        _hb_ot_layout_collect_lookups_lookups (face,
-                                               table_tag,
-                                               feature_indices[i],
-                                               lookup_indexes);
-
-      offset += len;
-    } while (len == ARRAY_LENGTH (feature_indices));
+    l.add_feature_indexes_to (c->feature_indexes);
   }
   else
   {
+    /* Ugh. Any faster way? */
     for (; *features; features++)
     {
-      unsigned int feature_index;
-      if (hb_ot_layout_language_find_feature (face,
-                                              table_tag,
-                                              script_index,
-                                              language_index,
-                                              *features,
-                                              &feature_index))
-        _hb_ot_layout_collect_lookups_lookups (face,
-                                               table_tag,
-                                               feature_index,
-                                               lookup_indexes);
+      hb_tag_t feature_tag = *features;
+      unsigned int num_features = l.get_feature_count ();
+      for (unsigned int i = 0; i < num_features; i++)
+      {
+        unsigned int feature_index = l.get_feature_index (i);
+
+        if (feature_tag == c->g.get_feature_tag (feature_index))
+        {
+          c->feature_indexes->add (feature_index);
+          break;
+        }
+      }
     }
   }
 }
 
 static void
-_hb_ot_layout_collect_lookups_languages (hb_face_t      *face,
-                                         hb_tag_t        table_tag,
-                                         unsigned int    script_index,
-                                         const hb_tag_t *languages,
-                                         const hb_tag_t *features,
-                                         hb_set_t       *lookup_indexes /* OUT */)
+script_collect_features (hb_collect_features_context_t *c,
+                         const OT::Script   &s,
+                         const hb_tag_t *languages,
+                         const hb_tag_t *features)
 {
-  _hb_ot_layout_collect_lookups_features (face,
-                                          table_tag,
-                                          script_index,
-                                          HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
-                                          features,
-                                          lookup_indexes);
+  if (c->visited (s)) return;
 
   if (!languages)
   {
-    /* All languages */
-    unsigned int count = hb_ot_layout_script_get_language_tags (face,
-                                                                table_tag,
-                                                                script_index,
-                                                                0, nullptr, nullptr);
+    /* All languages. */
+    if (s.has_default_lang_sys ())
+      langsys_collect_features (c,
+                                s.get_default_lang_sys (),
+                                features);
+
+    unsigned int count = s.get_lang_sys_count ();
     for (unsigned int language_index = 0; language_index < count; language_index++)
-      _hb_ot_layout_collect_lookups_features (face,
-                                              table_tag,
-                                              script_index,
-                                              language_index,
-                                              features,
-                                              lookup_indexes);
+      langsys_collect_features (c,
+                                s.get_lang_sys (language_index),
+                                features);
   }
   else
   {
     for (; *languages; languages++)
     {
       unsigned int language_index;
-      if (hb_ot_layout_script_find_language (face,
-                                             table_tag,
-                                             script_index,
-                                             *languages,
-                                             &language_index))
-        _hb_ot_layout_collect_lookups_features (face,
-                                                table_tag,
-                                                script_index,
-                                                language_index,
-                                                features,
-                                                lookup_indexes);
+      if (s.find_lang_sys_index (*languages, &language_index))
+        langsys_collect_features (c,
+                                  s.get_lang_sys (language_index),
+                                  features);
+    }
+  }
+}
+
+/**
+ * hb_ot_layout_collect_features:
+ *
+ * Since: 1.8.5
+ **/
+void
+hb_ot_layout_collect_features (hb_face_t      *face,
+                               hb_tag_t        table_tag,
+                               const hb_tag_t *scripts,
+                               const hb_tag_t *languages,
+                               const hb_tag_t *features,
+                               hb_set_t       *feature_indexes /* OUT */)
+{
+  hb_collect_features_context_t c (face, table_tag, feature_indexes);
+  if (!scripts)
+  {
+    /* All scripts. */
+    unsigned int count = c.g.get_script_count ();
+    for (unsigned int script_index = 0; script_index < count; script_index++)
+      script_collect_features (&c,
+                               c.g.get_script (script_index),
+                               languages,
+                               features);
+  }
+  else
+  {
+    for (; *scripts; scripts++)
+    {
+      unsigned int script_index;
+      if (c.g.find_script_index (*scripts, &script_index))
+        script_collect_features (&c,
+                                 c.g.get_script (script_index),
+                                 languages,
+                                 features);
     }
   }
 }
@@ -782,37 +856,14 @@
                               const hb_tag_t *features,
                               hb_set_t       *lookup_indexes /* OUT */)
 {
-  if (!scripts)
-  {
-    /* All scripts */
-    unsigned int count = hb_ot_layout_table_get_script_tags (face,
-                                                             table_tag,
-                                                             0, nullptr, nullptr);
-    for (unsigned int script_index = 0; script_index < count; script_index++)
-      _hb_ot_layout_collect_lookups_languages (face,
-                                               table_tag,
-                                               script_index,
-                                               languages,
-                                               features,
-                                               lookup_indexes);
-  }
-  else
-  {
-    for (; *scripts; scripts++)
-    {
-      unsigned int script_index;
-      if (hb_ot_layout_table_find_script (face,
-                                          table_tag,
-                                          *scripts,
-                                          &script_index))
-        _hb_ot_layout_collect_lookups_languages (face,
-                                                 table_tag,
-                                                 script_index,
-                                                 languages,
-                                                 features,
-                                                 lookup_indexes);
-    }
-  }
+  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+
+  hb_set_t feature_indexes;
+  hb_ot_layout_collect_features (face, table_tag, scripts, languages, features, &feature_indexes);
+
+  for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID;
+       hb_set_next (&feature_indexes, &feature_index);)
+    g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes);
 }
 
 /**
@@ -824,13 +875,11 @@
 hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
                                     hb_tag_t      table_tag,
                                     unsigned int  lookup_index,
-                                    hb_set_t     *glyphs_before, /* OUT. May be nullptr */
-                                    hb_set_t     *glyphs_input,  /* OUT. May be nullptr */
-                                    hb_set_t     *glyphs_after,  /* OUT. May be nullptr */
-                                    hb_set_t     *glyphs_output  /* OUT. May be nullptr */)
+                                    hb_set_t     *glyphs_before, /* OUT.  May be NULL */
+                                    hb_set_t     *glyphs_input,  /* OUT.  May be NULL */
+                                    hb_set_t     *glyphs_after,  /* OUT.  May be NULL */
+                                    hb_set_t     *glyphs_output  /* OUT.  May be NULL */)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return;
-
   OT::hb_collect_glyphs_context_t c (face,
                                      glyphs_before,
                                      glyphs_input,
@@ -841,13 +890,13 @@
   {
     case HB_OT_TAG_GSUB:
     {
-      const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
+      const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
       l.collect_glyphs (&c);
       return;
     }
     case HB_OT_TAG_GPOS:
     {
-      const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
+      const OT::PosLookup& l = face->table.GPOS->table->get_lookup (lookup_index);
       l.collect_glyphs (&c);
       return;
     }
@@ -894,7 +943,7 @@
 hb_bool_t
 hb_ot_layout_has_substitution (hb_face_t *face)
 {
-  return &_get_gsub (face) != &Null(OT::GSUB);
+  return face->table.GSUB->table->has_data ();
 }
 
 /**
@@ -909,29 +958,82 @@
                                       unsigned int          glyphs_length,
                                       hb_bool_t             zero_context)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return false;
-  return hb_ot_layout_lookup_would_substitute_fast (face, lookup_index, glyphs, glyphs_length, zero_context);
+  return hb_ot_layout_lookup_would_substitute_fast (face,
+                                                    lookup_index,
+                                                    glyphs, glyphs_length,
+                                                    zero_context);
 }
 
-hb_bool_t
+bool
 hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
                                            unsigned int          lookup_index,
                                            const hb_codepoint_t *glyphs,
                                            unsigned int          glyphs_length,
-                                           hb_bool_t             zero_context)
+                                           bool                  zero_context)
 {
-  if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
+  if (unlikely (lookup_index >= face->table.GSUB->lookup_count)) return false;
   OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
 
-  const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
+  const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
+
+  return l.would_apply (&c, &face->table.GSUB->accels[lookup_index]);
+}
 
-  return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]);
+void
+hb_ot_layout_substitute_start (hb_font_t    *font,
+                               hb_buffer_t  *buffer)
+{
+_hb_ot_layout_set_glyph_props (font, buffer);
 }
 
 void
-hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
+hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
+                                    bool (*filter) (const hb_glyph_info_t *info))
 {
-  OT::GSUB::substitute_start (font, buffer);
+  /* Merge clusters and delete filtered glyphs.
+   * NOTE! We can't use out-buffer as we have positioning data. */
+  unsigned int j = 0;
+  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 (filter (&info[i]))
+    {
+      /* Merge clusters.
+       * Same logic as buffer->delete_glyph(), but for in-place removal. */
+
+      unsigned int cluster = info[i].cluster;
+      if (i + 1 < count && cluster == info[i + 1].cluster)
+        continue; /* Cluster survives; do nothing. */
+
+      if (j)
+      {
+        /* Merge cluster backward. */
+        if (cluster < info[j - 1].cluster)
+        {
+          unsigned int mask = info[i].mask;
+          unsigned int old_cluster = info[j - 1].cluster;
+          for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
+            buffer->set_cluster (info[k - 1], cluster, mask);
+        }
+        continue;
+      }
+
+      if (i + 1 < count)
+        buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
+
+      continue;
+    }
+
+    if (j != i)
+    {
+      info[j] = info[i];
+      pos[j] = pos[i];
+    }
+    j++;
+  }
+  buffer->len = j;
 }
 
 /**
@@ -944,10 +1046,10 @@
                                         unsigned int  lookup_index,
                                         hb_set_t     *glyphs)
 {
-  hb_auto_t<hb_map_t> done_lookups;
+  hb_map_t done_lookups;
   OT::hb_closure_context_t c (face, glyphs, &done_lookups);
 
-  const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index);
+  const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
 
   l.closure (&c, lookup_index);
 }
@@ -965,10 +1067,11 @@
                                          const hb_set_t *lookups,
                                          hb_set_t       *glyphs)
 {
-  hb_auto_t<hb_map_t> done_lookups;
+  hb_map_t done_lookups;
   OT::hb_closure_context_t c (face, glyphs, &done_lookups);
-  const OT::GSUB& gsub = _get_gsub (face);
+  const OT::GSUB& gsub = *face->table.GSUB->table;
 
+  unsigned int iteration_count = 0;
   unsigned int glyphs_length;
   do
   {
@@ -983,7 +1086,8 @@
       for (unsigned int i = 0; i < gsub.get_lookup_count (); i++)
         gsub.get_lookup (i).closure (&c, i);
     }
-  } while (glyphs_length != glyphs->get_population ());
+  } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
+           glyphs_length != glyphs->get_population ());
 }
 
 /*
@@ -993,7 +1097,7 @@
 hb_bool_t
 hb_ot_layout_has_positioning (hb_face_t *face)
 {
-  return &_get_gpos (face) != &Null(OT::GPOS);
+  return face->table.GPOS->table->has_data ();
 }
 
 void
@@ -1020,14 +1124,14 @@
  * Since: 0.9.10
  **/
 hb_bool_t
-hb_ot_layout_get_size_params (hb_face_t    *face,
-                              unsigned int *design_size,       /* OUT.  May be nullptr */
-                              unsigned int *subfamily_id,      /* OUT.  May be nullptr */
-                              unsigned int *subfamily_name_id, /* OUT.  May be nullptr */
-                              unsigned int *range_start,       /* OUT.  May be nullptr */
-                              unsigned int *range_end          /* OUT.  May be nullptr */)
+hb_ot_layout_get_size_params (hb_face_t       *face,
+                              unsigned int    *design_size,       /* OUT.  May be NULL */
+                              unsigned int    *subfamily_id,      /* OUT.  May be NULL */
+                              hb_ot_name_id_t *subfamily_name_id, /* OUT.  May be NULL */
+                              unsigned int    *range_start,       /* OUT.  May be NULL */
+                              unsigned int    *range_end          /* OUT.  May be NULL */)
 {
-  const OT::GPOS &gpos = _get_gpos (face);
+  const OT::GPOS &gpos = *face->table.GPOS->table;
   const hb_tag_t tag = HB_TAG ('s','i','z','e');
 
   unsigned int num_features = gpos.get_feature_count ();
@@ -1040,30 +1144,152 @@
 
       if (params.designSize)
       {
-#define PARAM(a, A) if (a) *a = params.A
-        PARAM (design_size, designSize);
-        PARAM (subfamily_id, subfamilyID);
-        PARAM (subfamily_name_id, subfamilyNameID);
-        PARAM (range_start, rangeStart);
-        PARAM (range_end, rangeEnd);
-#undef PARAM
+        if (design_size) *design_size = params.designSize;
+        if (subfamily_id) *subfamily_id = params.subfamilyID;
+        if (subfamily_name_id) *subfamily_name_id = params.subfamilyNameID;
+        if (range_start) *range_start = params.rangeStart;
+        if (range_end) *range_end = params.rangeEnd;
 
         return true;
       }
     }
   }
 
-#define PARAM(a, A) if (a) *a = 0
-  PARAM (design_size, designSize);
-  PARAM (subfamily_id, subfamilyID);
-  PARAM (subfamily_name_id, subfamilyNameID);
-  PARAM (range_start, rangeStart);
-  PARAM (range_end, rangeEnd);
-#undef PARAM
+  if (design_size) *design_size = 0;
+  if (subfamily_id) *subfamily_id = 0;
+  if (subfamily_name_id) *subfamily_name_id = HB_OT_NAME_ID_INVALID;
+  if (range_start) *range_start = 0;
+  if (range_end) *range_end = 0;
 
   return false;
 }
 
+/**
+ * hb_ot_layout_feature_get_name_ids:
+ * @face: #hb_face_t to work upon
+ * @table_tag: table tag to query, "GSUB" or "GPOS".
+ * @feature_index: index of feature to query.
+ * @label_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
+ *            for a user-interface label for this feature. (May be NULL.)
+ * @tooltip_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
+ *              that an application can use for tooltip text for this
+ *              feature. (May be NULL.)
+ * @sample_id: (out) (allow-none): The ‘name’ table name ID that specifies sample text
+ *             that illustrates the effect of this feature. (May be NULL.)
+ * @num_named_parameters: (out) (allow-none):  Number of named parameters. (May be zero.)
+ * @first_param_id: (out) (allow-none): The first ‘name’ table name ID used to specify
+ *                  strings for user-interface labels for the feature
+ *                  parameters. (Must be zero if numParameters is zero.)
+ *
+ * Fetches name indices from feature parameters for "Stylistic Set" ('ssXX') or
+ * "Character Variant" ('cvXX') features.
+ *
+ * Return value: true if data found, false otherwise
+ *
+ * Since: 2.0.0
+ **/
+hb_bool_t
+hb_ot_layout_feature_get_name_ids (hb_face_t       *face,
+                                   hb_tag_t         table_tag,
+                                   unsigned int     feature_index,
+                                   hb_ot_name_id_t *label_id,             /* OUT.  May be NULL */
+                                   hb_ot_name_id_t *tooltip_id,           /* OUT.  May be NULL */
+                                   hb_ot_name_id_t *sample_id,            /* OUT.  May be NULL */
+                                   unsigned int    *num_named_parameters, /* OUT.  May be NULL */
+                                   hb_ot_name_id_t *first_param_id        /* OUT.  May be NULL */)
+{
+  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+
+  hb_tag_t feature_tag = g.get_feature_tag (feature_index);
+  const OT::Feature &f = g.get_feature (feature_index);
+
+  const OT::FeatureParams &feature_params = f.get_feature_params ();
+  if (&feature_params != &Null (OT::FeatureParams))
+  {
+    const OT::FeatureParamsStylisticSet& ss_params =
+      feature_params.get_stylistic_set_params (feature_tag);
+    if (&ss_params != &Null (OT::FeatureParamsStylisticSet)) /* ssXX */
+    {
+      if (label_id) *label_id = ss_params.uiNameID;
+      // ssXX features don't have the rest
+      if (tooltip_id) *tooltip_id = HB_OT_NAME_ID_INVALID;
+      if (sample_id) *sample_id = HB_OT_NAME_ID_INVALID;
+      if (num_named_parameters) *num_named_parameters = 0;
+      if (first_param_id) *first_param_id = HB_OT_NAME_ID_INVALID;
+      return true;
+    }
+    const OT::FeatureParamsCharacterVariants& cv_params =
+      feature_params.get_character_variants_params (feature_tag);
+    if (&cv_params != &Null (OT::FeatureParamsCharacterVariants)) /* cvXX */
+    {
+      if (label_id) *label_id = cv_params.featUILableNameID;
+      if (tooltip_id) *tooltip_id = cv_params.featUITooltipTextNameID;
+      if (sample_id) *sample_id = cv_params.sampleTextNameID;
+      if (num_named_parameters) *num_named_parameters = cv_params.numNamedParameters;
+      if (first_param_id) *first_param_id = cv_params.firstParamUILabelNameID;
+      return true;
+    }
+  }
+
+  if (label_id) *label_id = HB_OT_NAME_ID_INVALID;
+  if (tooltip_id) *tooltip_id = HB_OT_NAME_ID_INVALID;
+  if (sample_id) *sample_id = HB_OT_NAME_ID_INVALID;
+  if (num_named_parameters) *num_named_parameters = 0;
+  if (first_param_id) *first_param_id = HB_OT_NAME_ID_INVALID;
+  return false;
+}
+
+/**
+ * hb_ot_layout_feature_get_characters:
+ * @face: #hb_face_t to work upon
+ * @table_tag: table tag to query, "GSUB" or "GPOS".
+ * @feature_index: index of feature to query.
+ * @start_offset: In case the resulting char_count was equal to its input value, there
+ *                is a chance there were more characters on the tag so this API can be
+ *                called with an offset till resulting char_count gets to a number
+ *                lower than input buffer (or consider using just a bigger buffer for
+ *                one shot copying).
+ * @char_count: (inout) (allow-none): The count of characters for which this feature
+ *              provides glyph variants. (May be zero.)
+ * @characters: (out caller-allocates) (array length=char_count): A buffer pointer. The Unicode codepoints
+ *              of the characters for which this feature provides glyph variants.
+ *
+ * Fetches characters listed by designer under feature parameters for "Character
+ * Variant" ("cvXX") features.
+ *
+ * Return value: Number of total sample characters in the cvXX feature.
+ *
+ * Since: 2.0.0
+ **/
+unsigned int
+hb_ot_layout_feature_get_characters (hb_face_t      *face,
+                                     hb_tag_t        table_tag,
+                                     unsigned int    feature_index,
+                                     unsigned int    start_offset,
+                                     unsigned int   *char_count, /* IN/OUT.  May be NULL */
+                                     hb_codepoint_t *characters  /* OUT.     May be NULL */)
+{
+  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+
+  hb_tag_t feature_tag = g.get_feature_tag (feature_index);
+  const OT::Feature &f = g.get_feature (feature_index);
+
+  const OT::FeatureParams &feature_params = f.get_feature_params ();
+
+  const OT::FeatureParamsCharacterVariants& cv_params =
+    feature_params.get_character_variants_params(feature_tag);
+
+  unsigned int len = 0;
+  if (char_count && characters && start_offset < cv_params.characters.len)
+  {
+    len = MIN (cv_params.characters.len - start_offset, *char_count);
+    for (unsigned int i = 0; i < len; ++i)
+      characters[i] = cv_params.characters[start_offset + i];
+  }
+  if (char_count) *char_count = len;
+  return cv_params.characters.len;
+}
+
 
 /*
  * Parts of different types are implemented here such that they have direct
@@ -1073,86 +1299,36 @@
 
 struct GSUBProxy
 {
-  static const unsigned int table_index = 0;
-  static const bool inplace = false;
+  static constexpr unsigned table_index = 0u;
+  static constexpr bool inplace = false;
   typedef OT::SubstLookup Lookup;
 
   GSUBProxy (hb_face_t *face) :
-    table (*hb_ot_layout_from_face (face)->gsub),
-    accels (hb_ot_layout_from_face (face)->gsub_accels) {}
+    table (*face->table.GSUB->table),
+    accels (face->table.GSUB->accels) {}
 
   const OT::GSUB &table;
-  const hb_ot_layout_lookup_accelerator_t *accels;
+  const OT::hb_ot_layout_lookup_accelerator_t *accels;
 };
 
 struct GPOSProxy
 {
-  static const unsigned int table_index = 1;
-  static const bool inplace = true;
+  static constexpr unsigned table_index = 1u;
+  static constexpr bool inplace = true;
   typedef OT::PosLookup Lookup;
 
   GPOSProxy (hb_face_t *face) :
-    table (*hb_ot_layout_from_face (face)->gpos),
-    accels (hb_ot_layout_from_face (face)->gpos_accels) {}
+    table (*face->table.GPOS->table),
+    accels (face->table.GPOS->accels) {}
 
   const OT::GPOS &table;
-  const hb_ot_layout_lookup_accelerator_t *accels;
+  const OT::hb_ot_layout_lookup_accelerator_t *accels;
 };
 
 
-struct hb_get_subtables_context_t :
-       OT::hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
-{
-  template <typename Type>
-  static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
-  {
-    const Type *typed_obj = (const Type *) obj;
-    return typed_obj->apply (c);
-  }
-
-  typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
-
-  struct hb_applicable_t
-  {
-    inline void init (const void *obj_, hb_apply_func_t apply_func_)
-    {
-      obj = obj_;
-      apply_func = apply_func_;
-    }
-
-    inline bool apply (OT::hb_ot_apply_context_t *c) const { return apply_func (obj, c); }
-
-    private:
-    const void *obj;
-    hb_apply_func_t apply_func;
-  };
-
-  typedef hb_auto_t<hb_vector_t<hb_applicable_t> > array_t;
-
-  /* Dispatch interface. */
-  inline const char *get_name (void) { return "GET_SUBTABLES"; }
-  template <typename T>
-  inline return_t dispatch (const T &obj)
-  {
-    hb_applicable_t *entry = array.push();
-    entry->init (&obj, apply_to<T>);
-    return HB_VOID;
-  }
-  static return_t default_return_value (void) { return HB_VOID; }
-  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
-
-  hb_get_subtables_context_t (array_t &array_) :
-                              array (array_),
-                              debug_depth (0) {}
-
-  array_t &array;
-  unsigned int debug_depth;
-};
-
 static inline bool
 apply_forward (OT::hb_ot_apply_context_t *c,
-               const hb_ot_layout_lookup_accelerator_t &accel,
-               const hb_get_subtables_context_t::array_t &subtables)
+               const OT::hb_ot_layout_lookup_accelerator_t &accel)
 {
   bool ret = false;
   hb_buffer_t *buffer = c->buffer;
@@ -1163,12 +1339,7 @@
         (buffer->cur().mask & c->lookup_mask) &&
         c->check_glyph_property (&buffer->cur(), c->lookup_props))
      {
-       for (unsigned int i = 0; i < subtables.len; i++)
-         if (subtables[i].apply (c))
-         {
-           applied = true;
-           break;
-         }
+       applied = accel.apply (c);
      }
 
     if (applied)
@@ -1181,8 +1352,7 @@
 
 static inline bool
 apply_backward (OT::hb_ot_apply_context_t *c,
-               const hb_ot_layout_lookup_accelerator_t &accel,
-               const hb_get_subtables_context_t::array_t &subtables)
+               const OT::hb_ot_layout_lookup_accelerator_t &accel)
 {
   bool ret = false;
   hb_buffer_t *buffer = c->buffer;
@@ -1191,14 +1361,8 @@
     if (accel.may_have (buffer->cur().codepoint) &&
         (buffer->cur().mask & c->lookup_mask) &&
         c->check_glyph_property (&buffer->cur(), c->lookup_props))
-    {
-     for (unsigned int i = 0; i < subtables.len; i++)
-       if (subtables[i].apply (c))
-       {
-         ret = true;
-         break;
-       }
-    }
+     ret |= accel.apply (c);
+
     /* The reverse lookup doesn't "advance" cursor (for good reason). */
     buffer->idx--;
 
@@ -1211,7 +1375,7 @@
 static inline void
 apply_string (OT::hb_ot_apply_context_t *c,
               const typename Proxy::Lookup &lookup,
-              const hb_ot_layout_lookup_accelerator_t &accel)
+              const OT::hb_ot_layout_lookup_accelerator_t &accel)
 {
   hb_buffer_t *buffer = c->buffer;
 
@@ -1220,19 +1384,15 @@
 
   c->set_lookup_props (lookup.get_props ());
 
-  hb_get_subtables_context_t::array_t subtables;
-  hb_get_subtables_context_t c_get_subtables (subtables);
-  lookup.dispatch (&c_get_subtables);
-
   if (likely (!lookup.is_reverse ()))
   {
     /* in/out forward substitution/positioning */
-    if (Proxy::table_index == 0)
+    if (Proxy::table_index == 0u)
       buffer->clear_output ();
     buffer->idx = 0;
 
     bool ret;
-    ret = apply_forward (c, accel, subtables);
+    ret = apply_forward (c, accel);
     if (ret)
     {
       if (!Proxy::inplace)
@@ -1244,11 +1404,11 @@
   else
   {
     /* in-place backward substitution/positioning */
-    if (Proxy::table_index == 0)
+    if (Proxy::table_index == 0u)
       buffer->remove_output ();
     buffer->idx = buffer->len - 1;
 
-    apply_backward (c, accel, subtables);
+    apply_backward (c, accel);
   }
 }
 
@@ -1263,7 +1423,7 @@
   OT::hb_ot_apply_context_t c (table_index, font, buffer);
   c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
 
-  for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
+  for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++) {
     const stage_map_t *stage = &stages[table_index][stage_index];
     for (; i < stage->last_lookup; i++)
     {
@@ -1273,6 +1433,11 @@
       c.set_lookup_mask (lookups[table_index][i].mask);
       c.set_auto_zwj (lookups[table_index][i].auto_zwj);
       c.set_auto_zwnj (lookups[table_index][i].auto_zwnj);
+      if (lookups[table_index][i].random)
+      {
+        c.set_random (true);
+        buffer->unsafe_to_break_all ();
+      }
       apply_string<Proxy> (&c,
                            proxy.table.get_lookup (lookup_index),
                            proxy.accels[lookup_index]);
@@ -1302,31 +1467,65 @@
 void
 hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
                                 const OT::SubstLookup &lookup,
-                                const hb_ot_layout_lookup_accelerator_t &accel)
+                                const OT::hb_ot_layout_lookup_accelerator_t &accel)
 {
   apply_string<GSUBProxy> (c, lookup, accel);
 }
 
-
-
+#if 0
+static const OT::BASE& _get_base (hb_face_t *face)
+{
+  return *face->table.BASE;
+}
 
+hb_bool_t
+hb_ot_layout_get_baseline (hb_font_t               *font,
+                           hb_ot_layout_baseline_t  baseline,
+                           hb_direction_t           direction,
+                           hb_tag_t                 script_tag,
+                           hb_tag_t                 language_tag,
+                           hb_position_t           *coord        /* OUT.  May be NULL. */)
+{
+  const OT::BASE &base = _get_base (font->face);
+  bool result = base.get_baseline (font, baseline, direction, script_tag,
+                                   language_tag, coord);
+
+  /* TODO: Simulate https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags#ideographic-em-box */
+  if (!result && coord) *coord = 0;
+
+  if (coord) *coord = font->em_scale_dir (*coord, direction);
+
+  return result;
+}
+
+/* To be moved to public header */
 /*
- * OT::BASE
+ * BASE
  */
 
-// /**
-//  * hb_ot_base_has_data:
-//  * @face: #hb_face_t to test
-//  *
-//  * This function allows to verify the presence of an OpenType BASE table on the
-//  * face.
-//  *
-//  * Return value: true if face has a BASE table, false otherwise
-//  *
-//  * Since: XXX
-//  **/
-// hb_bool_t
-// hb_ot_base_has_data (hb_face_t *face)
-// {
-//   return &_get_base (face) != &Null(OT::BASE);
-// }
+/**
+ * hb_ot_layout_baseline_t:
+ *
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags
+ *
+ * Since: DONTREPLACEME
+ */
+typedef enum {
+  HB_OT_LAYOUT_BASELINE_HANG = HB_TAG('h','a','n','g'),
+  HB_OT_LAYOUT_BASELINE_ICFB = HB_TAG('i','c','f','b'),
+  HB_OT_LAYOUT_BASELINE_ICFT = HB_TAG('i','c','f','t'),
+  HB_OT_LAYOUT_BASELINE_IDEO = HB_TAG('i','d','e','o'),
+  HB_OT_LAYOUT_BASELINE_IDTB = HB_TAG('i','d','t','b'),
+  HB_OT_LAYOUT_BASELINE_MATH = HB_TAG('m','a','t','h'),
+  HB_OT_LAYOUT_BASELINE_ROMN = HB_TAG('r','o','m','n')
+} hb_ot_layout_baseline_t;
+
+HB_EXTERN hb_bool_t
+hb_ot_layout_get_baseline (hb_font_t               *font,
+                           hb_ot_layout_baseline_t  baseline,
+                           hb_direction_t           direction,
+                           hb_tag_t                 script_tag,
+                           hb_tag_t                 language_tag,
+                           hb_position_t           *coord        /* OUT.  May be NULL. */);
+
+#endif
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.h	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.h	Fri Mar 01 16:59:19 2019 -0800
@@ -33,7 +33,7 @@
 
 #include "hb.h"
 
-#include "hb-ot-tag.h"
+#include "hb-ot-name.h"
 
 HB_BEGIN_DECLS
 
@@ -46,6 +46,47 @@
 
 
 /*
+ * Script & Language tags.
+ */
+
+#define HB_OT_TAG_DEFAULT_SCRIPT        HB_TAG ('D', 'F', 'L', 'T')
+#define HB_OT_TAG_DEFAULT_LANGUAGE      HB_TAG ('d', 'f', 'l', 't')
+
+/**
+ * HB_OT_MAX_TAGS_PER_SCRIPT:
+ *
+ * Since: 2.0.0
+ **/
+#define HB_OT_MAX_TAGS_PER_SCRIPT       3u
+/**
+ * HB_OT_MAX_TAGS_PER_LANGUAGE:
+ *
+ * Since: 2.0.0
+ **/
+#define HB_OT_MAX_TAGS_PER_LANGUAGE     3u
+
+HB_EXTERN void
+hb_ot_tags_from_script_and_language (hb_script_t   script,
+                                     hb_language_t language,
+                                     unsigned int *script_count /* IN/OUT */,
+                                     hb_tag_t     *script_tags /* OUT */,
+                                     unsigned int *language_count /* IN/OUT */,
+                                     hb_tag_t     *language_tags /* OUT */);
+
+HB_EXTERN hb_script_t
+hb_ot_tag_to_script (hb_tag_t tag);
+
+HB_EXTERN hb_language_t
+hb_ot_tag_to_language (hb_tag_t tag);
+
+HB_EXTERN void
+hb_ot_tags_to_script_and_language (hb_tag_t       script_tag,
+                                   hb_tag_t       language_tag,
+                                   hb_script_t   *script /* OUT */,
+                                   hb_language_t *language /* OUT */);
+
+
+/*
  * GDEF
  */
 
@@ -111,13 +152,13 @@
                                 hb_tag_t      script_tag,
                                 unsigned int *script_index);
 
-/* Like find_script, but takes zero-terminated array of scripts to test */
 HB_EXTERN hb_bool_t
-hb_ot_layout_table_choose_script (hb_face_t      *face,
+hb_ot_layout_table_select_script (hb_face_t      *face,
                                   hb_tag_t        table_tag,
+                                  unsigned int    script_count,
                                   const hb_tag_t *script_tags,
-                                  unsigned int   *script_index,
-                                  hb_tag_t       *chosen_script);
+                                  unsigned int   *script_index /* OUT */,
+                                  hb_tag_t       *chosen_script /* OUT */);
 
 HB_EXTERN unsigned int
 hb_ot_layout_table_get_feature_tags (hb_face_t    *face,
@@ -135,11 +176,12 @@
                                        hb_tag_t     *language_tags /* OUT */);
 
 HB_EXTERN hb_bool_t
-hb_ot_layout_script_find_language (hb_face_t    *face,
-                                   hb_tag_t      table_tag,
-                                   unsigned int  script_index,
-                                   hb_tag_t      language_tag,
-                                   unsigned int *language_index);
+hb_ot_layout_script_select_language (hb_face_t      *face,
+                                     hb_tag_t        table_tag,
+                                     unsigned int    script_index,
+                                     unsigned int    language_count,
+                                     const hb_tag_t *language_tags,
+                                     unsigned int   *language_index /* OUT */);
 
 HB_EXTERN hb_bool_t
 hb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
@@ -194,6 +236,13 @@
 hb_ot_layout_table_get_lookup_count (hb_face_t    *face,
                                      hb_tag_t      table_tag);
 
+HB_EXTERN void
+hb_ot_layout_collect_features (hb_face_t      *face,
+                               hb_tag_t        table_tag,
+                               const hb_tag_t *scripts,
+                               const hb_tag_t *languages,
+                               const hb_tag_t *features,
+                               hb_set_t       *feature_indexes /* OUT */);
 
 HB_EXTERN void
 hb_ot_layout_collect_lookups (hb_face_t      *face,
@@ -207,10 +256,10 @@
 hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
                                     hb_tag_t      table_tag,
                                     unsigned int  lookup_index,
-                                    hb_set_t     *glyphs_before, /* OUT. May be NULL */
-                                    hb_set_t     *glyphs_input,  /* OUT. May be NULL */
-                                    hb_set_t     *glyphs_after,  /* OUT. May be NULL */
-                                    hb_set_t     *glyphs_output  /* OUT. May be NULL */);
+                                    hb_set_t     *glyphs_before, /* OUT.  May be NULL */
+                                    hb_set_t     *glyphs_input,  /* OUT.  May be NULL */
+                                    hb_set_t     *glyphs_after,  /* OUT.  May be NULL */
+                                    hb_set_t     *glyphs_output  /* OUT.  May be NULL */);
 
 #ifdef HB_NOT_IMPLEMENTED
 typedef struct
@@ -315,29 +364,32 @@
 /* Optical 'size' feature info.  Returns true if found.
  * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
 HB_EXTERN hb_bool_t
-hb_ot_layout_get_size_params (hb_face_t    *face,
-                              unsigned int *design_size,       /* OUT.  May be NULL */
-                              unsigned int *subfamily_id,      /* OUT.  May be NULL */
-                              unsigned int *subfamily_name_id, /* OUT.  May be NULL */
-                              unsigned int *range_start,       /* OUT.  May be NULL */
-                              unsigned int *range_end          /* OUT.  May be NULL */);
+hb_ot_layout_get_size_params (hb_face_t       *face,
+                              unsigned int    *design_size,       /* OUT.  May be NULL */
+                              unsigned int    *subfamily_id,      /* OUT.  May be NULL */
+                              hb_ot_name_id_t *subfamily_name_id, /* OUT.  May be NULL */
+                              unsigned int    *range_start,       /* OUT.  May be NULL */
+                              unsigned int    *range_end          /* OUT.  May be NULL */);
 
 
-/*
- * BASE
- */
-#if 0
+HB_EXTERN hb_bool_t
+hb_ot_layout_feature_get_name_ids (hb_face_t       *face,
+                                   hb_tag_t         table_tag,
+                                   unsigned int     feature_index,
+                                   hb_ot_name_id_t *label_id             /* OUT.  May be NULL */,
+                                   hb_ot_name_id_t *tooltip_id           /* OUT.  May be NULL */,
+                                   hb_ot_name_id_t *sample_id            /* OUT.  May be NULL */,
+                                   unsigned int    *num_named_parameters /* OUT.  May be NULL */,
+                                   hb_ot_name_id_t *first_param_id       /* OUT.  May be NULL */);
 
-#define HB_OT_TAG_BASE_HANG HB_TAG('h','a','n','g')
-#define HB_OT_TAG_BASE_ICFB HB_TAG('i','c','f','b')
-#define HB_OT_TAG_BASE_ICFT HB_TAG('i','c','f','t')
-#define HB_OT_TAG_BASE_IDEO HB_TAG('i','d','e','o')
-#define HB_OT_TAG_BASE_IDTB HB_TAG('i','d','t','b')
-#define HB_OT_TAG_BASE_MATH HB_TAG('m','a','t','h')
-#define HB_OT_TAG_BASE_ROMN HB_TAG('r','o','m','n')
 
-#endif
-
+HB_EXTERN unsigned int
+hb_ot_layout_feature_get_characters (hb_face_t      *face,
+                                     hb_tag_t        table_tag,
+                                     unsigned int    feature_index,
+                                     unsigned int    start_offset,
+                                     unsigned int   *char_count    /* IN/OUT.  May be NULL */,
+                                     hb_codepoint_t *characters    /* OUT.     May be NULL */);
 
 HB_END_DECLS
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,612 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2012,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
+ */
+
+#ifndef HB_OT_LAYOUT_HH
+#define HB_OT_LAYOUT_HH
+
+#include "hb.hh"
+
+#include "hb-font.hh"
+#include "hb-buffer.hh"
+#include "hb-open-type.hh"
+#include "hb-ot-shape.hh"
+#include "hb-set-digest.hh"
+
+
+struct hb_ot_shape_plan_t;
+
+
+/*
+ * kern
+ */
+
+HB_INTERNAL bool
+hb_ot_layout_has_kerning (hb_face_t *face);
+
+HB_INTERNAL bool
+hb_ot_layout_has_machine_kerning (hb_face_t *face);
+
+HB_INTERNAL bool
+hb_ot_layout_has_cross_kerning (hb_face_t *face);
+
+HB_INTERNAL void
+hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
+                   hb_font_t *font,
+                   hb_buffer_t  *buffer);
+
+
+/* Private API corresponding to hb-ot-layout.h: */
+
+HB_INTERNAL bool
+hb_ot_layout_table_find_feature (hb_face_t    *face,
+                                 hb_tag_t      table_tag,
+                                 hb_tag_t      feature_tag,
+                                 unsigned int *feature_index);
+
+
+/*
+ * GDEF
+ */
+
+enum hb_ot_layout_glyph_props_flags_t
+{
+  /* The following three match LookupFlags::Ignore* numbers. */
+  HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH   = 0x02u,
+  HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE     = 0x04u,
+  HB_OT_LAYOUT_GLYPH_PROPS_MARK         = 0x08u,
+
+  /* The following are used internally; not derived from GDEF. */
+  HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED  = 0x10u,
+  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED      = 0x20u,
+  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED   = 0x40u,
+
+  HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE     = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
+                                          HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
+                                          HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
+};
+HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t);
+
+
+/*
+ * GSUB/GPOS
+ */
+
+HB_INTERNAL bool
+hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
+                                           unsigned int          lookup_index,
+                                           const hb_codepoint_t *glyphs,
+                                           unsigned int          glyphs_length,
+                                           bool                  zero_context);
+
+
+/* Should be called before all the substitute_lookup's are done. */
+HB_INTERNAL void
+hb_ot_layout_substitute_start (hb_font_t    *font,
+                               hb_buffer_t  *buffer);
+
+HB_INTERNAL void
+hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
+                                    bool (*filter) (const hb_glyph_info_t *info));
+
+namespace OT {
+  struct hb_ot_apply_context_t;
+  struct SubstLookup;
+  struct hb_ot_layout_lookup_accelerator_t;
+}
+
+HB_INTERNAL void
+hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
+                                const OT::SubstLookup &lookup,
+                                const OT::hb_ot_layout_lookup_accelerator_t &accel);
+
+
+/* Should be called before all the position_lookup's are done. */
+HB_INTERNAL void
+hb_ot_layout_position_start (hb_font_t    *font,
+                             hb_buffer_t  *buffer);
+
+/* Should be called after all the position_lookup's are done, to fini advances. */
+HB_INTERNAL void
+hb_ot_layout_position_finish_advances (hb_font_t    *font,
+                                       hb_buffer_t  *buffer);
+
+/* Should be called after hb_ot_layout_position_finish_advances, to fini offsets. */
+HB_INTERNAL void
+hb_ot_layout_position_finish_offsets (hb_font_t    *font,
+                                      hb_buffer_t  *buffer);
+
+
+/*
+ * Buffer var routines.
+ */
+
+/* buffer var allocations, used during the entire shaping process */
+#define unicode_props()         var2.u16[0]
+
+/* buffer var allocations, used during the GSUB/GPOS processing */
+#define glyph_props()           var1.u16[0] /* GDEF glyph properties */
+#define lig_props()             var1.u8[2] /* GSUB/GPOS ligature tracking */
+#define syllable()              var1.u8[3] /* GSUB/GPOS shaping boundaries */
+
+
+/* Loop over syllables. Based on foreach_cluster(). */
+#define foreach_syllable(buffer, start, end) \
+  for (unsigned int \
+       _count = buffer->len, \
+       start = 0, end = _count ? _hb_next_syllable (buffer, 0) : 0; \
+       start < _count; \
+       start = end, end = _hb_next_syllable (buffer, start))
+
+static inline unsigned int
+_hb_next_syllable (hb_buffer_t *buffer, unsigned int start)
+{
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+
+  unsigned int syllable = info[start].syllable();
+  while (++start < count && syllable == info[start].syllable())
+    ;
+
+  return start;
+}
+
+
+/* unicode_props */
+
+/* Design:
+ * unicode_props() is a two-byte number.  The low byte includes:
+ * - General_Category: 5 bits.
+ * - A bit each for:
+ *   * Is it Default_Ignorable(); we have a modified Default_Ignorable().
+ *   * Whether it's one of the three Mongolian Free Variation Selectors,
+ *     CGJ, or other characters that are hidden but should not be ignored
+ *     like most other Default_Ignorable()s do during matching.
+ *   * Whether it's a grapheme continuation.
+ *
+ * The high-byte has different meanings, switched by the Gen-Cat:
+ * - For Mn,Mc,Me: the modified Combining_Class.
+ * - For Cf: whether it's ZWJ, ZWNJ, or something else.
+ * - For Ws: index of which space character this is, if space fallback
+ *   is needed, ie. we don't set this by default, only if asked to.
+ */
+
+enum hb_unicode_props_flags_t {
+  UPROPS_MASK_GEN_CAT   = 0x001Fu,
+  UPROPS_MASK_IGNORABLE = 0x0020u,
+  UPROPS_MASK_HIDDEN    = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3, or TAG characters */
+  UPROPS_MASK_CONTINUATION=0x0080u,
+
+  /* If GEN_CAT=FORMAT, top byte masks: */
+  UPROPS_MASK_Cf_ZWJ    = 0x0100u,
+  UPROPS_MASK_Cf_ZWNJ   = 0x0200u
+};
+HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
+
+static inline void
+_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
+{
+  hb_unicode_funcs_t *unicode = buffer->unicode;
+  unsigned int u = info->codepoint;
+  unsigned int gen_cat = (unsigned int) unicode->general_category (u);
+  unsigned int props = gen_cat;
+
+  if (u >= 0x80)
+  {
+    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII;
+
+    if (unlikely (unicode->is_default_ignorable (u)))
+    {
+      buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
+      props |=  UPROPS_MASK_IGNORABLE;
+      if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ;
+      else if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ;
+      /* Mongolian Free Variation Selectors need to be remembered
+       * because although we need to hide them like default-ignorables,
+       * they need to non-ignorable during shaping.  This is similar to
+       * what we do for joiners in Indic-like shapers, but since the
+       * FVSes are GC=Mn, we have use a separate bit to remember them.
+       * Fixes:
+       * https://github.com/harfbuzz/harfbuzz/issues/234 */
+      else if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN;
+      /* TAG characters need similar treatment. Fixes:
+       * https://github.com/harfbuzz/harfbuzz/issues/463 */
+      else if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
+      /* COMBINING GRAPHEME JOINER should not be skipped; at least some times.
+       * https://github.com/harfbuzz/harfbuzz/issues/554 */
+      else if (unlikely (u == 0x034Fu))
+      {
+        buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CGJ;
+        props |= UPROPS_MASK_HIDDEN;
+      }
+    }
+
+    if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (gen_cat)))
+    {
+      props |= UPROPS_MASK_CONTINUATION;
+      props |= unicode->modified_combining_class (u)<<8;
+    }
+  }
+
+  info->unicode_props() = props;
+}
+
+static inline void
+_hb_glyph_info_set_general_category (hb_glyph_info_t *info,
+                                     hb_unicode_general_category_t gen_cat)
+{
+  /* Clears top-byte. */
+  info->unicode_props() = (unsigned int) gen_cat | (info->unicode_props() & (0xFF & ~UPROPS_MASK_GEN_CAT));
+}
+
+static inline hb_unicode_general_category_t
+_hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
+{
+  return (hb_unicode_general_category_t) (info->unicode_props() & UPROPS_MASK_GEN_CAT);
+}
+
+static inline bool
+_hb_glyph_info_is_unicode_mark (const hb_glyph_info_t *info)
+{
+  return HB_UNICODE_GENERAL_CATEGORY_IS_MARK (info->unicode_props() & UPROPS_MASK_GEN_CAT);
+}
+static inline void
+_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
+                                             unsigned int modified_class)
+{
+  if (unlikely (!_hb_glyph_info_is_unicode_mark (info)))
+    return;
+  info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF);
+}
+static inline unsigned int
+_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
+}
+#define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info)))
+
+static inline bool
+_hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_get_general_category (info) ==
+         HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
+}
+static inline void
+_hb_glyph_info_set_unicode_space_fallback_type (hb_glyph_info_t *info, hb_unicode_funcs_t::space_t s)
+{
+  if (unlikely (!_hb_glyph_info_is_unicode_space (info)))
+    return;
+  info->unicode_props() = (((unsigned int) s)<<8) | (info->unicode_props() & 0xFF);
+}
+static inline hb_unicode_funcs_t::space_t
+_hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_space (info) ?
+         (hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) :
+         hb_unicode_funcs_t::NOT_SPACE;
+}
+
+static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
+
+static inline bool
+_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
+{
+  return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
+         !_hb_glyph_info_ligated (info);
+}
+static inline bool
+_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
+{
+  return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
+          == UPROPS_MASK_IGNORABLE) &&
+         !_hb_glyph_info_ligated (info);
+}
+static inline void
+_hb_glyph_info_unhide (hb_glyph_info_t *info)
+{
+  info->unicode_props() &= ~ UPROPS_MASK_HIDDEN;
+}
+
+static inline void
+_hb_glyph_info_set_continuation (hb_glyph_info_t *info)
+{
+  info->unicode_props() |= UPROPS_MASK_CONTINUATION;
+}
+static inline void
+_hb_glyph_info_reset_continuation (hb_glyph_info_t *info)
+{
+  info->unicode_props() &= ~ UPROPS_MASK_CONTINUATION;
+}
+static inline bool
+_hb_glyph_info_is_continuation (const hb_glyph_info_t *info)
+{
+  return info->unicode_props() & UPROPS_MASK_CONTINUATION;
+}
+/* Loop over grapheme. Based on foreach_cluster(). */
+#define foreach_grapheme(buffer, start, end) \
+  for (unsigned int \
+       _count = buffer->len, \
+       start = 0, end = _count ? _hb_next_grapheme (buffer, 0) : 0; \
+       start < _count; \
+       start = end, end = _hb_next_grapheme (buffer, start))
+
+static inline unsigned int
+_hb_next_grapheme (hb_buffer_t *buffer, unsigned int start)
+{
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+
+  while (++start < count && _hb_glyph_info_is_continuation (&info[start]))
+    ;
+
+  return start;
+}
+
+static inline bool
+_hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_get_general_category (info) ==
+         HB_UNICODE_GENERAL_CATEGORY_FORMAT;
+}
+static inline bool
+_hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ);
+}
+static inline bool
+_hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ);
+}
+static inline bool
+_hb_glyph_info_is_joiner (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & (UPROPS_MASK_Cf_ZWNJ|UPROPS_MASK_Cf_ZWJ));
+}
+static inline void
+_hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
+{
+  if (!_hb_glyph_info_is_unicode_format (info))
+    return;
+  info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ;
+}
+
+/* lig_props: aka lig_id / lig_comp
+ *
+ * When a ligature is formed:
+ *
+ *   - The ligature glyph and any marks in between all the same newly allocated
+ *     lig_id,
+ *   - The ligature glyph will get lig_num_comps set to the number of components
+ *   - The marks get lig_comp > 0, reflecting which component of the ligature
+ *     they were applied to.
+ *   - This is used in GPOS to attach marks to the right component of a ligature
+ *     in MarkLigPos,
+ *   - Note that when marks are ligated together, much of the above is skipped
+ *     and the current lig_id reused.
+ *
+ * When a multiple-substitution is done:
+ *
+ *   - All resulting glyphs will have lig_id = 0,
+ *   - The resulting glyphs will have lig_comp = 0, 1, 2, ... respectively.
+ *   - This is used in GPOS to attach marks to the first component of a
+ *     multiple substitution in MarkBasePos.
+ *
+ * The numbers are also used in GPOS to do mark-to-mark positioning only
+ * to marks that belong to the same component of the same ligature.
+ */
+
+static inline void
+_hb_glyph_info_clear_lig_props (hb_glyph_info_t *info)
+{
+  info->lig_props() = 0;
+}
+
+#define IS_LIG_BASE 0x10
+
+static inline void
+_hb_glyph_info_set_lig_props_for_ligature (hb_glyph_info_t *info,
+                                           unsigned int lig_id,
+                                           unsigned int lig_num_comps)
+{
+  info->lig_props() = (lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F);
+}
+
+static inline void
+_hb_glyph_info_set_lig_props_for_mark (hb_glyph_info_t *info,
+                                       unsigned int lig_id,
+                                       unsigned int lig_comp)
+{
+  info->lig_props() = (lig_id << 5) | (lig_comp & 0x0F);
+}
+
+static inline void
+_hb_glyph_info_set_lig_props_for_component (hb_glyph_info_t *info, unsigned int comp)
+{
+  _hb_glyph_info_set_lig_props_for_mark (info, 0, comp);
+}
+
+static inline unsigned int
+_hb_glyph_info_get_lig_id (const hb_glyph_info_t *info)
+{
+  return info->lig_props() >> 5;
+}
+
+static inline bool
+_hb_glyph_info_ligated_internal (const hb_glyph_info_t *info)
+{
+  return !!(info->lig_props() & IS_LIG_BASE);
+}
+
+static inline unsigned int
+_hb_glyph_info_get_lig_comp (const hb_glyph_info_t *info)
+{
+  if (_hb_glyph_info_ligated_internal (info))
+    return 0;
+  else
+    return info->lig_props() & 0x0F;
+}
+
+static inline unsigned int
+_hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info)
+{
+  if ((info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE) &&
+      _hb_glyph_info_ligated_internal (info))
+    return info->lig_props() & 0x0F;
+  else
+    return 1;
+}
+
+static inline uint8_t
+_hb_allocate_lig_id (hb_buffer_t *buffer) {
+  uint8_t lig_id = buffer->next_serial () & 0x07;
+  if (unlikely (!lig_id))
+    lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
+  return lig_id;
+}
+
+/* glyph_props: */
+
+static inline void
+_hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props)
+{
+  info->glyph_props() = props;
+}
+
+static inline unsigned int
+_hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info)
+{
+  return info->glyph_props();
+}
+
+static inline bool
+_hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
+}
+
+static inline bool
+_hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE);
+}
+
+static inline bool
+_hb_glyph_info_is_mark (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
+}
+
+static inline bool
+_hb_glyph_info_substituted (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
+}
+
+static inline bool
+_hb_glyph_info_ligated (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
+}
+
+static inline bool
+_hb_glyph_info_multiplied (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
+}
+
+static inline bool
+_hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
+}
+
+static inline void
+_hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
+{
+  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
+                           HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
+}
+
+static inline void
+_hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
+{
+  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
+}
+
+
+/* Allocation / deallocation. */
+
+static inline void
+_hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props);
+}
+
+static inline void
+_hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props);
+}
+
+static inline void
+_hb_buffer_assert_unicode_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_ASSERT_VAR (buffer, unicode_props);
+}
+
+static inline void
+_hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
+  HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
+  HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
+}
+
+static inline void
+_hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
+  HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
+  HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
+}
+
+static inline void
+_hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
+  HB_BUFFER_ASSERT_VAR (buffer, lig_props);
+  HB_BUFFER_ASSERT_VAR (buffer, syllable);
+}
+
+/* Make sure no one directly touches our props... */
+#undef unicode_props0
+#undef unicode_props1
+#undef lig_props
+#undef glyph_props
+
+#endif /* HB_OT_LAYOUT_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-map-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,253 +0,0 @@
-/*
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2010,2011,2012,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
- */
-
-#ifndef HB_OT_MAP_PRIVATE_HH
-#define HB_OT_MAP_PRIVATE_HH
-
-#include "hb-buffer-private.hh"
-
-
-struct hb_ot_shape_plan_t;
-
-static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
-
-struct hb_ot_map_t
-{
-  friend struct hb_ot_map_builder_t;
-
-  public:
-
-  struct feature_map_t {
-    hb_tag_t tag; /* should be first for our bsearch to work */
-    unsigned int index[2]; /* GSUB/GPOS */
-    unsigned int stage[2]; /* GSUB/GPOS */
-    unsigned int shift;
-    hb_mask_t mask;
-    hb_mask_t _1_mask; /* mask for value=1, for quick access */
-    unsigned int needs_fallback : 1;
-    unsigned int auto_zwnj : 1;
-    unsigned int auto_zwj : 1;
-
-    inline int cmp (const hb_tag_t *tag_) const
-    { return *tag_ < tag ? -1 : *tag_ > tag ? 1 : 0; }
-  };
-
-  struct lookup_map_t {
-    unsigned short index;
-    unsigned short auto_zwnj : 1;
-    unsigned short auto_zwj : 1;
-    hb_mask_t mask;
-
-    static int cmp (const void *pa, const void *pb)
-    {
-      const lookup_map_t *a = (const lookup_map_t *) pa;
-      const lookup_map_t *b = (const lookup_map_t *) pb;
-      return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
-    }
-  };
-
-  typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
-
-  struct stage_map_t {
-    unsigned int last_lookup; /* Cumulative */
-    pause_func_t pause_func;
-  };
-
-  inline void init (void)
-  {
-    memset (this, 0, sizeof (*this));
-
-    features.init ();
-    for (unsigned int table_index = 0; table_index < 2; table_index++)
-    {
-      lookups[table_index].init ();
-      stages[table_index].init ();
-    }
-  }
-  inline void fini (void)
-  {
-    features.fini ();
-    for (unsigned int table_index = 0; table_index < 2; table_index++)
-    {
-      lookups[table_index].fini ();
-      stages[table_index].fini ();
-    }
-  }
-
-  inline hb_mask_t get_global_mask (void) const { return global_mask; }
-
-  inline hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = nullptr) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    if (shift) *shift = map ? map->shift : 0;
-    return map ? map->mask : 0;
-  }
-
-  inline bool needs_fallback (hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->needs_fallback : false;
-  }
-
-  inline hb_mask_t get_1_mask (hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->_1_mask : 0;
-  }
-
-  inline unsigned int get_feature_index (unsigned int table_index, hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX;
-  }
-
-  inline unsigned int get_feature_stage (unsigned int table_index, hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->stage[table_index] : (unsigned int) -1;
-  }
-
-  inline void get_stage_lookups (unsigned int table_index, unsigned int stage,
-                                 const struct lookup_map_t **plookups, unsigned int *lookup_count) const {
-    if (unlikely (stage == (unsigned int) -1)) {
-      *plookups = nullptr;
-      *lookup_count = 0;
-      return;
-    }
-    assert (stage <= stages[table_index].len);
-    unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0;
-    unsigned int end   = stage < stages[table_index].len ? stages[table_index][stage].last_lookup : lookups[table_index].len;
-    *plookups = end == start ? nullptr : &lookups[table_index][start];
-    *lookup_count = end - start;
-  }
-
-  HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
-  template <typename Proxy>
-  HB_INTERNAL inline void apply (const Proxy &proxy,
-                                 const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
-  HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
-  HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
-
-  public:
-  hb_tag_t chosen_script[2];
-  bool found_script[2];
-
-  private:
-
-  hb_mask_t global_mask;
-
-  hb_vector_t<feature_map_t, 8> features;
-  hb_vector_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */
-  hb_vector_t<stage_map_t, 4> stages[2]; /* GSUB/GPOS */
-};
-
-enum hb_ot_map_feature_flags_t {
-  F_NONE                = 0x0000u,
-  F_GLOBAL              = 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */
-  F_HAS_FALLBACK        = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */
-  F_MANUAL_ZWNJ         = 0x0004u, /* Don't skip over ZWNJ when matching **context**. */
-  F_MANUAL_ZWJ          = 0x0008u, /* Don't skip over ZWJ when matching **input**. */
-  F_GLOBAL_SEARCH       = 0x0010u  /* If feature not found in LangSys, look for it in global feature list and pick one. */
-};
-HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t);
-/* Macro version for where const is desired. */
-#define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r)))
-
-
-struct hb_ot_map_builder_t
-{
-  public:
-
-  HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_,
-                                   const hb_segment_properties_t *props_);
-
-  HB_INTERNAL ~hb_ot_map_builder_t (void);
-
-  HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value,
-                                hb_ot_map_feature_flags_t flags);
-
-  inline void add_global_bool_feature (hb_tag_t tag)
-  { add_feature (tag, 1, F_GLOBAL); }
-
-  inline void add_gsub_pause (hb_ot_map_t::pause_func_t pause_func)
-  { add_pause (0, pause_func); }
-  inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func)
-  { add_pause (1, pause_func); }
-
-  HB_INTERNAL void compile (hb_ot_map_t  &m,
-                            const int    *coords,
-                            unsigned int  num_coords);
-
-  private:
-
-  HB_INTERNAL void add_lookups (hb_ot_map_t  &m,
-                                unsigned int  table_index,
-                                unsigned int  feature_index,
-                                unsigned int  variations_index,
-                                hb_mask_t     mask,
-                                bool          auto_zwnj = true,
-                                bool          auto_zwj = true);
-
-  struct feature_info_t {
-    hb_tag_t tag;
-    unsigned int seq; /* sequence#, used for stable sorting only */
-    unsigned int max_value;
-    hb_ot_map_feature_flags_t flags;
-    unsigned int default_value; /* for non-global features, what should the unset glyphs take */
-    unsigned int stage[2]; /* GSUB/GPOS */
-
-    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->tag != b->tag) ?  (a->tag < b->tag ? -1 : 1) :
-             (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
-    }
-  };
-
-  struct stage_info_t {
-    unsigned int index;
-    hb_ot_map_t::pause_func_t pause_func;
-  };
-
-  HB_INTERNAL void add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func);
-
-  public:
-
-  hb_face_t *face;
-  hb_segment_properties_t props;
-
-  hb_tag_t chosen_script[2];
-  bool found_script[2];
-  unsigned int script_index[2], language_index[2];
-
-  private:
-
-  unsigned int current_stage[2]; /* GSUB/GPOS */
-  hb_vector_t<feature_info_t, 32> feature_infos;
-  hb_vector_t<stage_info_t, 8> stages[2]; /* GSUB/GPOS */
-};
-
-
-
-#endif /* HB_OT_MAP_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-map.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-map.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -26,14 +26,14 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-map-private.hh"
-
-#include "hb-ot-layout-private.hh"
+#include "hb-ot-map.hh"
+#include "hb-ot-shape.hh"
+#include "hb-ot-layout.hh"
 
 
 void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const
 {
-  for (unsigned int i = 0; i < lookups[table_index].len; i++)
+  for (unsigned int i = 0; i < lookups[table_index].length; i++)
     hb_set_add (lookups_out, lookups[table_index][i].index);
 }
 
@@ -54,33 +54,35 @@
   /* Fetch script/language indices for GSUB/GPOS.  We need these later to skip
    * features not available in either table and not waste precious bits for them. */
 
-  hb_tag_t script_tags[3] = {HB_TAG_NONE, HB_TAG_NONE, HB_TAG_NONE};
-  hb_tag_t language_tag;
+  unsigned int script_count = HB_OT_MAX_TAGS_PER_SCRIPT;
+  unsigned int language_count = HB_OT_MAX_TAGS_PER_LANGUAGE;
+  hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
+  hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
 
-  hb_ot_tags_from_script (props.script, &script_tags[0], &script_tags[1]);
-  language_tag = hb_ot_tag_from_language (props.language);
+  hb_ot_tags_from_script_and_language (props.script, props.language, &script_count, script_tags, &language_count, language_tags);
 
   for (unsigned int table_index = 0; table_index < 2; table_index++) {
     hb_tag_t table_tag = table_tags[table_index];
-    found_script[table_index] = (bool) hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]);
-    hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
+    found_script[table_index] = (bool) hb_ot_layout_table_select_script (face, table_tag, script_count, script_tags, &script_index[table_index], &chosen_script[table_index]);
+    hb_ot_layout_script_select_language (face, table_tag, script_index[table_index], language_count, language_tags, &language_index[table_index]);
   }
 }
 
-hb_ot_map_builder_t::~hb_ot_map_builder_t (void)
+hb_ot_map_builder_t::~hb_ot_map_builder_t ()
 {
   feature_infos.fini ();
   for (unsigned int table_index = 0; table_index < 2; table_index++)
     stages[table_index].fini ();
 }
 
-void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value,
-                                       hb_ot_map_feature_flags_t flags)
+void hb_ot_map_builder_t::add_feature (hb_tag_t tag,
+                                       hb_ot_map_feature_flags_t flags,
+                                       unsigned int value)
 {
+  if (unlikely (!tag)) return;
   feature_info_t *info = feature_infos.push();
-  if (unlikely (!tag)) return;
   info->tag = tag;
-  info->seq = feature_infos.len;
+  info->seq = feature_infos.length;
   info->max_value = value;
   info->flags = flags;
   info->default_value = (flags & F_GLOBAL) ? value : 0;
@@ -95,7 +97,8 @@
                                   unsigned int  variations_index,
                                   hb_mask_t     mask,
                                   bool          auto_zwnj,
-                                  bool          auto_zwj)
+                                  bool          auto_zwj,
+                                  bool          random)
 {
   unsigned int lookup_indices[32];
   unsigned int offset, len;
@@ -122,6 +125,7 @@
       lookup->index = lookup_indices[i];
       lookup->auto_zwnj = auto_zwnj;
       lookup->auto_zwj = auto_zwj;
+      lookup->random = random;
     }
 
     offset += len;
@@ -139,13 +143,12 @@
 }
 
 void
-hb_ot_map_builder_t::compile (hb_ot_map_t  &m,
-                              const int    *coords,
-                              unsigned int  num_coords)
+hb_ot_map_builder_t::compile (hb_ot_map_t                  &m,
+                              const hb_ot_shape_plan_key_t &key)
 {
   static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
   unsigned int global_bit_mask = HB_GLYPH_FLAG_DEFINED + 1;
-  unsigned int global_bit_shift = _hb_popcount (HB_GLYPH_FLAG_DEFINED);
+  unsigned int global_bit_shift = hb_popcount (HB_GLYPH_FLAG_DEFINED);
 
   m.global_mask = global_bit_mask;
 
@@ -171,10 +174,11 @@
   }
 
   /* Sort features and merge duplicates */
+  if (feature_infos.length)
   {
     feature_infos.qsort ();
     unsigned int j = 0;
-    for (unsigned int i = 1; i < feature_infos.len; i++)
+    for (unsigned int i = 1; i < feature_infos.length; i++)
       if (feature_infos[i].tag != feature_infos[j].tag)
         feature_infos[++j] = feature_infos[i];
       else {
@@ -198,7 +202,7 @@
   /* Allocate bits now */
   unsigned int next_bit = global_bit_shift + 1;
 
-  for (unsigned int i = 0; i < feature_infos.len; i++)
+  for (unsigned int i = 0; i < feature_infos.length; i++)
   {
     const feature_info_t *info = &feature_infos[i];
 
@@ -208,8 +212,8 @@
       /* Uses the global bit */
       bits_needed = 0;
     else
-      /* Limit to 8 bits per feature. */
-      bits_needed = MIN(8u, _hb_bit_storage (info->max_value));
+      /* Limit bits per feature. */
+      bits_needed = MIN(HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value));
 
     if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
       continue; /* Feature disabled, or not enough bits. */
@@ -252,6 +256,7 @@
     map->stage[1] = info->stage[1];
     map->auto_zwnj = !(info->flags & F_MANUAL_ZWNJ);
     map->auto_zwj = !(info->flags & F_MANUAL_ZWJ);
+    map->random = !!(info->flags & F_RANDOM);
     if ((info->flags & F_GLOBAL) && info->max_value == 1) {
       /* Uses the global bit */
       map->shift = global_bit_shift;
@@ -276,13 +281,6 @@
   {
     /* Collect lookup indices for features */
 
-    unsigned int variations_index;
-    hb_ot_layout_table_find_feature_variations (face,
-                                                table_tags[table_index],
-                                                coords,
-                                                num_coords,
-                                                &variations_index);
-
     unsigned int stage_index = 0;
     unsigned int last_num_lookups = 0;
     for (unsigned stage = 0; stage < current_stage[table_index]; stage++)
@@ -291,25 +289,26 @@
           required_feature_stage[table_index] == stage)
         add_lookups (m, table_index,
                      required_feature_index[table_index],
-                     variations_index,
+                     key.variations_index[table_index],
                      global_bit_mask);
 
-      for (unsigned i = 0; i < m.features.len; i++)
+      for (unsigned i = 0; i < m.features.length; i++)
         if (m.features[i].stage[table_index] == stage)
           add_lookups (m, table_index,
                        m.features[i].index[table_index],
-                       variations_index,
+                       key.variations_index[table_index],
                        m.features[i].mask,
                        m.features[i].auto_zwnj,
-                       m.features[i].auto_zwj);
+                       m.features[i].auto_zwj,
+                       m.features[i].random);
 
       /* Sort lookups and merge duplicates */
-      if (last_num_lookups < m.lookups[table_index].len)
+      if (last_num_lookups < m.lookups[table_index].length)
       {
-        m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].len);
+        m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].length);
 
         unsigned int j = last_num_lookups;
-        for (unsigned int i = j + 1; i < m.lookups[table_index].len; i++)
+        for (unsigned int i = j + 1; i < m.lookups[table_index].length; i++)
           if (m.lookups[table_index][i].index != m.lookups[table_index][j].index)
             m.lookups[table_index][++j] = m.lookups[table_index][i];
           else
@@ -321,9 +320,9 @@
         m.lookups[table_index].shrink (j + 1);
       }
 
-      last_num_lookups = m.lookups[table_index].len;
+      last_num_lookups = m.lookups[table_index].length;
 
-      if (stage_index < stages[table_index].len && stages[table_index][stage_index].index == stage) {
+      if (stage_index < stages[table_index].length && stages[table_index][stage_index].index == stage) {
         hb_ot_map_t::stage_map_t *stage_map = m.stages[table_index].push ();
         stage_map->last_lookup = last_num_lookups;
         stage_map->pause_func = stages[table_index][stage_index].pause_func;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-map.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,284 @@
+/*
+ * Copyright © 2009,2010  Red Hat, Inc.
+ * Copyright © 2010,2011,2012,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
+ */
+
+#ifndef HB_OT_MAP_HH
+#define HB_OT_MAP_HH
+
+#include "hb-buffer.hh"
+
+
+#define HB_OT_MAP_MAX_BITS 8u
+#define HB_OT_MAP_MAX_VALUE ((1u << HB_OT_MAP_MAX_BITS) - 1u)
+
+struct hb_ot_shape_plan_t;
+
+static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
+
+struct hb_ot_map_t
+{
+  friend struct hb_ot_map_builder_t;
+
+  public:
+
+  struct feature_map_t {
+    hb_tag_t tag; /* should be first for our bsearch to work */
+    unsigned int index[2]; /* GSUB/GPOS */
+    unsigned int stage[2]; /* GSUB/GPOS */
+    unsigned int shift;
+    hb_mask_t mask;
+    hb_mask_t _1_mask; /* mask for value=1, for quick access */
+    unsigned int needs_fallback : 1;
+    unsigned int auto_zwnj : 1;
+    unsigned int auto_zwj : 1;
+    unsigned int random : 1;
+
+    int cmp (const hb_tag_t tag_) const
+    { return tag_ < tag ? -1 : tag_ > tag ? 1 : 0; }
+  };
+
+  struct lookup_map_t {
+    unsigned short index;
+    unsigned short auto_zwnj : 1;
+    unsigned short auto_zwj : 1;
+    unsigned short random : 1;
+    hb_mask_t mask;
+
+    static int cmp (const void *pa, const void *pb)
+    {
+      const lookup_map_t *a = (const lookup_map_t *) pa;
+      const lookup_map_t *b = (const lookup_map_t *) pb;
+      return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
+    }
+  };
+
+  typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
+
+  struct stage_map_t {
+    unsigned int last_lookup; /* Cumulative */
+    pause_func_t pause_func;
+  };
+
+  void init ()
+  {
+    memset (this, 0, sizeof (*this));
+
+    features.init ();
+    for (unsigned int table_index = 0; table_index < 2; table_index++)
+    {
+      lookups[table_index].init ();
+      stages[table_index].init ();
+    }
+  }
+  void fini ()
+  {
+    features.fini ();
+    for (unsigned int table_index = 0; table_index < 2; table_index++)
+    {
+      lookups[table_index].fini ();
+      stages[table_index].fini ();
+    }
+  }
+
+  hb_mask_t get_global_mask () const { return global_mask; }
+
+  hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = nullptr) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    if (shift) *shift = map ? map->shift : 0;
+    return map ? map->mask : 0;
+  }
+
+  bool needs_fallback (hb_tag_t feature_tag) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    return map ? map->needs_fallback : false;
+  }
+
+  hb_mask_t get_1_mask (hb_tag_t feature_tag) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    return map ? map->_1_mask : 0;
+  }
+
+  unsigned int get_feature_index (unsigned int table_index, hb_tag_t feature_tag) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    return map ? map->index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX;
+  }
+
+  unsigned int get_feature_stage (unsigned int table_index, hb_tag_t feature_tag) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    return map ? map->stage[table_index] : (unsigned int) -1;
+  }
+
+  void get_stage_lookups (unsigned int table_index, unsigned int stage,
+                          const struct lookup_map_t **plookups, unsigned int *lookup_count) const
+  {
+    if (unlikely (stage == (unsigned int) -1)) {
+      *plookups = nullptr;
+      *lookup_count = 0;
+      return;
+    }
+    assert (stage <= stages[table_index].length);
+    unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0;
+    unsigned int end   = stage < stages[table_index].length ? stages[table_index][stage].last_lookup : lookups[table_index].length;
+    *plookups = end == start ? nullptr : &lookups[table_index][start];
+    *lookup_count = end - start;
+  }
+
+  HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
+  template <typename Proxy>
+  HB_INTERNAL inline void apply (const Proxy &proxy,
+                                 const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
+  HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
+  HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
+
+  public:
+  hb_tag_t chosen_script[2];
+  bool found_script[2];
+
+  private:
+
+  hb_mask_t global_mask;
+
+  hb_vector_t<feature_map_t> features;
+  hb_vector_t<lookup_map_t> lookups[2]; /* GSUB/GPOS */
+  hb_vector_t<stage_map_t> stages[2]; /* GSUB/GPOS */
+};
+
+enum hb_ot_map_feature_flags_t
+{
+  F_NONE                = 0x0000u,
+  F_GLOBAL              = 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */
+  F_HAS_FALLBACK        = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */
+  F_MANUAL_ZWNJ         = 0x0004u, /* Don't skip over ZWNJ when matching **context**. */
+  F_MANUAL_ZWJ          = 0x0008u, /* Don't skip over ZWJ when matching **input**. */
+  F_MANUAL_JOINERS      = F_MANUAL_ZWNJ | F_MANUAL_ZWJ,
+  F_GLOBAL_MANUAL_JOINERS= F_GLOBAL | F_MANUAL_JOINERS,
+  F_GLOBAL_HAS_FALLBACK = F_GLOBAL | F_HAS_FALLBACK,
+  F_GLOBAL_SEARCH       = 0x0010u, /* If feature not found in LangSys, look for it in global feature list and pick one. */
+  F_RANDOM              = 0x0020u  /* Randomly select a glyph from an AlternateSubstFormat1 subtable. */
+};
+HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t);
+
+
+struct hb_ot_map_feature_t
+{
+  hb_tag_t tag;
+  hb_ot_map_feature_flags_t flags;
+};
+
+struct hb_ot_shape_plan_key_t;
+
+struct hb_ot_map_builder_t
+{
+  public:
+
+  HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_,
+                                   const hb_segment_properties_t *props_);
+
+  HB_INTERNAL ~hb_ot_map_builder_t ();
+
+  HB_INTERNAL void add_feature (hb_tag_t tag,
+                                hb_ot_map_feature_flags_t flags=F_NONE,
+                                unsigned int value=1);
+
+  void add_feature (const hb_ot_map_feature_t &feat)
+  { add_feature (feat.tag, feat.flags); }
+
+  void enable_feature (hb_tag_t tag,
+                              hb_ot_map_feature_flags_t flags=F_NONE,
+                              unsigned int value=1)
+  { add_feature (tag, F_GLOBAL | flags, value); }
+
+  void disable_feature (hb_tag_t tag)
+  { add_feature (tag, F_GLOBAL, 0); }
+
+  void add_gsub_pause (hb_ot_map_t::pause_func_t pause_func)
+  { add_pause (0, pause_func); }
+  void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func)
+  { add_pause (1, pause_func); }
+
+  HB_INTERNAL void compile (hb_ot_map_t                  &m,
+                            const hb_ot_shape_plan_key_t &key);
+
+  private:
+
+  HB_INTERNAL void add_lookups (hb_ot_map_t  &m,
+                                unsigned int  table_index,
+                                unsigned int  feature_index,
+                                unsigned int  variations_index,
+                                hb_mask_t     mask,
+                                bool          auto_zwnj = true,
+                                bool          auto_zwj = true,
+                                bool          random = false);
+
+  struct feature_info_t {
+    hb_tag_t tag;
+    unsigned int seq; /* sequence#, used for stable sorting only */
+    unsigned int max_value;
+    hb_ot_map_feature_flags_t flags;
+    unsigned int default_value; /* for non-global features, what should the unset glyphs take */
+    unsigned int stage[2]; /* GSUB/GPOS */
+
+    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->tag != b->tag) ?  (a->tag < b->tag ? -1 : 1) :
+             (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
+    }
+  };
+
+  struct stage_info_t {
+    unsigned int index;
+    hb_ot_map_t::pause_func_t pause_func;
+  };
+
+  HB_INTERNAL void add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func);
+
+  public:
+
+  hb_face_t *face;
+  hb_segment_properties_t props;
+
+  hb_tag_t chosen_script[2];
+  bool found_script[2];
+  unsigned int script_index[2], language_index[2];
+
+  private:
+
+  unsigned int current_stage[2]; /* GSUB/GPOS */
+  hb_vector_t<feature_info_t> feature_infos;
+  hb_vector_t<stage_info_t> stages[2]; /* GSUB/GPOS */
+};
+
+
+
+#endif /* HB_OT_MAP_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-math-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,718 @@
+/*
+ * Copyright © 2016  Igalia S.L.
+ *
+ *  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.
+ *
+ * Igalia Author(s): Frédéric Wang
+ */
+
+#ifndef HB_OT_MATH_TABLE_HH
+#define HB_OT_MATH_TABLE_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-ot-math.h"
+
+namespace OT {
+
+
+struct MathValueRecord
+{
+  hb_position_t get_x_value (hb_font_t *font, const void *base) const
+  { return font->em_scale_x (value) + (base+deviceTable).get_x_delta (font); }
+  hb_position_t get_y_value (hb_font_t *font, const void *base) const
+  { return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && deviceTable.sanitize (c, base));
+  }
+
+  protected:
+  HBINT16                       value;          /* The X or Y value in design units */
+  OffsetTo<Device>      deviceTable;    /* Offset to the device table - from the
+                                         * beginning of parent table.  May be NULL.
+                                         * Suggested format for device table is 1. */
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct MathConstants
+{
+  bool sanitize_math_value_records (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    unsigned int count = ARRAY_LENGTH (mathValueRecords);
+    for (unsigned int i = 0; i < count; i++)
+      if (!mathValueRecords[i].sanitize (c, this))
+        return_trace (false);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && sanitize_math_value_records (c));
+  }
+
+  hb_position_t get_value (hb_ot_math_constant_t constant,
+                                  hb_font_t *font) const
+  {
+    switch (constant) {
+
+    case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN:
+    case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN:
+      return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN];
+
+    case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT:
+    case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT:
+      return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]);
+
+    case HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE:
+    case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE:
+    case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP:
+    case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT:
+      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value (font, this);
+
+    case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT:
+    case HB_OT_MATH_CONSTANT_AXIS_HEIGHT:
+    case HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN:
+    case HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_MATH_LEADING:
+    case HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER:
+    case HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER:
+    case HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_STACK_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN:
+    case HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX:
+    case HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED:
+    case HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER:
+    case HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN:
+    case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN:
+      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value (font, this);
+
+    case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT:
+      return radicalDegreeBottomRaisePercent;
+
+    default:
+      return 0;
+    }
+  }
+
+  protected:
+  HBINT16 percentScaleDown[2];
+  HBUINT16 minHeight[2];
+  MathValueRecord mathValueRecords[51];
+  HBINT16 radicalDegreeBottomRaisePercent;
+
+  public:
+  DEFINE_SIZE_STATIC (214);
+};
+
+struct MathItalicsCorrectionInfo
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  coverage.sanitize (c, this) &&
+                  italicsCorrection.sanitize (c, this));
+  }
+
+  hb_position_t get_value (hb_codepoint_t glyph,
+                           hb_font_t *font) const
+  {
+    unsigned int index = (this+coverage).get_coverage (glyph);
+    return italicsCorrection[index].get_x_value (font, this);
+  }
+
+  protected:
+  OffsetTo<Coverage>       coverage;            /* Offset to Coverage table -
+                                                 * from the beginning of
+                                                 * MathItalicsCorrectionInfo
+                                                 * table. */
+  ArrayOf<MathValueRecord> italicsCorrection;   /* Array of MathValueRecords
+                                                 * defining italics correction
+                                                 * values for each
+                                                 * covered glyph. */
+
+  public:
+  DEFINE_SIZE_ARRAY (4, italicsCorrection);
+};
+
+struct MathTopAccentAttachment
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  topAccentCoverage.sanitize (c, this) &&
+                  topAccentAttachment.sanitize (c, this));
+  }
+
+  hb_position_t get_value (hb_codepoint_t glyph,
+                           hb_font_t *font) const
+  {
+    unsigned int index = (this+topAccentCoverage).get_coverage (glyph);
+    if (index == NOT_COVERED)
+      return font->get_glyph_h_advance (glyph) / 2;
+    return topAccentAttachment[index].get_x_value (font, this);
+  }
+
+  protected:
+  OffsetTo<Coverage>       topAccentCoverage;   /* Offset to Coverage table -
+                                                 * from the beginning of
+                                                 * MathTopAccentAttachment
+                                                 * table. */
+  ArrayOf<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords
+                                                 * defining top accent
+                                                 * attachment points for each
+                                                 * covered glyph. */
+
+  public:
+  DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment);
+};
+
+struct MathKern
+{
+  bool sanitize_math_value_records (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    unsigned int count = 2 * heightCount + 1;
+    for (unsigned int i = 0; i < count; i++)
+      if (!mathValueRecordsZ.arrayZ[i].sanitize (c, this)) return_trace (false);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  c->check_array (mathValueRecordsZ.arrayZ, 2 * heightCount + 1) &&
+                  sanitize_math_value_records (c));
+  }
+
+  hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const
+  {
+    const MathValueRecord* correctionHeight = mathValueRecordsZ.arrayZ;
+    const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount;
+    int sign = font->y_scale < 0 ? -1 : +1;
+
+    /* The description of the MathKern table is a ambiguous, but interpreting
+     * "between the two heights found at those indexes" for 0 < i < len as
+     *
+     *   correctionHeight[i-1] < correction_height <= correctionHeight[i]
+     *
+     * makes the result consistent with the limit cases and we can just use the
+     * binary search algorithm of std::upper_bound:
+     */
+    unsigned int i = 0;
+    unsigned int count = heightCount;
+    while (count > 0)
+    {
+      unsigned int half = count / 2;
+      hb_position_t height = correctionHeight[i + half].get_y_value (font, this);
+      if (sign * height < sign * correction_height)
+      {
+        i += half + 1;
+        count -= half + 1;
+      } else
+        count = half;
+    }
+    return kernValue[i].get_x_value (font, this);
+  }
+
+  protected:
+  HBUINT16      heightCount;
+  UnsizedArrayOf<MathValueRecord>
+                mathValueRecordsZ;      /* Array of correction heights at
+                                         * which the kern value changes.
+                                         * Sorted by the height value in
+                                         * design units (heightCount entries),
+                                         * Followed by:
+                                         * Array of kern values corresponding
+                                         * to heights. (heightCount+1 entries).
+                                         */
+
+  public:
+  DEFINE_SIZE_ARRAY (2, mathValueRecordsZ);
+};
+
+struct MathKernInfoRecord
+{
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+
+    unsigned int count = ARRAY_LENGTH (mathKern);
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!mathKern[i].sanitize (c, base)))
+        return_trace (false);
+
+    return_trace (true);
+  }
+
+  hb_position_t get_kerning (hb_ot_math_kern_t kern,
+                             hb_position_t correction_height,
+                             hb_font_t *font,
+                             const void *base) const
+  {
+    unsigned int idx = kern;
+    if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0;
+    return (base+mathKern[idx]).get_value (correction_height, font);
+  }
+
+  protected:
+  /* Offset to MathKern table for each corner -
+   * from the beginning of MathKernInfo table.  May be NULL. */
+  OffsetTo<MathKern> mathKern[4];
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct MathKernInfo
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  mathKernCoverage.sanitize (c, this) &&
+                  mathKernInfoRecords.sanitize (c, this));
+  }
+
+  hb_position_t get_kerning (hb_codepoint_t glyph,
+                             hb_ot_math_kern_t kern,
+                             hb_position_t correction_height,
+                             hb_font_t *font) const
+  {
+    unsigned int index = (this+mathKernCoverage).get_coverage (glyph);
+    return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this);
+  }
+
+  protected:
+  OffsetTo<Coverage>            mathKernCoverage;    /* Offset to Coverage table -
+                                                      * from the beginning of the
+                                                      * MathKernInfo table. */
+  ArrayOf<MathKernInfoRecord>   mathKernInfoRecords; /* Array of
+                                                      * MathKernInfoRecords,
+                                                      * per-glyph information for
+                                                      * mathematical positioning
+                                                      * of subscripts and
+                                                      * superscripts. */
+
+  public:
+  DEFINE_SIZE_ARRAY (4, mathKernInfoRecords);
+};
+
+struct MathGlyphInfo
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  mathItalicsCorrectionInfo.sanitize (c, this) &&
+                  mathTopAccentAttachment.sanitize (c, this) &&
+                  extendedShapeCoverage.sanitize (c, this) &&
+                  mathKernInfo.sanitize (c, this));
+  }
+
+  hb_position_t
+  get_italics_correction (hb_codepoint_t  glyph, hb_font_t *font) const
+  { return (this+mathItalicsCorrectionInfo).get_value (glyph, font); }
+
+  hb_position_t
+  get_top_accent_attachment (hb_codepoint_t  glyph, hb_font_t *font) const
+  { return (this+mathTopAccentAttachment).get_value (glyph, font); }
+
+  bool is_extended_shape (hb_codepoint_t glyph) const
+  { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; }
+
+  hb_position_t get_kerning (hb_codepoint_t glyph,
+                             hb_ot_math_kern_t kern,
+                             hb_position_t correction_height,
+                             hb_font_t *font) const
+  { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); }
+
+  protected:
+  /* Offset to MathItalicsCorrectionInfo table -
+   * from the beginning of MathGlyphInfo table. */
+  OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
+
+  /* Offset to MathTopAccentAttachment table -
+   * from the beginning of MathGlyphInfo table. */
+  OffsetTo<MathTopAccentAttachment> mathTopAccentAttachment;
+
+  /* Offset to coverage table for Extended Shape glyphs -
+   * from the beginning of MathGlyphInfo table. When the left or right glyph of
+   * a box is an extended shape variant, the (ink) box (and not the default
+   * position defined by values in MathConstants table) should be used for
+   * vertical positioning purposes.  May be NULL.. */
+  OffsetTo<Coverage> extendedShapeCoverage;
+
+   /* Offset to MathKernInfo table -
+    * from the beginning of MathGlyphInfo table. */
+  OffsetTo<MathKernInfo> mathKernInfo;
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct MathGlyphVariantRecord
+{
+  friend struct MathGlyphConstruction;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  GlyphID variantGlyph;       /* Glyph ID for the variant. */
+  HBUINT16  advanceMeasurement; /* Advance width/height, in design units, of the
+                                 * variant, in the direction of requested
+                                 * glyph extension. */
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct PartFlags : HBUINT16
+{
+  enum Flags {
+    Extender    = 0x0001u, /* If set, the part can be skipped or repeated. */
+
+    Defined     = 0x0001u, /* All defined flags. */
+  };
+
+  public:
+  DEFINE_SIZE_STATIC (2);
+};
+
+struct MathGlyphPartRecord
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  void extract (hb_ot_math_glyph_part_t &out,
+                int scale,
+                hb_font_t *font) const
+  {
+    out.glyph                   = glyph;
+
+    out.start_connector_length  = font->em_scale (startConnectorLength, scale);
+    out.end_connector_length    = font->em_scale (endConnectorLength, scale);
+    out.full_advance            = font->em_scale (fullAdvance, scale);
+
+    static_assert ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER ==
+                   (unsigned int) PartFlags::Extender, "");
+
+    out.flags = (hb_ot_math_glyph_part_flags_t)
+                (unsigned int)
+                (partFlags & PartFlags::Defined);
+  }
+
+  protected:
+  GlyphID   glyph;                /* Glyph ID for the part. */
+  HBUINT16    startConnectorLength; /* Advance width/ height of the straight bar
+                                   * connector material, in design units, is at
+                                   * the beginning of the glyph, in the
+                                   * direction of the extension. */
+  HBUINT16    endConnectorLength;   /* Advance width/ height of the straight bar
+                                   * connector material, in design units, is at
+                                   * the end of the glyph, in the direction of
+                                   * the extension. */
+  HBUINT16    fullAdvance;        /* Full advance width/height for this part,
+                                   * in the direction of the extension.
+                                   * In design units. */
+  PartFlags partFlags;            /* Part qualifiers. */
+
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+struct MathGlyphAssembly
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  italicsCorrection.sanitize (c, this) &&
+                  partRecords.sanitize (c));
+  }
+
+  unsigned int get_parts (hb_direction_t direction,
+                          hb_font_t *font,
+                          unsigned int start_offset,
+                          unsigned int *parts_count, /* IN/OUT */
+                          hb_ot_math_glyph_part_t *parts /* OUT */,
+                          hb_position_t *italics_correction /* OUT */) const
+  {
+    if (parts_count)
+    {
+      int scale = font->dir_scale (direction);
+      hb_array_t<const MathGlyphPartRecord> arr = partRecords.sub_array (start_offset, parts_count);
+      unsigned int count = arr.length;
+      for (unsigned int i = 0; i < count; i++)
+        arr[i].extract (parts[i], scale, font);
+    }
+
+    if (italics_correction)
+      *italics_correction = italicsCorrection.get_x_value (font, this);
+
+    return partRecords.len;
+  }
+
+  protected:
+  MathValueRecord          italicsCorrection; /* Italics correction of this
+                                               * MathGlyphAssembly. Should not
+                                               * depend on the assembly size. */
+  ArrayOf<MathGlyphPartRecord> partRecords;   /* Array of part records, from
+                                               * left to right and bottom to
+                                               * top. */
+
+  public:
+  DEFINE_SIZE_ARRAY (6, partRecords);
+};
+
+struct MathGlyphConstruction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  glyphAssembly.sanitize (c, this) &&
+                  mathGlyphVariantRecord.sanitize (c));
+  }
+
+  const MathGlyphAssembly &get_assembly () const { return this+glyphAssembly; }
+
+  unsigned int get_variants (hb_direction_t direction,
+                             hb_font_t *font,
+                             unsigned int start_offset,
+                             unsigned int *variants_count, /* IN/OUT */
+                             hb_ot_math_glyph_variant_t *variants /* OUT */) const
+  {
+    if (variants_count)
+    {
+      int scale = font->dir_scale (direction);
+      hb_array_t<const MathGlyphVariantRecord> arr = mathGlyphVariantRecord.sub_array (start_offset, variants_count);
+      unsigned int count = arr.length;
+      for (unsigned int i = 0; i < count; i++)
+      {
+        variants[i].glyph = arr[i].variantGlyph;
+        variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale);
+      }
+    }
+    return mathGlyphVariantRecord.len;
+  }
+
+  protected:
+  /* Offset to MathGlyphAssembly table for this shape - from the beginning of
+     MathGlyphConstruction table.  May be NULL. */
+  OffsetTo<MathGlyphAssembly>     glyphAssembly;
+
+  /* MathGlyphVariantRecords for alternative variants of the glyphs. */
+  ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord;
+
+  public:
+  DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord);
+};
+
+struct MathVariants
+{
+  bool sanitize_offsets (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    unsigned int count = vertGlyphCount + horizGlyphCount;
+    for (unsigned int i = 0; i < count; i++)
+      if (!glyphConstruction.arrayZ[i].sanitize (c, this)) return_trace (false);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  vertGlyphCoverage.sanitize (c, this) &&
+                  horizGlyphCoverage.sanitize (c, this) &&
+                  c->check_array (glyphConstruction.arrayZ, vertGlyphCount + horizGlyphCount) &&
+                  sanitize_offsets (c));
+  }
+
+  hb_position_t get_min_connector_overlap (hb_direction_t direction,
+                                                  hb_font_t *font) const
+  { return font->em_scale_dir (minConnectorOverlap, direction); }
+
+  unsigned int get_glyph_variants (hb_codepoint_t glyph,
+                                   hb_direction_t direction,
+                                   hb_font_t *font,
+                                   unsigned int start_offset,
+                                   unsigned int *variants_count, /* IN/OUT */
+                                   hb_ot_math_glyph_variant_t *variants /* OUT */) const
+  { return get_glyph_construction (glyph, direction, font)
+           .get_variants (direction, font, start_offset, variants_count, variants); }
+
+  unsigned int get_glyph_parts (hb_codepoint_t glyph,
+                                       hb_direction_t direction,
+                                       hb_font_t *font,
+                                       unsigned int start_offset,
+                                       unsigned int *parts_count, /* IN/OUT */
+                                       hb_ot_math_glyph_part_t *parts /* OUT */,
+                                       hb_position_t *italics_correction /* OUT */) const
+  { return get_glyph_construction (glyph, direction, font)
+           .get_assembly ()
+           .get_parts (direction, font,
+                       start_offset, parts_count, parts,
+                       italics_correction); }
+
+  private:
+  const MathGlyphConstruction &
+  get_glyph_construction (hb_codepoint_t glyph,
+                          hb_direction_t direction,
+                          hb_font_t *font HB_UNUSED) const
+  {
+    bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
+    unsigned int count = vertical ? vertGlyphCount : horizGlyphCount;
+    const OffsetTo<Coverage> &coverage = vertical ? vertGlyphCoverage
+                                                  : horizGlyphCoverage;
+
+    unsigned int index = (this+coverage).get_coverage (glyph);
+    if (unlikely (index >= count)) return Null (MathGlyphConstruction);
+
+    if (!vertical)
+      index += vertGlyphCount;
+
+    return this+glyphConstruction[index];
+  }
+
+  protected:
+  HBUINT16           minConnectorOverlap; /* Minimum overlap of connecting
+                                           * glyphs during glyph construction,
+                                           * in design units. */
+  OffsetTo<Coverage> vertGlyphCoverage;   /* Offset to Coverage table -
+                                           * from the beginning of MathVariants
+                                           * table. */
+  OffsetTo<Coverage> horizGlyphCoverage;  /* Offset to Coverage table -
+                                           * from the beginning of MathVariants
+                                           * table. */
+  HBUINT16           vertGlyphCount;      /* Number of glyphs for which
+                                           * information is provided for
+                                           * vertically growing variants. */
+  HBUINT16           horizGlyphCount;     /* Number of glyphs for which
+                                           * information is provided for
+                                           * horizontally growing variants. */
+
+  /* Array of offsets to MathGlyphConstruction tables - from the beginning of
+     the MathVariants table, for shapes growing in vertical/horizontal
+     direction. */
+  UnsizedArrayOf<OffsetTo<MathGlyphConstruction> >
+                        glyphConstruction;
+
+  public:
+  DEFINE_SIZE_ARRAY (10, glyphConstruction);
+};
+
+
+/*
+ * MATH -- Mathematical typesetting
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/math
+ */
+
+struct MATH
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_MATH;
+
+  bool has_data () const { return version.to_int (); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+                  likely (version.major == 1) &&
+                  mathConstants.sanitize (c, this) &&
+                  mathGlyphInfo.sanitize (c, this) &&
+                  mathVariants.sanitize (c, this));
+  }
+
+  hb_position_t get_constant (hb_ot_math_constant_t  constant,
+                                     hb_font_t             *font) const
+  { return (this+mathConstants).get_value (constant, font); }
+
+  const MathGlyphInfo &get_glyph_info () const { return this+mathGlyphInfo; }
+
+  const MathVariants &get_variants () const    { return this+mathVariants; }
+
+  protected:
+  FixedVersion<>version;                /* Version of the MATH table
+                                         * initially set to 0x00010000u */
+  OffsetTo<MathConstants> mathConstants;/* MathConstants table */
+  OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */
+  OffsetTo<MathVariants>  mathVariants; /* MathVariants table */
+
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_MATH_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-math.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,253 @@
+/*
+ * Copyright © 2016  Igalia S.L.
+ *
+ *  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.
+ *
+ * Igalia Author(s): Frédéric Wang
+ */
+
+#include "hb-open-type.hh"
+
+#include "hb-ot-face.hh"
+#include "hb-ot-math-table.hh"
+
+
+/**
+ * SECTION:hb-ot-math
+ * @title: hb-ot-math
+ * @short_description: OpenType Math information
+ * @include: hb-ot.h
+ *
+ * Functions for fetching mathematics layout data from OpenType fonts.
+ **/
+
+
+/*
+ * OT::MATH
+ */
+
+/**
+ * hb_ot_math_has_data:
+ * @face: #hb_face_t to test
+ *
+ * This function allows to verify the presence of an OpenType MATH table on the
+ * face.
+ *
+ * Return value: true if face has a MATH table, false otherwise
+ *
+ * Since: 1.3.3
+ **/
+hb_bool_t
+hb_ot_math_has_data (hb_face_t *face)
+{
+  return face->table.MATH->has_data ();
+}
+
+/**
+ * hb_ot_math_get_constant:
+ * @font: #hb_font_t from which to retrieve the value
+ * @constant: #hb_ot_math_constant_t the constant to retrieve
+ *
+ * This function returns the requested math constants as a #hb_position_t.
+ * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN,
+ * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or
+ * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is
+ * actually an integer between 0 and 100 representing that percentage.
+ *
+ * Return value: the requested constant or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_constant (hb_font_t *font,
+                         hb_ot_math_constant_t constant)
+{
+  return font->face->table.MATH->get_constant(constant, font);
+}
+
+/**
+ * hb_ot_math_get_glyph_italics_correction:
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ *
+ * Return value: the italics correction of the glyph or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
+                                         hb_codepoint_t glyph)
+{
+  return font->face->table.MATH->get_glyph_info().get_italics_correction (glyph, font);
+}
+
+/**
+ * hb_ot_math_get_glyph_top_accent_attachment:
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ *
+ * Return value: the top accent attachment of the glyph or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
+                                            hb_codepoint_t glyph)
+{
+  return font->face->table.MATH->get_glyph_info().get_top_accent_attachment (glyph, font);
+}
+
+/**
+ * hb_ot_math_is_glyph_extended_shape:
+ * @face: a #hb_face_t to test
+ * @glyph: a glyph index to test
+ *
+ * Return value: true if the glyph is an extended shape, false otherwise
+ *
+ * Since: 1.3.3
+ **/
+hb_bool_t
+hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
+                                    hb_codepoint_t glyph)
+{
+  return face->table.MATH->get_glyph_info().is_extended_shape (glyph);
+}
+
+/**
+ * hb_ot_math_get_glyph_kerning:
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ * @kern: the #hb_ot_math_kern_t from which to retrieve the value
+ * @correction_height: the correction height to use to determine the kerning.
+ *
+ * This function tries to retrieve the MathKern table for the specified font,
+ * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the
+ * MathKern table to find one value that is greater or equal to specified
+ * correction_height. If one is found the corresponding value from the list of
+ * kerns is returned and otherwise the last kern value is returned.
+ *
+ * Return value: requested kerning or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_glyph_kerning (hb_font_t *font,
+                              hb_codepoint_t glyph,
+                              hb_ot_math_kern_t kern,
+                              hb_position_t correction_height)
+{
+  return font->face->table.MATH->get_glyph_info().get_kerning (glyph,
+                                                               kern,
+                                                               correction_height,
+                                                               font);
+}
+
+/**
+ * hb_ot_math_get_glyph_variants:
+ * @font: #hb_font_t from which to retrieve the values
+ * @glyph: index of the glyph to stretch
+ * @direction: direction of the stretching
+ * @start_offset: offset of the first variant to retrieve
+ * @variants_count: maximum number of variants to retrieve after start_offset
+ * (IN) and actual number of variants retrieved (OUT)
+ * @variants: array of size at least @variants_count to store the result
+ *
+ * This function tries to retrieve the MathGlyphConstruction for the specified
+ * font, glyph and direction. Note that only the value of
+ * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list
+ * of size variants as an array of hb_ot_math_glyph_variant_t structs.
+ *
+ * Return value: the total number of size variants available or 0
+ *
+ * Since: 1.3.3
+ **/
+unsigned int
+hb_ot_math_get_glyph_variants (hb_font_t *font,
+                               hb_codepoint_t glyph,
+                               hb_direction_t direction,
+                               unsigned int start_offset,
+                               unsigned int *variants_count, /* IN/OUT */
+                               hb_ot_math_glyph_variant_t *variants /* OUT */)
+{
+  return font->face->table.MATH->get_variants().get_glyph_variants (glyph, direction, font,
+                                                                    start_offset,
+                                                                    variants_count,
+                                                                    variants);
+}
+
+/**
+ * hb_ot_math_get_min_connector_overlap:
+ * @font: #hb_font_t from which to retrieve the value
+ * @direction: direction of the stretching
+ *
+ * This function tries to retrieve the MathVariants table for the specified
+ * font and returns the minimum overlap of connecting glyphs to draw a glyph
+ * assembly in the specified direction. Note that only the value of
+ * #HB_DIRECTION_IS_HORIZONTAL is considered.
+ *
+ * Return value: requested min connector overlap or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_min_connector_overlap (hb_font_t *font,
+                                      hb_direction_t direction)
+{
+  return font->face->table.MATH->get_variants().get_min_connector_overlap (direction, font);
+}
+
+/**
+ * hb_ot_math_get_glyph_assembly:
+ * @font: #hb_font_t from which to retrieve the values
+ * @glyph: index of the glyph to stretch
+ * @direction: direction of the stretching
+ * @start_offset: offset of the first glyph part to retrieve
+ * @parts_count: maximum number of glyph parts to retrieve after start_offset
+ * (IN) and actual number of parts retrieved (OUT)
+ * @parts: array of size at least @parts_count to store the result
+ * @italics_correction: italic correction of the glyph assembly
+ *
+ * This function tries to retrieve the GlyphAssembly for the specified font,
+ * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL
+ * is considered. It provides the information necessary to draw the glyph
+ * assembly as an array of #hb_ot_math_glyph_part_t.
+ *
+ * Return value: the total number of parts in the glyph assembly
+ *
+ * Since: 1.3.3
+ **/
+unsigned int
+hb_ot_math_get_glyph_assembly (hb_font_t *font,
+                               hb_codepoint_t glyph,
+                               hb_direction_t direction,
+                               unsigned int start_offset,
+                               unsigned int *parts_count, /* IN/OUT */
+                               hb_ot_math_glyph_part_t *parts, /* OUT */
+                               hb_position_t *italics_correction /* OUT */)
+{
+  return font->face->table.MATH->get_variants().get_glyph_parts (glyph,
+                                                                 direction,
+                                                                 font,
+                                                                 start_offset,
+                                                                 parts_count,
+                                                                 parts,
+                                                                 italics_correction);
+}
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-maxp-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-maxp-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,8 +27,7 @@
 #ifndef HB_OT_MAXP_TABLE_HH
 #define HB_OT_MAXP_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-subset-plan.hh"
+#include "hb-open-type.hh"
 
 namespace OT {
 
@@ -42,7 +41,7 @@
 
 struct maxpV1Tail
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -72,19 +71,16 @@
 
 struct maxp
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_maxp;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_maxp;
 
-  inline unsigned int get_num_glyphs (void) const
-  {
-    return numGlyphs;
-  }
+  unsigned int get_num_glyphs () const { return numGlyphs; }
 
-  inline void set_num_glyphs (unsigned int count)
+  void set_num_glyphs (unsigned int count)
   {
     numGlyphs.set (count);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
@@ -93,23 +89,23 @@
     if (version.major == 1)
     {
       const maxpV1Tail &v1 = StructAfter<maxpV1Tail> (*this);
-      return v1.sanitize (c);
+      return_trace (v1.sanitize (c));
     }
     return_trace (likely (version.major == 0 && version.minor == 0x5000u));
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
-    hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_maxp));
+    hb_blob_t *maxp_blob = hb_sanitize_context_t().reference_table<maxp> (plan->source);
     hb_blob_t *maxp_prime_blob = hb_blob_copy_writable_or_fail (maxp_blob);
     hb_blob_destroy (maxp_blob);
 
     if (unlikely (!maxp_prime_blob)) {
       return false;
     }
-    OT::maxp *maxp_prime = (OT::maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
+    maxp *maxp_prime = (maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
 
-    maxp_prime->set_num_glyphs (plan->glyphs.len);
+    maxp_prime->set_num_glyphs (plan->glyphs.length);
     if (plan->drop_hints)
       drop_hint_fields (plan, maxp_prime);
 
@@ -118,7 +114,7 @@
     return result;
   }
 
-  static inline void drop_hint_fields (hb_subset_plan_t *plan, OT::maxp *maxp_prime)
+  static void drop_hint_fields (hb_subset_plan_t *plan HB_UNUSED, maxp *maxp_prime)
   {
     if (maxp_prime->version.major == 1)
     {
@@ -137,7 +133,7 @@
   FixedVersion<>version;                /* Version of the maxp table (0.5 or 1.0),
                                          * 0x00005000u or 0x00010000u. */
   HBUINT16      numGlyphs;              /* The number of glyphs in the font. */
-/*maxpV1Tail v1Tail[VAR]; */
+/*maxpV1Tail    v1Tail[VAR]; */
   public:
   DEFINE_SIZE_STATIC (6);
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name-language.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,457 @@
+/*
+ * 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
+ */
+
+#include "hb-ot-name-language.hh"
+
+/* Following two tables were generated by joining FreeType, FontConfig,
+ * and OpenType specification language lists, then filled in missing
+ * entries using:
+ * https://docs.microsoft.com/en-us/windows/desktop/intl/language-identifier-constants-and-strings
+ */
+
+struct hb_ot_language_map_t
+{
+  static int cmp (const void *key, const void *item)
+  {
+    unsigned int a = * (unsigned int *) key;
+    unsigned int b = ((const hb_ot_language_map_t *) item)->code;
+    return a < b ? -1 : a > b ? +1 : 0;
+  }
+
+  uint16_t      code;
+  char          lang[6];
+};
+
+static const hb_ot_language_map_t
+hb_ms_language_map[] =
+{
+  {0x0001,      "ar"},  /* ??? */
+  {0x0004,      "zh"},  /* ??? */
+  {0x0009,      "en"},  /* ??? */
+  {0x0401,      "ar"},  /* Arabic (Saudi Arabia) */
+  {0x0402,      "bg"},  /* Bulgarian (Bulgaria) */
+  {0x0403,      "ca"},  /* Catalan (Catalan) */
+  {0x0404,      "zh-tw"},       /* Chinese (Taiwan) */
+  {0x0405,      "cs"},  /* Czech (Czech Republic) */
+  {0x0406,      "da"},  /* Danish (Denmark) */
+  {0x0407,      "de"},  /* German (Germany) */
+  {0x0408,      "el"},  /* Greek (Greece) */
+  {0x0409,      "en"},  /* English (United States) */
+  {0x040A,      "es"},  /* Spanish (Traditional Sort) (Spain) */
+  {0x040B,      "fi"},  /* Finnish (Finland) */
+  {0x040C,      "fr"},  /* French (France) */
+  {0x040D,      "he"},  /* Hebrew (Israel) */
+  {0x040E,      "hu"},  /* Hungarian (Hungary) */
+  {0x040F,      "is"},  /* Icelandic (Iceland) */
+  {0x0410,      "it"},  /* Italian (Italy) */
+  {0x0411,      "ja"},  /* Japanese (Japan) */
+  {0x0412,      "ko"},  /* Korean (Korea) */
+  {0x0413,      "nl"},  /* Dutch (Netherlands) */
+  {0x0414,      "no"},  /* Norwegian (Bokmal) (Norway) */
+  {0x0415,      "pl"},  /* Polish (Poland) */
+  {0x0416,      "pt"},  /* Portuguese (Brazil) */
+  {0x0417,      "rm"},  /* Romansh (Switzerland) */
+  {0x0418,      "ro"},  /* Romanian (Romania) */
+  {0x0419,      "ru"},  /* Russian (Russia) */
+  {0x041A,      "hr"},  /* Croatian (Croatia) */
+  {0x041B,      "sk"},  /* Slovak (Slovakia) */
+  {0x041C,      "sq"},  /* Albanian (Albania) */
+  {0x041D,      "sv"},  /* Swedish (Sweden) */
+  {0x041E,      "th"},  /* Thai (Thailand) */
+  {0x041F,      "tr"},  /* Turkish (Turkey) */
+  {0x0420,      "ur"},  /* Urdu (Islamic Republic of Pakistan) */
+  {0x0421,      "id"},  /* Indonesian (Indonesia) */
+  {0x0422,      "uk"},  /* Ukrainian (Ukraine) */
+  {0x0423,      "be"},  /* Belarusian (Belarus) */
+  {0x0424,      "sl"},  /* Slovenian (Slovenia) */
+  {0x0425,      "et"},  /* Estonian (Estonia) */
+  {0x0426,      "lv"},  /* Latvian (Latvia) */
+  {0x0427,      "lt"},  /* Lithuanian (Lithuania) */
+  {0x0428,      "tg"},  /* Tajik (Cyrillic) (Tajikistan) */
+  {0x0429,      "fa"},  /* Persian (Iran) */
+  {0x042A,      "vi"},  /* Vietnamese (Vietnam) */
+  {0x042B,      "hy"},  /* Armenian (Armenia) */
+  {0x042C,      "az"},  /* Azeri (Latin) (Azerbaijan) */
+  {0x042D,      "eu"},  /* Basque (Basque) */
+  {0x042E,      "hsb"}, /* Upper Sorbian (Germany) */
+  {0x042F,      "mk"},  /* Macedonian (FYROM) (Former Yugoslav Republic of Macedonia) */
+  {0x0430,      "st"},  /* ??? */
+  {0x0431,      "ts"},  /* ??? */
+  {0x0432,      "tn"},  /* Setswana (South Africa) */
+  {0x0433,      "ven"}, /* ??? */
+  {0x0434,      "xh"},  /* isiXhosa (South Africa) */
+  {0x0435,      "zu"},  /* isiZulu (South Africa) */
+  {0x0436,      "af"},  /* Afrikaans (South Africa) */
+  {0x0437,      "ka"},  /* Georgian (Georgia) */
+  {0x0438,      "fo"},  /* Faroese (Faroe Islands) */
+  {0x0439,      "hi"},  /* Hindi (India) */
+  {0x043A,      "mt"},  /* Maltese (Malta) */
+  {0x043B,      "se"},  /* Sami (Northern) (Norway) */
+  {0x043C,      "ga"},  /* ??? */
+  {0x043D,      "yi"},  /* ??? */
+  {0x043E,      "ms"},  /* Malay (Malaysia) */
+  {0x043F,      "kk"},  /* Kazakh (Kazakhstan) */
+  {0x0440,      "ky"},  /* Kyrgyz (Kyrgyzstan) */
+  {0x0441,      "sw"},  /* Kiswahili (Kenya) */
+  {0x0442,      "tk"},  /* Turkmen (Turkmenistan) */
+  {0x0443,      "uz"},  /* Uzbek (Latin) (Uzbekistan) */
+  {0x0444,      "tt"},  /* Tatar (Russia) */
+  {0x0445,      "bn"},  /* Bengali (India) */
+  {0x0446,      "pa"},  /* Punjabi (India) */
+  {0x0447,      "gu"},  /* Gujarati (India) */
+  {0x0448,      "or"},  /* Odia (formerly Oriya) (India) */
+  {0x0449,      "ta"},  /* Tamil (India) */
+  {0x044A,      "te"},  /* Telugu (India) */
+  {0x044B,      "kn"},  /* Kannada (India) */
+  {0x044C,      "ml"},  /* Malayalam (India) */
+  {0x044D,      "as"},  /* Assamese (India) */
+  {0x044E,      "mr"},  /* Marathi (India) */
+  {0x044F,      "sa"},  /* Sanskrit (India) */
+  {0x0450,      "mn"},  /* Mongolian (Cyrillic) (Mongolia) */
+  {0x0451,      "bo"},  /* Tibetan (PRC) */
+  {0x0452,      "cy"},  /* Welsh (United Kingdom) */
+  {0x0453,      "km"},  /* Khmer (Cambodia) */
+  {0x0454,      "lo"},  /* Lao (Lao P.D.R.) */
+  {0x0455,      "my"},  /* ??? */
+  {0x0456,      "gl"},  /* Galician (Galician) */
+  {0x0457,      "kok"}, /* Konkani (India) */
+  {0x0458,      "mni"}, /* ??? */
+  {0x0459,      "sd"},  /* ??? */
+  {0x045A,      "syr"}, /* Syriac (Syria) */
+  {0x045B,      "si"},  /* Sinhala (Sri Lanka) */
+  {0x045C,      "chr"}, /* ??? */
+  {0x045D,      "iu"},  /* Inuktitut (Canada) */
+  {0x045E,      "am"},  /* Amharic (Ethiopia) */
+  {0x0460,      "ks"},  /* ??? */
+  {0x0461,      "ne"},  /* Nepali (Nepal) */
+  {0x0462,      "fy"},  /* Frisian (Netherlands) */
+  {0x0463,      "ps"},  /* Pashto (Afghanistan) */
+  {0x0464,      "phi"}, /* Filipino (Philippines) */
+  {0x0465,      "div"}, /* Divehi (Maldives) */
+  {0x0468,      "ha"},  /* Hausa (Latin) (Nigeria) */
+  {0x046A,      "yo"},  /* Yoruba (Nigeria) */
+  {0x046B,      "quz"}, /* Quechua (Bolivia) */
+  {0x046C,      "nso"}, /* Sesotho sa Leboa (South Africa) */
+  {0x046D,      "ba"},  /* Bashkir (Russia) */
+  {0x046E,      "lb"},  /* Luxembourgish (Luxembourg) */
+  {0x046F,      "kl"},  /* Greenlandic (Greenland) */
+  {0x0470,      "ibo"}, /* Igbo (Nigeria) */
+  {0x0471,      "kau"}, /* ??? */
+  {0x0472,      "om"},  /* ??? */
+  {0x0473,      "ti"},  /* ??? */
+  {0x0474,      "gn"},  /* ??? */
+  {0x0475,      "haw"}, /* ??? */
+  {0x0476,      "la"},  /* ??? */
+  {0x0477,      "so"},  /* ??? */
+  {0x0478,      "ii"},  /* Yi (PRC) */
+  {0x0479,      "pap"}, /* ??? */
+  {0x047A,      "arn"}, /* Mapudungun (Chile) */
+  {0x047C,      "moh"}, /* Mohawk (Mohawk) */
+  {0x047E,      "br"},  /* Breton (France) */
+  {0x0480,      "ug"},  /* Uighur (PRC) */
+  {0x0481,      "mi"},  /* Maori (New Zealand) */
+  {0x0482,      "oc"},  /* Occitan (France) */
+  {0x0483,      "co"},  /* Corsican (France) */
+  {0x0484,      "gsw"}, /* Alsatian (France) */
+  {0x0485,      "sah"}, /* Yakut (Russia) */
+  {0x0486,      "qut"}, /* K'iche (Guatemala) */
+  {0x0487,      "rw"},  /* Kinyarwanda (Rwanda) */
+  {0x0488,      "wo"},  /* Wolof (Senegal) */
+  {0x048C,      "fa"},  /* Dari (Afghanistan) */
+  {0x0801,      "ar"},  /* Arabic (Iraq) */
+  {0x0804,      "zh-cn"},       /* Chinese (People’s Republic of China) */
+  {0x0807,      "de"},  /* German (Switzerland) */
+  {0x0809,      "en"},  /* English (United Kingdom) */
+  {0x080A,      "es"},  /* Spanish (Mexico) */
+  {0x080C,      "fr"},  /* French (Belgium) */
+  {0x0810,      "it"},  /* Italian (Switzerland) */
+  {0x0812,      "ko"},  /* ??? */
+  {0x0813,      "nl"},  /* Dutch (Belgium) */
+  {0x0814,      "nn"},  /* Norwegian (Nynorsk) (Norway) */
+  {0x0816,      "pt"},  /* Portuguese (Portugal) */
+  {0x0818,      "mo"},  /* ??? */
+  {0x0819,      "ru"},  /* ??? */
+  {0x081A,      "sr"},  /* Serbian (Latin) (Serbia) */
+  {0x081D,      "sv"},  /* Sweden (Finland) */
+  {0x0820,      "ur"},  /* ??? */
+  {0x0827,      "lt"},  /* ??? */
+  {0x082C,      "az"},  /* Azeri (Cyrillic) (Azerbaijan) */
+  {0x082E,      "dsb"}, /* Lower Sorbian (Germany) */
+//{0x083B,      ""},    /* Sami (Northern) (Sweden) */
+  {0x083C,      "gd"},  /* Irish (Ireland) */
+  {0x083E,      "ms"},  /* Malay (Brunei Darussalam) */
+  {0x0843,      "uz"},  /* Uzbek (Cyrillic) (Uzbekistan) */
+  {0x0845,      "bn"},  /* Bengali (Bangladesh) */
+  {0x0846,      "ar"},  /* ??? */
+  {0x0850,      "mn"},  /* Mongolian (Traditional) (People’s Republic of China) */
+  {0x0851,      "dz"},  /* ??? */
+  {0x085D,      "iu"},  /* Inuktitut (Latin) (Canada) */
+  {0x085F,      "tzm"}, /* Tamazight (Latin) (Algeria) */
+  {0x0861,      "ne"},  /* ??? */
+//{0x086B,      ""},    /* Quechua (Ecuador) */
+  {0x0873,      "ti"},  /* ??? */
+  {0x0C01,      "ar"},  /* Arabic (Egypt) */
+  {0x0C04,      "zh-hk"},       /* Chinese (Hong Kong S.A.R.) */
+  {0x0C07,      "de"},  /* German (Austria) */
+  {0x0C09,      "en"},  /* English (Australia) */
+  {0x0C0A,      "es"},  /* Spanish (Modern Sort) (Spain) */
+  {0x0C0C,      "fr"},  /* French (Canada) */
+  {0x0C1A,      "sr"},  /* Serbian (Cyrillic) (Serbia) */
+  {0x0C3B,      "se"},  /* Sami (Northern) (Finland) */
+//{0x0C6B,      ""},    /* Quechua (Peru) */
+  {0x1001,      "ar"},  /* Arabic (Libya) */
+  {0x1004,      "zh-sg"},       /* Chinese (Singapore) */
+  {0x1007,      "de"},  /* German (Luxembourg) */
+  {0x1009,      "en"},  /* English (Canada) */
+  {0x100A,      "es"},  /* Spanish (Guatemala) */
+  {0x100C,      "fr"},  /* French (Switzerland) */
+  {0x101A,      "hr"},  /* Croatian (Latin) (Bosnia and Herzegovina) */
+  {0x103B,      "smj"}, /* Sami (Lule) (Norway) */
+  {0x1401,      "ar"},  /* Arabic (Algeria) */
+//{0x1404,      ""},    /* Chinese (Macao S.A.R.) */
+  {0x1407,      "de"},  /* German (Liechtenstein) */
+  {0x1409,      "en"},  /* English (New Zealand) */
+  {0x140A,      "es"},  /* Spanish (Costa Rica) */
+  {0x140C,      "fr"},  /* French (Luxembourg) */
+  {0x141A,      "bs"},  /* Bosnian (Latin) (Bosnia and Herzegovina) */
+//{0x143B,      ""},    /* Sami (Lule) (Sweden) */
+  {0x1801,      "ar"},  /* Arabic (Morocco) */
+  {0x1809,      "en"},  /* English (Ireland) */
+  {0x180A,      "es"},  /* Spanish (Panama) */
+  {0x180C,      "fr"},  /* French (Principality of Monaco) */
+//{0x181A,      ""},    /* Serbian (Latin) (Bosnia and Herzegovina) */
+  {0x183B,      "sma"}, /* Sami (Southern) (Norway) */
+  {0x1C01,      "ar"},  /* Arabic (Tunisia) */
+  {0x1C09,      "en"},  /* English (South Africa) */
+  {0x1C0A,      "es"},  /* Spanish (Dominican Republic) */
+  {0x1C0C,      "fr"},  /* ??? */
+//{0x1C1A,      ""},    /* Serbian (Cyrillic) (Bosnia and Herzegovina) */
+//{0x1C3B,      ""},    /* Sami (Southern) (Sweden) */
+  {0x2001,      "ar"},  /* Arabic (Oman) */
+  {0x2009,      "en"},  /* English (Jamaica) */
+  {0x200A,      "es"},  /* Spanish (Venezuela) */
+  {0x200C,      "fr"},  /* ??? */
+  {0x201A,      "bs"},  /* Bosnian (Cyrillic) (Bosnia and Herzegovina) */
+  {0x203B,      "sms"}, /* Sami (Skolt) (Finland) */
+  {0x2401,      "ar"},  /* Arabic (Yemen) */
+  {0x2409,      "en"},  /* English (Caribbean) */
+  {0x240A,      "es"},  /* Spanish (Colombia) */
+  {0x240C,      "fr"},  /* ??? */
+  {0x243B,      "smn"}, /* Sami (Inari) (Finland) */
+  {0x2801,      "ar"},  /* Arabic (Syria) */
+  {0x2809,      "en"},  /* English (Belize) */
+  {0x280A,      "es"},  /* Spanish (Peru) */
+  {0x280C,      "fr"},  /* ??? */
+  {0x2C01,      "ar"},  /* Arabic (Jordan) */
+  {0x2C09,      "en"},  /* English (Trinidad and Tobago) */
+  {0x2C0A,      "es"},  /* Spanish (Argentina) */
+  {0x2C0C,      "fr"},  /* ??? */
+  {0x3001,      "ar"},  /* Arabic (Lebanon) */
+  {0x3009,      "en"},  /* English (Zimbabwe) */
+  {0x300A,      "es"},  /* Spanish (Ecuador) */
+  {0x300C,      "fr"},  /* ??? */
+  {0x3401,      "ar"},  /* Arabic (Kuwait) */
+  {0x3409,      "en"},  /* English (Republic of the Philippines) */
+  {0x340A,      "es"},  /* Spanish (Chile) */
+  {0x340C,      "fr"},  /* ??? */
+  {0x3801,      "ar"},  /* Arabic (U.A.E.) */
+  {0x380A,      "es"},  /* Spanish (Uruguay) */
+  {0x380C,      "fr"},  /* ??? */
+  {0x3C01,      "ar"},  /* Arabic (Bahrain) */
+  {0x3C09,      "en"},  /* ??? */
+  {0x3C0A,      "es"},  /* Spanish (Paraguay) */
+  {0x3C0C,      "fr"},  /* ??? */
+  {0x4001,      "ar"},  /* Arabic (Qatar) */
+  {0x4009,      "en"},  /* English (India) */
+  {0x400A,      "es"},  /* Spanish (Bolivia) */
+  {0x4409,      "en"},  /* English (Malaysia) */
+  {0x440A,      "es"},  /* Spanish (El Salvador) */
+  {0x4809,      "en"},  /* English (Singapore) */
+  {0x480A,      "es"},  /* Spanish (Honduras) */
+  {0x4C0A,      "es"},  /* Spanish (Nicaragua) */
+  {0x500A,      "es"},  /* Spanish (Puerto Rico) */
+  {0x540A,      "es"},  /* Spanish (United States) */
+  {0xE40A,      "es"},  /* ??? */
+  {0xE40C,      "fr"},  /* ??? */
+};
+
+static const hb_ot_language_map_t
+hb_mac_language_map[] =
+{
+  {  0, "en"},  /* English */
+  {  1, "fr"},  /* French */
+  {  2, "de"},  /* German */
+  {  3, "it"},  /* Italian */
+  {  4, "nl"},  /* Dutch */
+  {  5, "sv"},  /* Swedish */
+  {  6, "es"},  /* Spanish */
+  {  7, "da"},  /* Danish */
+  {  8, "pt"},  /* Portuguese */
+  {  9, "no"},  /* Norwegian */
+  { 10, "he"},  /* Hebrew */
+  { 11, "ja"},  /* Japanese */
+  { 12, "ar"},  /* Arabic */
+  { 13, "fi"},  /* Finnish */
+  { 14, "el"},  /* Greek */
+  { 15, "is"},  /* Icelandic */
+  { 16, "mt"},  /* Maltese */
+  { 17, "tr"},  /* Turkish */
+  { 18, "hr"},  /* Croatian */
+  { 19, "zh-tw"},       /* Chinese (Traditional) */
+  { 20, "ur"},  /* Urdu */
+  { 21, "hi"},  /* Hindi */
+  { 22, "th"},  /* Thai */
+  { 23, "ko"},  /* Korean */
+  { 24, "lt"},  /* Lithuanian */
+  { 25, "pl"},  /* Polish */
+  { 26, "hu"},  /* Hungarian */
+  { 27, "et"},  /* Estonian */
+  { 28, "lv"},  /* Latvian */
+//{ 29, ""},    /* Sami */
+  { 30, "fo"},  /* Faroese */
+  { 31, "fa"},  /* Farsi/Persian */
+  { 32, "ru"},  /* Russian */
+  { 33, "zh-cn"},       /* Chinese (Simplified) */
+  { 34, "nl"},  /* Flemish */
+  { 35, "ga"},  /* Irish Gaelic */
+  { 36, "sq"},  /* Albanian */
+  { 37, "ro"},  /* Romanian */
+  { 38, "cs"},  /* Czech */
+  { 39, "sk"},  /* Slovak */
+  { 40, "sl"},  /* Slovenian */
+  { 41, "yi"},  /* Yiddish */
+  { 42, "sr"},  /* Serbian */
+  { 43, "mk"},  /* Macedonian */
+  { 44, "bg"},  /* Bulgarian */
+  { 45, "uk"},  /* Ukrainian */
+  { 46, "be"},  /* Byelorussian */
+  { 47, "uz"},  /* Uzbek */
+  { 48, "kk"},  /* Kazakh */
+  { 49, "az"},  /* Azerbaijani (Cyrillic script) */
+  { 50, "az"},  /* Azerbaijani (Arabic script) */
+  { 51, "hy"},  /* Armenian */
+  { 52, "ka"},  /* Georgian */
+  { 53, "mo"},  /* Moldavian */
+  { 54, "ky"},  /* Kirghiz */
+  { 55, "tg"},  /* Tajiki */
+  { 56, "tk"},  /* Turkmen */
+  { 57, "mn"},  /* Mongolian (Mongolian script) */
+  { 58, "mn"},  /* Mongolian (Cyrillic script) */
+  { 59, "ps"},  /* Pashto */
+  { 60, "ku"},  /* Kurdish */
+  { 61, "ks"},  /* Kashmiri */
+  { 62, "sd"},  /* Sindhi */
+  { 63, "bo"},  /* Tibetan */
+  { 64, "ne"},  /* Nepali */
+  { 65, "sa"},  /* Sanskrit */
+  { 66, "mr"},  /* Marathi */
+  { 67, "bn"},  /* Bengali */
+  { 68, "as"},  /* Assamese */
+  { 69, "gu"},  /* Gujarati */
+  { 70, "pa"},  /* Punjabi */
+  { 71, "or"},  /* Oriya */
+  { 72, "ml"},  /* Malayalam */
+  { 73, "kn"},  /* Kannada */
+  { 74, "ta"},  /* Tamil */
+  { 75, "te"},  /* Telugu */
+  { 76, "si"},  /* Sinhalese */
+  { 77, "my"},  /* Burmese */
+  { 78, "km"},  /* Khmer */
+  { 79, "lo"},  /* Lao */
+  { 80, "vi"},  /* Vietnamese */
+  { 81, "id"},  /* Indonesian */
+  { 82, "tl"},  /* Tagalog */
+  { 83, "ms"},  /* Malay (Roman script) */
+  { 84, "ms"},  /* Malay (Arabic script) */
+  { 85, "am"},  /* Amharic */
+  { 86, "ti"},  /* Tigrinya */
+  { 87, "om"},  /* Galla */
+  { 88, "so"},  /* Somali */
+  { 89, "sw"},  /* Swahili */
+  { 90, "rw"},  /* Kinyarwanda/Ruanda */
+  { 91, "rn"},  /* Rundi */
+  { 92, "ny"},  /* Nyanja/Chewa */
+  { 93, "mg"},  /* Malagasy */
+  { 94, "eo"},  /* Esperanto */
+  {128, "cy"},  /* Welsh */
+  {129, "eu"},  /* Basque */
+  {130, "ca"},  /* Catalan */
+  {131, "la"},  /* Latin */
+  {132, "qu"},  /* Quechua */
+  {133, "gn"},  /* Guarani */
+  {134, "ay"},  /* Aymara */
+  {135, "tt"},  /* Tatar */
+  {136, "ug"},  /* Uighur */
+  {137, "dz"},  /* Dzongkha */
+  {138, "jw"},  /* Javanese (Roman script) */
+  {139, "su"},  /* Sundanese (Roman script) */
+  {140, "gl"},  /* Galician */
+  {141, "af"},  /* Afrikaans */
+  {142, "br"},  /* Breton */
+  {143, "iu"},  /* Inuktitut */
+  {144, "gd"},  /* Scottish Gaelic */
+  {145, "gv"},  /* Manx Gaelic */
+  {146, "ga"},  /* Irish Gaelic (with dot above) */
+  {147, "to"},  /* Tongan */
+  {148, "el"},  /* Greek (polytonic) */
+  {149, "ik"},  /* Greenlandic */
+  {150, "az"},  /* Azerbaijani (Roman script) */
+};
+
+
+static hb_language_t
+_hb_ot_name_language_for (unsigned int code,
+                          const hb_ot_language_map_t *array,
+                          unsigned int len)
+{
+  const hb_ot_language_map_t *entry = (const hb_ot_language_map_t *)
+                                      hb_bsearch (&code,
+                                                  array,
+                                                  len,
+                                                  sizeof (array[0]),
+                                                  hb_ot_language_map_t::cmp);
+
+  if (entry)
+    return hb_language_from_string (entry->lang, -1);
+
+  return HB_LANGUAGE_INVALID;
+}
+
+hb_language_t
+_hb_ot_name_language_for_ms_code (unsigned int code)
+{
+  return _hb_ot_name_language_for (code,
+                                   hb_ms_language_map,
+                                   ARRAY_LENGTH (hb_ms_language_map));
+}
+
+hb_language_t
+_hb_ot_name_language_for_mac_code (unsigned int code)
+{
+  return _hb_ot_name_language_for (code,
+                                   hb_mac_language_map,
+                                   ARRAY_LENGTH (hb_mac_language_map));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name-language.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_NAME_LANGUAGE_HH
+#define HB_OT_NAME_LANGUAGE_HH
+
+#include "hb.hh"
+
+
+HB_INTERNAL hb_language_t
+_hb_ot_name_language_for_ms_code (unsigned int code);
+
+HB_INTERNAL hb_language_t
+_hb_ot_name_language_for_mac_code (unsigned int code);
+
+
+#endif /* HB_OT_NAME_LANGUAGE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,38 +27,73 @@
 #ifndef HB_OT_NAME_TABLE_HH
 #define HB_OT_NAME_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
+#include "hb-ot-name-language.hh"
+#include "hb-aat-layout.hh"
 
 
 namespace OT {
 
 
+#define entry_score var.u16[0]
+#define entry_index var.u16[1]
+
+
 /*
  * name -- Naming
  * https://docs.microsoft.com/en-us/typography/opentype/spec/name
  */
 #define HB_OT_TAG_name HB_TAG('n','a','m','e')
 
+#define UNSUPPORTED     42
 
 struct NameRecord
 {
-  static int cmp (const void *pa, const void *pb)
+  hb_language_t language (hb_face_t *face) const
   {
-    const NameRecord *a = (const NameRecord *) pa;
-    const NameRecord *b = (const NameRecord *) pb;
-    int ret;
-    ret = b->platformID.cmp (a->platformID);
-    if (ret) return ret;
-    ret = b->encodingID.cmp (a->encodingID);
-    if (ret) return ret;
-    ret = b->languageID.cmp (a->languageID);
-    if (ret) return ret;
-    ret = b->nameID.cmp (a->nameID);
-    if (ret) return ret;
-    return 0;
+    unsigned int p = platformID;
+    unsigned int l = languageID;
+
+    if (p == 3)
+      return _hb_ot_name_language_for_ms_code (l);
+
+    if (p == 1)
+      return _hb_ot_name_language_for_mac_code (l);
+
+    if (p == 0)
+      return _hb_aat_language_get (face, l);
+
+    return HB_LANGUAGE_INVALID;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  uint16_t score () const
+  {
+    /* Same order as in cmap::find_best_subtable(). */
+    unsigned int p = platformID;
+    unsigned int e = encodingID;
+
+    /* 32-bit. */
+    if (p == 3 && e == 10) return 0;
+    if (p == 0 && e ==  6) return 1;
+    if (p == 0 && e ==  4) return 2;
+
+    /* 16-bit. */
+    if (p == 3 && e ==  1) return 3;
+    if (p == 0 && e ==  3) return 4;
+    if (p == 0 && e ==  2) return 5;
+    if (p == 0 && e ==  1) return 6;
+    if (p == 0 && e ==  0) return 7;
+
+    /* Symbol. */
+    if (p == 3 && e ==  0) return 8;
+
+    /* We treat all Mac Latin names as ASCII only. */
+    if (p == 1 && e ==  0) return 10; /* 10 is magic number :| */
+
+    return UNSUPPORTED;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     /* We can check from base all the way up to the end of string... */
@@ -75,62 +110,168 @@
   DEFINE_SIZE_STATIC (12);
 };
 
+static int
+_hb_ot_name_entry_cmp_key (const void *pa, const void *pb)
+{
+  const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
+  const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
+
+  /* Compare by name_id, then language. */
+
+  if (a->name_id != b->name_id)
+    return a->name_id < b->name_id ? -1 : +1;
+
+  if (a->language == b->language) return 0;
+  if (!a->language) return -1;
+  if (!b->language) return +1;
+  return strcmp (hb_language_to_string (a->language),
+                 hb_language_to_string (b->language));
+}
+
+static int
+_hb_ot_name_entry_cmp (const void *pa, const void *pb)
+{
+  /* Compare by name_id, then language, then score, then index. */
+
+  int v = _hb_ot_name_entry_cmp_key (pa, pb);
+  if (v)
+    return v;
+
+  const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
+  const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
+
+  if (a->entry_score != b->entry_score)
+    return a->entry_score < b->entry_score ? -1 : +1;
+
+  if (a->entry_index != b->entry_index)
+    return a->entry_index < b->entry_index ? -1 : +1;
+
+  return 0;
+}
+
 struct name
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_name;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_name;
 
-  inline unsigned int get_name (unsigned int platform_id,
-                                unsigned int encoding_id,
-                                unsigned int language_id,
-                                unsigned int name_id,
-                                void *buffer,
-                                unsigned int buffer_length) const
-  {
-    NameRecord key;
-    key.platformID.set (platform_id);
-    key.encodingID.set (encoding_id);
-    key.languageID.set (language_id);
-    key.nameID.set (name_id);
-    NameRecord *match = (NameRecord *) bsearch (&key, nameRecord, count, sizeof (nameRecord[0]), NameRecord::cmp);
+  unsigned int get_size () const
+  { return min_size + count * nameRecordZ.item_size; }
 
-    if (!match)
-      return 0;
-
-    unsigned int length = MIN (buffer_length, (unsigned int) match->length);
-    memcpy (buffer, (char *) this + stringOffset + match->offset, length);
-    return length;
-  }
-
-  inline unsigned int get_size (void) const
-  { return min_size + count * nameRecord[0].min_size; }
-
-  inline bool sanitize_records (hb_sanitize_context_t *c) const {
+  bool sanitize_records (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
-    char *string_pool = (char *) this + stringOffset;
+    const void *string_pool = (this+stringOffset).arrayZ;
     unsigned int _count = count;
+    /* Move to run-time?! */
     for (unsigned int i = 0; i < _count; i++)
-      if (!nameRecord[i].sanitize (c, string_pool)) return_trace (false);
+      if (!nameRecordZ[i].sanitize (c, string_pool)) return_trace (false);
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                   likely (format == 0 || format == 1) &&
-                  c->check_array (nameRecord, nameRecord[0].static_size, count) &&
-                  sanitize_records (c));
+                  c->check_array (nameRecordZ.arrayZ, count) &&
+                  c->check_range (this, stringOffset));
   }
 
+  struct accelerator_t
+  {
+    void init (hb_face_t *face)
+    {
+      this->table = hb_sanitize_context_t().reference_table<name> (face);
+      assert (this->table.get_length () >= this->table->stringOffset);
+      this->pool = (const char *) (const void *) (this->table+this->table->stringOffset);
+      this->pool_len = this->table.get_length () - this->table->stringOffset;
+      const hb_array_t<const NameRecord> all_names (this->table->nameRecordZ.arrayZ,
+                                                    this->table->count);
+
+      this->names.init ();
+      this->names.alloc (all_names.length);
+
+      for (unsigned int i = 0; i < all_names.length; i++)
+      {
+        hb_ot_name_entry_t *entry = this->names.push ();
+
+        entry->name_id = all_names[i].nameID;
+        entry->language = all_names[i].language (face);
+        entry->entry_score =  all_names[i].score ();
+        entry->entry_index = i;
+      }
+
+      this->names.qsort (_hb_ot_name_entry_cmp);
+      /* Walk and pick best only for each name_id,language pair,
+       * while dropping unsupported encodings. */
+      unsigned int j = 0;
+      for (unsigned int i = 0; i < this->names.length; i++)
+      {
+        if (this->names[i].entry_score == UNSUPPORTED ||
+            this->names[i].language == HB_LANGUAGE_INVALID)
+          continue;
+        if (i &&
+            this->names[i - 1].name_id  == this->names[i].name_id &&
+            this->names[i - 1].language == this->names[i].language)
+          continue;
+        this->names[j++] = this->names[i];
+      }
+      this->names.resize (j);
+    }
+
+    void fini ()
+    {
+      this->names.fini ();
+      this->table.destroy ();
+    }
+
+    int get_index (hb_ot_name_id_t   name_id,
+                          hb_language_t     language,
+                          unsigned int     *width=nullptr) const
+    {
+      const hb_ot_name_entry_t key = {name_id, {0}, language};
+      const hb_ot_name_entry_t *entry = (const hb_ot_name_entry_t *)
+                                        hb_bsearch (&key,
+                                                    (const hb_ot_name_entry_t *) this->names,
+                                                    this->names.length,
+                                                    sizeof (key),
+                                                    _hb_ot_name_entry_cmp_key);
+      if (!entry)
+        return -1;
+
+      if (width)
+        *width = entry->entry_score < 10 ? 2 : 1;
+
+      return entry->entry_index;
+    }
+
+    hb_bytes_t get_name (unsigned int idx) const
+    {
+      const hb_array_t<const NameRecord> all_names (table->nameRecordZ.arrayZ, table->count);
+      const NameRecord &record = all_names[idx];
+      const hb_bytes_t string_pool (pool, pool_len);
+      return string_pool.sub_array (record.offset, record.length);
+    }
+
+    private:
+    const char *pool;
+    unsigned int pool_len;
+    public:
+    hb_blob_ptr_t<name> table;
+    hb_vector_t<hb_ot_name_entry_t> names;
+  };
+
   /* We only implement format 0 for now. */
   HBUINT16      format;                 /* Format selector (=0/1). */
   HBUINT16      count;                  /* Number of name records. */
-  Offset16      stringOffset;           /* Offset to start of string storage (from start of table). */
-  NameRecord    nameRecord[VAR];        /* The name records where count is the number of records. */
+  NNOffsetTo<UnsizedArrayOf<HBUINT8> >
+                stringOffset;           /* Offset to start of string storage (from start of table). */
+  UnsizedArrayOf<NameRecord>
+                nameRecordZ;            /* The name records where count is the number of records. */
   public:
-  DEFINE_SIZE_ARRAY (6, nameRecord);
+  DEFINE_SIZE_ARRAY (6, nameRecordZ);
 };
 
+struct name_accelerator_t : name::accelerator_t {};
 
 } /* namespace OT */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,224 @@
+/*
+ * 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
+ */
+
+#include "hb.hh"
+
+#include "hb-ot-name-table.hh"
+
+#include "hb-ot-face.hh"
+#include "hb-utf.hh"
+
+
+/**
+ * SECTION:hb-ot-name
+ * @title: hb-ot-name
+ * @short_description: OpenType font name information
+ * @include: hb-ot.h
+ *
+ * Functions for fetching name strings from OpenType fonts.
+ **/
+
+
+/**
+ * hb_ot_name_list_names:
+ * @face: font face.
+ * @num_entries: (out) (allow-none): number of returned entries.
+ *
+ * Enumerates all available name IDs and language combinations. Returned
+ * array is owned by the @face and should not be modified.  It can be
+ * used as long as @face is alive.
+ *
+ * Returns: (out) (transfer none) (array length=num_entries): Array of available name entries.
+ * Since: 2.1.0
+ **/
+const hb_ot_name_entry_t *
+hb_ot_name_list_names (hb_face_t    *face,
+                       unsigned int *num_entries /* OUT */)
+{
+  const OT::name_accelerator_t &name = *face->table.name;
+  if (num_entries) *num_entries = name.names.length;
+  return (const hb_ot_name_entry_t *) name.names;
+}
+
+
+template <typename in_utf_t, typename out_utf_t>
+static inline unsigned int
+hb_ot_name_convert_utf (hb_bytes_t                       bytes,
+                        unsigned int                    *text_size /* IN/OUT */,
+                        typename out_utf_t::codepoint_t *text /* OUT */)
+{
+  unsigned int src_len = bytes.length / sizeof (typename in_utf_t::codepoint_t);
+  const typename in_utf_t::codepoint_t *src = (const typename in_utf_t::codepoint_t *) bytes.arrayZ;
+  const typename in_utf_t::codepoint_t *src_end = src + src_len;
+
+  typename out_utf_t::codepoint_t *dst = text;
+
+  hb_codepoint_t unicode;
+  const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
+
+  if (text_size && *text_size)
+  {
+    (*text_size)--; /* Same room for NUL-termination. */
+    const typename out_utf_t::codepoint_t *dst_end = text + *text_size;
+
+    while (src < src_end && dst < dst_end)
+    {
+      const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement);
+      typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode);
+      if (dst_next == dst)
+        break; /* Out-of-room. */
+
+      dst = dst_next;
+      src = src_next;
+    };
+
+    *text_size = dst - text;
+    *dst = 0; /* NUL-terminate. */
+  }
+
+  /* Accumulate length of rest. */
+  unsigned int dst_len = dst - text;
+  while (src < src_end)
+  {
+    src = in_utf_t::next (src, src_end, &unicode, replacement);
+    dst_len += out_utf_t::encode_len (unicode);
+  };
+  return dst_len;
+}
+
+template <typename utf_t>
+static inline unsigned int
+hb_ot_name_get_utf (hb_face_t       *face,
+                    hb_ot_name_id_t  name_id,
+                    hb_language_t    language,
+                    unsigned int    *text_size /* IN/OUT */,
+                    typename utf_t::codepoint_t *text /* OUT */)
+{
+  const OT::name_accelerator_t &name = *face->table.name;
+
+  if (!language)
+    language = hb_language_from_string ("en", 2);
+
+  unsigned int width;
+  int idx = name.get_index (name_id, language, &width);
+  if (idx != -1)
+  {
+    hb_bytes_t bytes = name.get_name (idx);
+
+    if (width == 2) /* UTF16-BE */
+      return hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (bytes, text_size, text);
+
+    if (width == 1) /* ASCII */
+      return hb_ot_name_convert_utf<hb_ascii_t, utf_t> (bytes, text_size, text);
+  }
+
+  if (text_size)
+  {
+    if (*text_size)
+      *text = 0;
+    *text_size = 0;
+  }
+  return 0;
+}
+
+/**
+ * hb_ot_name_get_utf8:
+ * @face: font face.
+ * @name_id: OpenType name identifier to fetch.
+ * @language: language to fetch the name for.
+ * @text_size: (inout) (allow-none): input size of @text buffer, and output size of
+ *                                   text written to buffer.
+ * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
+ *
+ * Fetches a font name from the OpenType 'name' table.
+ * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
+ * Returns string in UTF-8 encoding.
+ *
+ * Returns: full length of the requested string, or 0 if not found.
+ * Since: 2.1.0
+ **/
+unsigned int
+hb_ot_name_get_utf8 (hb_face_t       *face,
+                     hb_ot_name_id_t  name_id,
+                     hb_language_t    language,
+                     unsigned int    *text_size /* IN/OUT */,
+                     char            *text      /* OUT */)
+{
+  return hb_ot_name_get_utf<hb_utf8_t> (face, name_id, language, text_size,
+                                        (hb_utf8_t::codepoint_t *) text);
+}
+
+/**
+ * hb_ot_name_get_utf16:
+ * @face: font face.
+ * @name_id: OpenType name identifier to fetch.
+ * @language: language to fetch the name for.
+ * @text_size: (inout) (allow-none): input size of @text buffer, and output size of
+ *                                   text written to buffer.
+ * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
+ *
+ * Fetches a font name from the OpenType 'name' table.
+ * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
+ * Returns string in UTF-16 encoding.
+ *
+ * Returns: full length of the requested string, or 0 if not found.
+ * Since: 2.1.0
+ **/
+unsigned int
+hb_ot_name_get_utf16 (hb_face_t       *face,
+                      hb_ot_name_id_t  name_id,
+                      hb_language_t    language,
+                      unsigned int    *text_size /* IN/OUT */,
+                      uint16_t        *text      /* OUT */)
+{
+  return hb_ot_name_get_utf<hb_utf16_t> (face, name_id, language, text_size, text);
+}
+
+/**
+ * hb_ot_name_get_utf32:
+ * @face: font face.
+ * @name_id: OpenType name identifier to fetch.
+ * @language: language to fetch the name for.
+ * @text_size: (inout) (allow-none): input size of @text buffer, and output size of
+ *                                   text written to buffer.
+ * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
+ *
+ * Fetches a font name from the OpenType 'name' table.
+ * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
+ * Returns string in UTF-32 encoding.
+ *
+ * Returns: full length of the requested string, or 0 if not found.
+ * Since: 2.1.0
+ **/
+unsigned int
+hb_ot_name_get_utf32 (hb_face_t       *face,
+                      hb_ot_name_id_t  name_id,
+                      hb_language_t    language,
+                      unsigned int    *text_size /* IN/OUT */,
+                      uint32_t        *text      /* OUT */)
+{
+  return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name.h	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,129 @@
+/*
+ * 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_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
+#ifndef HB_OT_NAME_H
+#define HB_OT_NAME_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+
+/**
+ * hb_ot_name_id_t:
+ * @HB_OT_NAME_ID_INVALID: Value to represent a nonexistent name ID.
+ *
+ * An integral type representing an OpenType 'name' table name identifier.
+ * There are predefined name IDs, as well as name IDs return from other
+ * API.  These can be used to fetch name strings from a font face.
+ *
+ * Since: 2.0.0
+ **/
+enum
+{
+  HB_OT_NAME_ID_COPYRIGHT               = 0,
+  HB_OT_NAME_ID_FONT_FAMILY             = 1,
+  HB_OT_NAME_ID_FONT_SUBFAMILY          = 2,
+  HB_OT_NAME_ID_UNIQUE_ID               = 3,
+  HB_OT_NAME_ID_FULL_NAME               = 4,
+  HB_OT_NAME_ID_VERSION_STRING          = 5,
+  HB_OT_NAME_ID_POSTSCRIPT_NAME         = 6,
+  HB_OT_NAME_ID_TRADEMARK               = 7,
+  HB_OT_NAME_ID_MANUFACTURER            = 8,
+  HB_OT_NAME_ID_DESIGNER                = 9,
+  HB_OT_NAME_ID_DESCRIPTION             = 10,
+  HB_OT_NAME_ID_VENDOR_URL              = 11,
+  HB_OT_NAME_ID_DESIGNER_URL            = 12,
+  HB_OT_NAME_ID_LICENSE                 = 13,
+  HB_OT_NAME_ID_LICENSE_URL             = 14,
+/*HB_OT_NAME_ID_RESERVED                = 15,*/
+  HB_OT_NAME_ID_TYPOGRAPHIC_FAMILY      = 16,
+  HB_OT_NAME_ID_TYPOGRAPHIC_SUBFAMILY   = 17,
+  HB_OT_NAME_ID_MAC_FULL_NAME           = 18,
+  HB_OT_NAME_ID_SAMPLE_TEXT             = 19,
+  HB_OT_NAME_ID_CID_FINDFONT_NAME       = 20,
+  HB_OT_NAME_ID_WWS_FAMILY              = 21,
+  HB_OT_NAME_ID_WWS_SUBFAMILY           = 22,
+  HB_OT_NAME_ID_LIGHT_BACKGROUND        = 23,
+  HB_OT_NAME_ID_DARK_BACKGROUND         = 24,
+  HB_OT_NAME_ID_VARIATIONS_PS_PREFIX    = 25,
+
+  HB_OT_NAME_ID_INVALID                 = 0xFFFF
+};
+
+typedef unsigned int hb_ot_name_id_t;
+
+
+/**
+ * hb_ot_name_entry_t:
+ * @name_id: name ID
+ * @language: language
+ *
+ * Structure representing a name ID in a particular language.
+ *
+ * Since: 2.1.0
+ **/
+typedef struct hb_ot_name_entry_t
+{
+  hb_ot_name_id_t name_id;
+  /*< private >*/
+  hb_var_int_t    var;
+  /*< public >*/
+  hb_language_t   language;
+} hb_ot_name_entry_t;
+
+HB_EXTERN const hb_ot_name_entry_t *
+hb_ot_name_list_names (hb_face_t    *face,
+                       unsigned int *num_entries /* OUT */);
+
+
+HB_EXTERN unsigned int
+hb_ot_name_get_utf8 (hb_face_t       *face,
+                     hb_ot_name_id_t  name_id,
+                     hb_language_t    language,
+                     unsigned int    *text_size /* IN/OUT */,
+                     char            *text      /* OUT */);
+
+HB_EXTERN unsigned int
+hb_ot_name_get_utf16 (hb_face_t       *face,
+                      hb_ot_name_id_t  name_id,
+                      hb_language_t    language,
+                      unsigned int    *text_size /* IN/OUT */,
+                      uint16_t        *text      /* OUT */);
+
+HB_EXTERN unsigned int
+hb_ot_name_get_utf32 (hb_face_t       *face,
+                      hb_ot_name_id_t  name_id,
+                      hb_language_t    language,
+                      unsigned int    *text_size /* IN/OUT */,
+                      uint32_t        *text      /* OUT */);
+
+
+HB_END_DECLS
+
+#endif /* HB_OT_NAME_H */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-os2-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-os2-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2011,2012  Google, Inc.
+ * Copyright © 2018  Ebrahim Byagowi
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -27,36 +28,131 @@
 #ifndef HB_OT_OS2_TABLE_HH
 #define HB_OT_OS2_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 #include "hb-ot-os2-unicode-ranges.hh"
-#include "hb-subset-plan.hh"
 
-namespace OT {
+#include "hb-set.hh"
 
 /*
  * OS/2 and Windows Metrics
  * https://docs.microsoft.com/en-us/typography/opentype/spec/os2
  */
-#define HB_OT_TAG_os2 HB_TAG('O','S','/','2')
+#define HB_OT_TAG_OS2 HB_TAG('O','S','/','2')
+
 
-struct os2
+namespace OT {
+
+struct OS2V1Tail
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_os2;
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT32      ulCodePageRange1;
+  HBUINT32      ulCodePageRange2;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+struct OS2V2Tail
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBINT16       sxHeight;
+  HBINT16       sCapHeight;
+  HBUINT16      usDefaultChar;
+  HBUINT16      usBreakChar;
+  HBUINT16      usMaxContext;
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+struct OS2V5Tail
+{
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  public:
+  HBUINT16      usLowerOpticalPointSize;
+  HBUINT16      usUpperOpticalPointSize;
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct OS2
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_OS2;
+
+  bool has_data () const { return this != &Null (OS2); }
+
+  const OS2V1Tail &v1 () const { return version >= 1 ? v1X : Null (OS2V1Tail); }
+  const OS2V2Tail &v2 () const { return version >= 2 ? v2X : Null (OS2V2Tail); }
+  const OS2V5Tail &v5 () const { return version >= 5 ? v5X : Null (OS2V5Tail); }
+
+  enum selection_flag_t {
+    ITALIC              = 1u<<0,
+    UNDERSCORE          = 1u<<1,
+    NEGATIVE            = 1u<<2,
+    OUTLINED            = 1u<<3,
+    STRIKEOUT           = 1u<<4,
+    BOLD                = 1u<<5,
+    REGULAR             = 1u<<6,
+    USE_TYPO_METRICS    = 1u<<7,
+    WWS                 = 1u<<8,
+    OBLIQUE             = 1u<<9
+  };
+
+  bool is_italic () const       { return fsSelection & ITALIC; }
+  bool is_oblique () const      { return fsSelection & OBLIQUE; }
+  bool is_typo_metrics () const { return fsSelection & USE_TYPO_METRICS; }
+
+  enum width_class_t {
+    FWIDTH_ULTRA_CONDENSED      = 1, /* 50% */
+    FWIDTH_EXTRA_CONDENSED      = 2, /* 62.5% */
+    FWIDTH_CONDENSED            = 3, /* 75% */
+    FWIDTH_SEMI_CONDENSED       = 4, /* 87.5% */
+    FWIDTH_NORMAL               = 5, /* 100% */
+    FWIDTH_SEMI_EXPANDED        = 6, /* 112.5% */
+    FWIDTH_EXPANDED             = 7, /* 125% */
+    FWIDTH_EXTRA_EXPANDED       = 8, /* 150% */
+    FWIDTH_ULTRA_EXPANDED       = 9  /* 200% */
+  };
+
+  float get_width () const
   {
-    hb_blob_t *os2_blob = OT::Sanitizer<OT::os2>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_os2));
+    switch (usWidthClass) {
+    case FWIDTH_ULTRA_CONDENSED:return 50.f;
+    case FWIDTH_EXTRA_CONDENSED:return 62.5f;
+    case FWIDTH_CONDENSED:      return 75.f;
+    case FWIDTH_SEMI_CONDENSED: return 87.5f;
+    default:
+    case FWIDTH_NORMAL:         return 100.f;
+    case FWIDTH_SEMI_EXPANDED:  return 112.5f;
+    case FWIDTH_EXPANDED:       return 125.f;
+    case FWIDTH_EXTRA_EXPANDED: return 150.f;
+    case FWIDTH_ULTRA_EXPANDED: return 200.f;
+    }
+  }
+
+  bool subset (hb_subset_plan_t *plan) const
+  {
+    hb_blob_t *os2_blob = hb_sanitize_context_t ().reference_table<OS2> (plan->source);
     hb_blob_t *os2_prime_blob = hb_blob_create_sub_blob (os2_blob, 0, -1);
     // TODO(grieger): move to hb_blob_copy_writable_or_fail
     hb_blob_destroy (os2_blob);
 
-    OT::os2 *os2_prime = (OT::os2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
+    OS2 *os2_prime = (OS2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
     if (unlikely (!os2_prime)) {
       hb_blob_destroy (os2_prime_blob);
       return false;
@@ -68,21 +164,21 @@
     os2_prime->usLastCharIndex.set (max_cp);
 
     _update_unicode_ranges (plan->unicodes, os2_prime->ulUnicodeRange);
-    bool result = plan->add_table (HB_OT_TAG_os2, os2_prime_blob);
+    bool result = plan->add_table (HB_OT_TAG_OS2, os2_prime_blob);
 
     hb_blob_destroy (os2_prime_blob);
     return result;
   }
 
-  inline void _update_unicode_ranges (const hb_set_t *codepoints,
-                                      HBUINT32 ulUnicodeRange[4]) const
+  void _update_unicode_ranges (const hb_set_t *codepoints,
+                               HBUINT32 ulUnicodeRange[4]) const
   {
     for (unsigned int i = 0; i < 4; i++)
       ulUnicodeRange[i].set (0);
 
     hb_codepoint_t cp = HB_SET_VALUE_INVALID;
     while (codepoints->next (&cp)) {
-      unsigned int bit = hb_get_unicode_range_bit (cp);
+      unsigned int bit = _hb_ot_os2_get_unicode_range_bit (cp);
       if (bit < 128)
       {
         unsigned int block = bit / 32;
@@ -100,7 +196,7 @@
     }
   }
 
-  static inline void find_min_and_max_codepoint (const hb_set_t *codepoints,
+  static void find_min_and_max_codepoint (const hb_set_t *codepoints,
                                                  uint16_t *min_cp, /* OUT */
                                                  uint16_t *max_cp  /* OUT */)
   {
@@ -119,17 +215,21 @@
   };
 
   // https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681
-  inline font_page_t get_font_page () const
+  font_page_t get_font_page () const
+  { return (font_page_t) (version == 0 ? fsSelection & 0xFF00 : 0); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
-    if (version != 0)
-      return (font_page_t) 0;
-    return (font_page_t) (fsSelection & 0xFF00);
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this))) return_trace (false);
+    if (unlikely (version >= 1 && !v1X.sanitize (c))) return_trace (false);
+    if (unlikely (version >= 2 && !v2X.sanitize (c))) return_trace (false);
+    if (unlikely (version >= 5 && !v5X.sanitize (c))) return_trace (false);
+    return_trace (true);
   }
 
   public:
   HBUINT16      version;
-
-  /* Version 0 */
   HBINT16       xAvgCharWidth;
   HBUINT16      usWeightClass;
   HBUINT16      usWidthClass;
@@ -156,24 +256,11 @@
   HBINT16       sTypoLineGap;
   HBUINT16      usWinAscent;
   HBUINT16      usWinDescent;
-
-  /* Version 1 */
-  //HBUINT32    ulCodePageRange1;
-  //HBUINT32    ulCodePageRange2;
-
-  /* Version 2 */
-  //HBINT16     sxHeight;
-  //HBINT16     sCapHeight;
-  //HBUINT16    usDefaultChar;
-  //HBUINT16    usBreakChar;
-  //HBUINT16    usMaxContext;
-
-  /* Version 5 */
-  //HBUINT16    usLowerOpticalPointSize;
-  //HBUINT16    usUpperOpticalPointSize;
-
+  OS2V1Tail     v1X;
+  OS2V2Tail     v2X;
+  OS2V5Tail     v5X;
   public:
-  DEFINE_SIZE_STATIC (78);
+  DEFINE_SIZE_MIN (78);
 };
 
 } /* namespace OT */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-os2-unicode-ranges.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-os2-unicode-ranges.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,19 +27,33 @@
 #ifndef HB_OT_OS2_UNICODE_RANGES_HH
 #define HB_OT_OS2_UNICODE_RANGES_HH
 
-#include "hb-private.hh"
-#include "hb-dsalgs.hh"
+#include "hb.hh"
 
 namespace OT {
 
-struct Range {
+struct OS2Range
+{
+  static int
+  cmp (const void *_key, const void *_item)
+  {
+    hb_codepoint_t cp = *((hb_codepoint_t *) _key);
+    const OS2Range *range = (OS2Range *) _item;
+
+    if (cp < range->start)
+      return -1;
+    else if (cp <= range->end)
+      return 0;
+    else
+      return +1;
+  }
+
   hb_codepoint_t start;
   hb_codepoint_t end;
   unsigned int bit;
 };
 
-/* Note: The contents of this array was generated using src/gen-unicode-ranges.py. */
-static Range os2UnicodeRangesSorted[] =
+/* Note: The contents of this array was generated using gen-os2-unicode-ranges.py. */
+static const OS2Range _hb_os2_unicode_ranges[] =
 {
   {     0x0,     0x7F,   0}, // Basic Latin
   {    0x80,     0xFF,   1}, // Latin-1 Supplement
@@ -212,31 +226,17 @@
   {0x100000, 0x10FFFD,  90}, // Private Use (plane 16)
 };
 
-static int
-_compare_range (const void *_key, const void *_item, void *_arg)
-{
-  hb_codepoint_t cp = *((hb_codepoint_t *) _key);
-  const Range *range = (Range *) _item;
-
-  if (cp < range->start)
-    return -1;
-  else if (cp <= range->end)
-    return 0;
-  else
-    return 1;
-}
-
 /**
- * hb_get_unicode_range_bit:
- * Returns the bit to be set in os/2 ulUnicodeRange for a given codepoint.
+ * _hb_ot_os2_get_unicode_range_bit:
+ * Returns the bit to be set in os/2 ulUnicodeOS2Range for a given codepoint.
  **/
 static unsigned int
-hb_get_unicode_range_bit (hb_codepoint_t cp)
+_hb_ot_os2_get_unicode_range_bit (hb_codepoint_t cp)
 {
-  Range *range = (Range*) hb_bsearch_r (&cp, os2UnicodeRangesSorted,
-                                        sizeof (os2UnicodeRangesSorted) / sizeof(Range),
-                                        sizeof(Range),
-                                        _compare_range, nullptr);
+  OS2Range *range = (OS2Range*) hb_bsearch (&cp, _hb_os2_unicode_ranges,
+                                            ARRAY_LENGTH (_hb_os2_unicode_ranges),
+                                            sizeof (OS2Range),
+                                            OS2Range::cmp);
   if (range != nullptr)
     return range->bit;
   return -1;
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-post-macroman.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-post-macroman.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,7 +27,7 @@
 #ifndef HB_OT_POST_MACROMAN_HH
 #if 0 /* Make checks happy. */
 #define HB_OT_POST_MACROMAN_HH
-#include "hb-private.hh"
+#include "hb.hh"
 #endif
 
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-post-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-post-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,9 +27,7 @@
 #ifndef HB_OT_POST_TABLE_HH
 #define HB_OT_POST_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-dsalgs.hh"
-#include "hb-subset-plan.hh"
+#include "hb-open-type.hh"
 
 #define HB_STRING_ARRAY_NAME format1_names
 #define HB_STRING_ARRAY_LIST "hb-ot-post-macroman.hh"
@@ -51,47 +49,39 @@
 
 struct postV2Tail
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  friend struct post;
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (glyphNameIndex.sanitize (c));
   }
 
-  ArrayOf<HBUINT16>glyphNameIndex;      /* This is not an offset, but is the
+  protected:
+  ArrayOf<HBUINT16>     glyphNameIndex; /* This is not an offset, but is the
                                          * ordinal number of the glyph in 'post'
                                          * string tables. */
-  HBUINT8               namesX[VAR];            /* Glyph names with length bytes [variable]
+/*UnsizedArrayOf<HBUINT8>
+                        namesX;*/       /* Glyph names with length bytes [variable]
                                          * (a Pascal string). */
 
-  DEFINE_SIZE_ARRAY2 (2, glyphNameIndex, namesX);
+  public:
+  DEFINE_SIZE_ARRAY (2, glyphNameIndex);
 };
 
 struct post
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_post;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_post;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this)))
-      return_trace (false);
-    if (version.to_int () == 0x00020000)
-    {
-      const postV2Tail &v2 = StructAfter<postV2Tail> (*this);
-      return_trace (v2.sanitize (c));
-    }
-    return_trace (true);
-  }
-
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
     unsigned int post_prime_length;
-    hb_blob_t *post_blob = OT::Sanitizer<post>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_post));
-    hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::static_size);
+    hb_blob_t *post_blob = hb_sanitize_context_t ().reference_table<post>(plan->source);
+    hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::min_size);
     post *post_prime = (post *) hb_blob_get_data_writable (post_prime_blob, &post_prime_length);
     hb_blob_destroy (post_blob);
 
-    if (unlikely (!post_prime || post_prime_length != post::static_size))
+    if (unlikely (!post_prime || post_prime_length != post::min_size))
     {
       hb_blob_destroy (post_prime_blob);
       DEBUG_MSG(SUBSET, nullptr, "Invalid source post table with length %d.", post_prime_length);
@@ -107,63 +97,58 @@
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
     {
       index_to_offset.init ();
 
-      blob = Sanitizer<post>().sanitize (face->reference_table (HB_OT_TAG_post));
-      const post *table = blob->as<post> ();
-      unsigned int table_length = blob->length;
+      table = hb_sanitize_context_t ().reference_table<post> (face);
+      unsigned int table_length = table.get_length ();
 
       version = table->version.to_int ();
-      if (version != 0x00020000)
-        return;
+      if (version != 0x00020000) return;
 
-      const postV2Tail &v2 = StructAfter<postV2Tail> (*table);
+      const postV2Tail &v2 = table->v2X;
 
       glyphNameIndex = &v2.glyphNameIndex;
       pool = &StructAfter<uint8_t> (v2.glyphNameIndex);
 
-      const uint8_t *end = (uint8_t *) table + table_length;
-      for (const uint8_t *data = pool; data < end && data + *data <= end; data += 1 + *data)
+      const uint8_t *end = (const uint8_t *) (const void *) table + table_length;
+      for (const uint8_t *data = pool;
+           index_to_offset.length < 65535 && data < end && data + *data < end;
+           data += 1 + *data)
         index_to_offset.push (data - pool);
     }
-    inline void fini (void)
+    void fini ()
     {
       index_to_offset.fini ();
-      free (gids_sorted_by_name);
+      free (gids_sorted_by_name.get ());
+      table.destroy ();
     }
 
-    inline bool get_glyph_name (hb_codepoint_t glyph,
-                                char *buf, unsigned int buf_len) const
+    bool get_glyph_name (hb_codepoint_t glyph,
+                         char *buf, unsigned int buf_len) const
     {
       hb_bytes_t s = find_glyph_name (glyph);
-      if (!s.len)
-        return false;
-      if (!buf_len)
-        return true;
-      if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */
-        return false;
-      strncpy (buf, s.bytes, s.len);
-      buf[s.len] = '\0';
+      if (!s.length) return false;
+      if (!buf_len) return true;
+      unsigned int len = MIN (buf_len - 1, s.length);
+      strncpy (buf, s.arrayZ, len);
+      buf[len] = '\0';
       return true;
     }
 
-    inline bool get_glyph_from_name (const char *name, int len,
-                                     hb_codepoint_t *glyph) const
+    bool get_glyph_from_name (const char *name, int len,
+                              hb_codepoint_t *glyph) const
     {
       unsigned int count = get_glyph_count ();
-      if (unlikely (!count))
-        return false;
+      if (unlikely (!count)) return false;
 
-      if (len < 0)
-        len = strlen (name);
+      if (len < 0) len = strlen (name);
 
-      if (unlikely (!len))
-        return false;
+      if (unlikely (!len)) return false;
 
     retry:
-      uint16_t *gids = (uint16_t *) hb_atomic_ptr_get (&gids_sorted_by_name);
+      uint16_t *gids = gids_sorted_by_name.get ();
 
       if (unlikely (!gids))
       {
@@ -175,14 +160,16 @@
           gids[i] = i;
         hb_sort_r (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
 
-        if (!hb_atomic_ptr_cmpexch (&gids_sorted_by_name, nullptr, gids)) {
+        if (unlikely (!gids_sorted_by_name.cmpexch (nullptr, gids)))
+        {
           free (gids);
           goto retry;
         }
       }
 
       hb_bytes_t st (name, len);
-      const uint16_t *gid = (const uint16_t *) hb_bsearch_r (&st, gids, count, sizeof (gids[0]), cmp_key, (void *) this);
+      const uint16_t *gid = (const uint16_t *) hb_bsearch_r (hb_addressof (st), gids, count,
+                                                             sizeof (gids[0]), cmp_key, (void *) this);
       if (gid)
       {
         *glyph = *gid;
@@ -194,7 +181,7 @@
 
     protected:
 
-    inline unsigned int get_glyph_count (void) const
+    unsigned int get_glyph_count () const
     {
       if (version == 0x00010000)
         return NUM_FORMAT1_NAMES;
@@ -205,7 +192,7 @@
       return 0;
     }
 
-    static inline int cmp_gids (const void *pa, const void *pb, void *arg)
+    static int cmp_gids (const void *pa, const void *pb, void *arg)
     {
       const accelerator_t *thiz = (const accelerator_t *) arg;
       uint16_t a = * (const uint16_t *) pa;
@@ -213,7 +200,7 @@
       return thiz->find_glyph_name (b).cmp (thiz->find_glyph_name (a));
     }
 
-    static inline int cmp_key (const void *pk, const void *po, void *arg)
+    static int cmp_key (const void *pk, const void *po, void *arg)
     {
       const accelerator_t *thiz = (const accelerator_t *) arg;
       const hb_bytes_t *key = (const hb_bytes_t *) pk;
@@ -221,7 +208,7 @@
       return thiz->find_glyph_name (o).cmp (*key);
     }
 
-    inline hb_bytes_t find_glyph_name (hb_codepoint_t glyph) const
+    hb_bytes_t find_glyph_name (hb_codepoint_t glyph) const
     {
       if (version == 0x00010000)
       {
@@ -239,9 +226,9 @@
         return format1_names (index);
       index -= NUM_FORMAT1_NAMES;
 
-      if (index >= index_to_offset.len)
+      if (index >= index_to_offset.length)
         return hb_bytes_t ();
-      unsigned int offset = index_to_offset.arrayZ[index];
+      unsigned int offset = index_to_offset[index];
 
       const uint8_t *data = pool + offset;
       unsigned int name_length = *data;
@@ -251,14 +238,23 @@
     }
 
     private:
-    hb_blob_t *blob;
+    hb_blob_ptr_t<post> table;
     uint32_t version;
     const ArrayOf<HBUINT16> *glyphNameIndex;
-    hb_vector_t<uint32_t, 1> index_to_offset;
+    hb_vector_t<uint32_t> index_to_offset;
     const uint8_t *pool;
-    mutable uint16_t *gids_sorted_by_name;
+    hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
   };
 
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          (version.to_int () == 0x00010000 ||
+                           (version.to_int () == 0x00020000 && v2X.sanitize (c)) ||
+                           version.to_int () == 0x00030000)));
+  }
+
   public:
   FixedVersion<>version;                /* 0x00010000 for version 1.0
                                          * 0x00020000 for version 2.0
@@ -291,10 +287,12 @@
                                          * is downloaded as a Type 1 font. */
   HBUINT32      maxMemType1;            /* Maximum memory usage when an OpenType font
                                          * is downloaded as a Type 1 font. */
-/*postV2Tail    v2[VAR];*/
-  DEFINE_SIZE_STATIC (32);
+  postV2Tail    v2X;
+  DEFINE_SIZE_MIN (32);
 };
 
+struct post_accelerator_t : post::accelerator_t {};
+
 } /* namespace OT */
 
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-fallback.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-fallback.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,9 +27,9 @@
 #ifndef HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
 #define HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-ot-shape-private.hh"
+#include "hb-ot-shape.hh"
 #include "hb-ot-layout-gsub-table.hh"
 
 
@@ -79,18 +79,15 @@
    * May not be good-enough for presidential candidate interviews, but good-enough for us... */
   hb_stable_sort (&glyphs[0], num_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &substitutes[0]);
 
-  OT::Supplier<OT::GlyphID> glyphs_supplier      (glyphs, num_glyphs);
-  OT::Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs);
 
   /* Each glyph takes four bytes max, and there's some overhead. */
   char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128];
-  OT::hb_serialize_context_t c (buf, sizeof (buf));
+  hb_serialize_context_t c (buf, sizeof (buf));
   OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
   bool ret = lookup->serialize_single (&c,
                                        OT::LookupFlag::IgnoreMarks,
-                                       glyphs_supplier,
-                                       substitutes_supplier,
-                                       num_glyphs);
+                                       hb_array (glyphs, num_glyphs),
+                                       hb_array (substitutes, num_glyphs));
   c.end_serialize ();
   /* TODO sanitize the results? */
 
@@ -155,25 +152,18 @@
   if (!num_ligatures)
     return nullptr;
 
-  OT::Supplier<OT::GlyphID>   first_glyphs_supplier                      (first_glyphs, num_first_glyphs);
-  OT::Supplier<unsigned int > ligature_per_first_glyph_count_supplier    (ligature_per_first_glyph_count_list, num_first_glyphs);
-  OT::Supplier<OT::GlyphID>   ligatures_supplier                         (ligature_list, num_ligatures);
-  OT::Supplier<unsigned int > component_count_supplier                   (component_count_list, num_ligatures);
-  OT::Supplier<OT::GlyphID>   component_supplier                         (component_list, num_ligatures);
 
   /* 16 bytes per ligature ought to be enough... */
   char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128];
-  OT::hb_serialize_context_t c (buf, sizeof (buf));
+  hb_serialize_context_t c (buf, sizeof (buf));
   OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
   bool ret = lookup->serialize_ligature (&c,
                                          OT::LookupFlag::IgnoreMarks,
-                                         first_glyphs_supplier,
-                                         ligature_per_first_glyph_count_supplier,
-                                         num_first_glyphs,
-                                         ligatures_supplier,
-                                         component_count_supplier,
-                                         component_supplier);
-
+                                         hb_array (first_glyphs, num_first_glyphs),
+                                         hb_array (ligature_per_first_glyph_count_list, num_first_glyphs),
+                                         hb_array (ligature_list, num_ligatures),
+                                         hb_array (component_count_list, num_ligatures),
+                                         hb_array (component_list, num_ligatures));
   c.end_serialize ();
   /* TODO sanitize the results? */
 
@@ -195,19 +185,15 @@
 
 struct arabic_fallback_plan_t
 {
-  ASSERT_POD ();
-
   unsigned int num_lookups;
   bool free_lookups;
 
   hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS];
   OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS];
-  hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
+  OT::hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
 };
 
-static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
-
-#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256)
+#if defined(_WIN32) && !defined(HB_NO_WIN1256)
 #define HB_WITH_WIN1256
 #endif
 
@@ -215,16 +201,20 @@
 #include "hb-ot-shape-complex-arabic-win1256.hh"
 #endif
 
-struct ManifestLookup {
+struct ManifestLookup
+{
+  public:
   OT::Tag tag;
   OT::OffsetTo<OT::SubstLookup> lookupOffset;
+  public:
+  DEFINE_SIZE_STATIC (6);
 };
 typedef OT::ArrayOf<ManifestLookup> Manifest;
 
 static bool
-arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan,
-                                   const hb_ot_shape_plan_t *plan,
-                                   hb_font_t *font)
+arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUSED,
+                                   const hb_ot_shape_plan_t *plan HB_UNUSED,
+                                   hb_font_t *font HB_UNUSED)
 {
 #ifdef HB_WITH_WIN1256
   /* Does this font look like it's Windows-1256-encoded? */
@@ -299,7 +289,7 @@
 {
   arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t));
   if (unlikely (!fallback_plan))
-    return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
+    return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
 
   fallback_plan->num_lookups = 0;
   fallback_plan->free_lookups = false;
@@ -314,14 +304,15 @@
   if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font))
     return fallback_plan;
 
+  assert (fallback_plan->num_lookups == 0);
   free (fallback_plan);
-  return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
+  return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
 }
 
 static void
 arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
 {
-  if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil)
+  if (!fallback_plan || fallback_plan->num_lookups == 0)
     return;
 
   for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright © 2015  Mozilla Foundation.
- * Copyright © 2015  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.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-struct arabic_shape_plan_t;
-
-HB_INTERNAL void *
-data_create_arabic (const hb_ot_shape_plan_t *plan);
-
-HB_INTERNAL void
-data_destroy_arabic (void *data);
-
-HB_INTERNAL void
-setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
-                         hb_buffer_t               *buffer,
-                         hb_script_t                script);
-
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-win1256.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-win1256.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -313,7 +313,7 @@
  * Include a second time to get the table data...
  */
 #if 0
-#include "hb-private.hh" /* Make check-includes.sh happy. */
+#include "hb.hh" /* Make check-includes.sh happy. */
 #endif
 #ifdef OT_MEASURE
 #include "hb-ot-shape-complex-arabic-win1256.hh"
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,10 +24,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-ot-shape-complex-arabic-private.hh"
-#include "hb-ot-shape-private.hh"
+#include "hb.hh"
+#include "hb-ot-shape-complex-arabic.hh"
+#include "hb-ot-shape.hh"
 
 
 /* buffer var allocations */
@@ -160,11 +159,6 @@
 
 
 static void
-nuke_joiners (const hb_ot_shape_plan_t *plan,
-              hb_font_t *font,
-              hb_buffer_t *buffer);
-
-static void
 arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
                        hb_font_t *font,
                        hb_buffer_t *buffer);
@@ -201,32 +195,38 @@
    * work correctly.  See https://github.com/harfbuzz/harfbuzz/issues/505
    */
 
-  map->add_gsub_pause (nuke_joiners);
 
-  map->add_global_bool_feature (HB_TAG('s','t','c','h'));
+  map->enable_feature (HB_TAG('s','t','c','h'));
   map->add_gsub_pause (record_stch);
 
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
+  map->enable_feature (HB_TAG('l','o','c','l'));
 
   map->add_gsub_pause (nullptr);
 
   for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++)
   {
     bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]);
-    map->add_feature (arabic_features[i], 1, has_fallback ? F_HAS_FALLBACK : F_NONE);
+    map->add_feature (arabic_features[i], has_fallback ? F_HAS_FALLBACK : F_NONE);
     map->add_gsub_pause (nullptr);
   }
 
-  map->add_feature (HB_TAG('r','l','i','g'), 1, F_GLOBAL|F_HAS_FALLBACK);
+  /* Normally, Unicode says a ZWNJ means "don't ligate".  In Arabic script
+   * however, it says a ZWJ should also mean "don't ligate".  So we run
+   * the main ligating features as MANUAL_ZWJ. */
+
+  map->enable_feature (HB_TAG('r','l','i','g'), F_MANUAL_ZWJ | F_HAS_FALLBACK);
+
   if (plan->props.script == HB_SCRIPT_ARABIC)
     map->add_gsub_pause (arabic_fallback_shape);
 
   /* No pause after rclt.  See 98460779bae19e4d64d29461ff154b3527bf8420. */
-  map->add_global_bool_feature (HB_TAG('r','c','l','t'));
-  map->add_global_bool_feature (HB_TAG('c','a','l','t'));
+  map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ);
+  map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ);
   map->add_gsub_pause (nullptr);
 
+  /* And undo here. */
+
   /* The spec includes 'cswh'.  Earlier versions of Windows
    * used to enable this by default, but testing suggests
    * that Windows 8 and later do not enable it by default,
@@ -235,23 +235,21 @@
    * Note that IranNastaliq uses this feature extensively
    * to fixup broken glyph sequences.  Oh well...
    * Test case: U+0643,U+0640,U+0631. */
-  //map->add_global_bool_feature (HB_TAG('c','s','w','h'));
-  map->add_global_bool_feature (HB_TAG('m','s','e','t'));
+  //map->enable_feature (HB_TAG('c','s','w','h'));
+  map->enable_feature (HB_TAG('m','s','e','t'));
 }
 
 #include "hb-ot-shape-complex-arabic-fallback.hh"
 
 struct arabic_shape_plan_t
 {
-  ASSERT_POD ();
-
   /* The "+ 1" in the next array is to accommodate for the "NONE" command,
    * which is not an OpenType feature, but this simplifies the code by not
    * having to do a "if (... < NONE) ..." and just rely on the fact that
    * mask_array[NONE] == 0. */
   hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
 
-  arabic_fallback_plan_t *fallback_plan;
+  hb_atomic_ptr_t<arabic_fallback_plan_t> fallback_plan;
 
   unsigned int do_fallback : 1;
   unsigned int has_stch : 1;
@@ -380,19 +378,6 @@
   setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script);
 }
 
-
-static void
-nuke_joiners (const hb_ot_shape_plan_t *plan HB_UNUSED,
-              hb_font_t *font HB_UNUSED,
-              hb_buffer_t *buffer)
-{
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    if (_hb_glyph_info_is_zwj (&info[i]))
-      _hb_glyph_info_flip_joiners (&info[i]);
-}
-
 static void
 arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
                        hb_font_t *font,
@@ -404,12 +389,13 @@
     return;
 
 retry:
-  arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) hb_atomic_ptr_get (&arabic_plan->fallback_plan);
+  arabic_fallback_plan_t *fallback_plan = arabic_plan->fallback_plan;
   if (unlikely (!fallback_plan))
   {
     /* This sucks.  We need a font to build the fallback plan... */
     fallback_plan = arabic_fallback_plan_create (plan, font);
-    if (unlikely (!hb_atomic_ptr_cmpexch (&(const_cast<arabic_shape_plan_t *> (arabic_plan))->fallback_plan, nullptr, fallback_plan))) {
+    if (unlikely (!arabic_plan->fallback_plan.cmpexch (nullptr, fallback_plan)))
+    {
       arabic_fallback_plan_destroy (fallback_plan);
       goto retry;
     }
@@ -428,7 +414,7 @@
 
 static void
 record_stch (const hb_ot_shape_plan_t *plan,
-             hb_font_t *font,
+             hb_font_t *font HB_UNUSED,
              hb_buffer_t *buffer)
 {
   const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
@@ -452,7 +438,7 @@
 }
 
 static void
-apply_stch (const hb_ot_shape_plan_t *plan,
+apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
             hb_buffer_t              *buffer,
             hb_font_t                *font)
 {
@@ -470,9 +456,9 @@
 
   int sign = font->x_scale < 0 ? -1 : +1;
   unsigned int extra_glyphs_needed = 0; // Set during MEASURE, used during CUT
-  typedef enum { MEASURE, CUT } step_t;
+  enum { MEASURE, CUT } /* step_t */;
 
-  for (step_t step = MEASURE; step <= CUT; step = (step_t) (step + 1))
+  for (unsigned int step = MEASURE; step <= CUT; step = step + 1)
   {
     unsigned int count = buffer->len;
     hb_glyph_info_t *info = buffer->info;
@@ -611,7 +597,7 @@
   HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
 }
 
-/* https://unicode.org/reports/tr53/tr53-1.pdf */
+/* http://www.unicode.org/reports/tr53/ */
 
 static hb_codepoint_t
 modifier_combining_marks[] =
@@ -623,6 +609,7 @@
   0x06E3u, /* ARABIC SMALL LOW SEEN */
   0x06E7u, /* ARABIC SMALL HIGH YEH */
   0x06E8u, /* ARABIC SMALL HIGH NOON */
+  0x08D3u, /* ARABIC SMALL LOW WAW */
   0x08F3u, /* ARABIC SMALL HIGH WAW */
 };
 
@@ -637,7 +624,7 @@
 }
 
 static void
-reorder_marks_arabic (const hb_ot_shape_plan_t *plan,
+reorder_marks_arabic (const hb_ot_shape_plan_t *plan HB_UNUSED,
                       hb_buffer_t              *buffer,
                       unsigned int              start,
                       unsigned int              end)
@@ -714,7 +701,7 @@
   nullptr, /* decompose */
   nullptr, /* compose */
   setup_masks_arabic,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   reorder_marks_arabic,
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2015  Mozilla Foundation.
+ * Copyright © 2015  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.
+ *
+ * Mozilla Author(s): Jonathan Kew
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_HH
+#define HB_OT_SHAPE_COMPLEX_ARABIC_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex.hh"
+
+
+struct arabic_shape_plan_t;
+
+HB_INTERNAL void *
+data_create_arabic (const hb_ot_shape_plan_t *plan);
+
+HB_INTERNAL void
+data_destroy_arabic (void *data);
+
+HB_INTERNAL void
+setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
+                         hb_buffer_t               *buffer,
+                         hb_script_t                script);
+
+#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-default.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-default.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-complex.hh"
 
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
@@ -39,7 +39,7 @@
   nullptr, /* decompose */
   nullptr, /* compose */
   nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-hangul.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-hangul.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-complex.hh"
 
 
 /* Hangul shaper */
@@ -56,7 +56,7 @@
   hb_ot_map_builder_t *map = &plan->map;
 
   for (unsigned int i = FIRST_HANGUL_FEATURE; i < HANGUL_FEATURE_COUNT; i++)
-    map->add_feature (hangul_features[i], 1, F_NONE);
+    map->add_feature (hangul_features[i]);
 }
 
 static void
@@ -65,13 +65,11 @@
   /* Uniscribe does not apply 'calt' for Hangul, and certain fonts
    * (Noto Sans CJK, Source Sans Han, etc) apply all of jamo lookups
    * in calt, which is not desirable. */
-  plan->map.add_feature (HB_TAG('c','a','l','t'), 0, F_GLOBAL);
+  plan->map.disable_feature (HB_TAG('c','a','l','t'));
 }
 
 struct hangul_shape_plan_t
 {
-  ASSERT_POD ();
-
   hb_mask_t mask_array[HANGUL_FEATURE_COUNT];
 };
 
@@ -128,7 +126,7 @@
 }
 
 static void
-preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
+preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
                         hb_buffer_t              *buffer,
                         hb_font_t                *font)
 {
@@ -345,13 +343,6 @@
         {
           unsigned int s_len = tindex ? 3 : 2;
           buffer->replace_glyphs (1, s_len, decomposed);
-          if (unlikely (!buffer->successful))
-            return;
-
-          /* We decomposed S: apply jamo features to the individual glyphs
-           * that are now in buffer->out_info.
-           */
-          hb_glyph_info_t *info = buffer->out_info;
 
           /* If we decomposed an LV because of a non-combining T following,
            * we want to include this T in the syllable.
@@ -361,6 +352,14 @@
             buffer->next_glyph ();
             s_len++;
           }
+
+          if (unlikely (!buffer->successful))
+            return;
+
+          /* We decomposed S: apply jamo features to the individual glyphs
+           * that are now in buffer->out_info.
+           */
+          hb_glyph_info_t *info = buffer->out_info;
           end = start + s_len;
 
           unsigned int i = start;
@@ -368,6 +367,7 @@
           info[i++].hangul_shaping_feature() = VJMO;
           if (i < end)
             info[i++].hangul_shaping_feature() = TJMO;
+
           if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
             buffer->merge_out_clusters (start, end);
           continue;
@@ -424,7 +424,7 @@
   nullptr, /* decompose */
   nullptr, /* compose */
   setup_masks_hangul,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-hebrew.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-hebrew.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-complex.hh"
 
 
 static bool
@@ -70,7 +70,7 @@
 
   bool found = (bool) c->unicode->compose (a, b, ab);
 
-  if (!found && !c->plan->has_mark)
+  if (!found && !c->plan->has_gpos_mark)
   {
       /* Special-case Hebrew presentation forms that are excluded from
        * standard normalization, but wanted for old fonts. */
@@ -154,18 +154,6 @@
   return found;
 }
 
-static bool
-disable_otl_hebrew (const hb_ot_shape_plan_t *plan)
-{
-  /* For Hebrew shaper, use fallback if GPOS does not have 'hebr'
-   * script.  This matches Uniscribe better, and makes fonts like
-   * Arial that have GSUB/GPOS/GDEF but no data for Hebrew work.
-   * See:
-   * https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368
-   */
-  return plan->map.chosen_script[1] != HB_TAG ('h','e','b','r');
-}
-
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
 {
@@ -179,7 +167,7 @@
   nullptr, /* decompose */
   compose_hebrew,
   nullptr, /* setup_masks */
-  disable_otl_hebrew,
+  HB_TAG ('h','e','b','r'), /* gpos_tag. https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368 */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-machine.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-machine.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -29,892 +29,714 @@
 #ifndef HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-ot-shape-complex-indic-machine.hh"
 static const unsigned char _indic_syllable_machine_trans_keys[] = {
-        8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u,
-        5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u,
-        4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u,
-        16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u,
-        4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u,
-        5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u,
-        4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u,
-        16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u,
-        4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 8u,
-        5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u,
-        5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u,
-        16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u,
-        4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u,
-        8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u,
+        8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u,
         5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u,
         4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u,
-        16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u,
-        4u, 13u, 4u, 8u, 4u, 13u, 4u, 13u, 5u, 8u, 5u, 8u, 5u, 7u, 5u, 8u,
-        5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u,
-        8u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u,
-        6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 8u, 8u, 1u, 19u, 3u, 17u,
-        3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u,
-        3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u,
-        3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u,
-        5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u,
-        3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u,
-        3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u,
-        1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u,
-        1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u,
-        3u, 17u, 3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u,
-        4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u,
-        4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u,
-        10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u,
+        16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u,
+        4u, 8u, 4u, 13u, 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u,
+        7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u,
+        6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u,
+        4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u,
+        4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u,
+        5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u,
+        7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u,
+        6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u,
+        4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 8u, 8u, 4u, 8u, 5u, 7u,
+        7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u,
+        5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u,
+        4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u,
+        4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 13u,
+        5u, 8u, 8u, 8u, 1u, 19u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u,
+        3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u,
+        3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u, 5u, 10u,
+        5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u,
+        4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u,
+        3u, 10u, 4u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u,
+        3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u,
+        1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u,
+        3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u,
+        3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u,
+        3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u,
+        10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u,
+        4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 3u, 10u,
+        3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u,
+        1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u,
+        1u, 16u, 1u, 16u, 1u, 16u, 4u, 8u, 3u, 10u, 3u, 10u, 4u, 10u, 1u, 16u,
+        3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u,
+        3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u,
+        5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u,
         3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u,
-        5u, 10u, 3u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u,
-        1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u,
-        3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u,
-        1u, 16u, 1u, 16u, 1u, 16u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u,
-        3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u,
-        3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u,
-        5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u,
-        4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u,
-        3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u,
-        1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u,
-        1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u,
-        3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 13u, 3u, 17u, 4u, 8u,
-        3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u,
-        3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u,
-        3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u,
-        10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u,
+        5u, 10u, 3u, 10u, 4u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u,
+        3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u,
+        1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 13u,
+        3u, 10u, 4u, 8u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u,
+        4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u,
+        4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 5u, 10u,
+        10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u,
         5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u,
-        4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u,
-        3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u,
-        1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u,
-        1u, 16u, 3u, 17u, 1u, 17u, 3u, 17u, 1u, 17u, 4u, 13u, 5u, 10u, 10u, 10u,
-        10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u,
-        4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u,
+        4u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u,
+        1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u,
+        3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 1u, 16u, 3u, 13u,
+        1u, 16u, 4u, 13u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u,
         3u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u,
         0
 };
 
 static const char _indic_syllable_machine_key_spans[] = {
-        1, 4, 3, 1, 4, 3, 1, 4,
-        3, 1, 4, 3, 1, 5, 1, 1,
-        5, 1, 1, 5, 1, 1, 5, 1,
-        1, 5, 10, 5, 10, 5, 10, 5,
-        10, 5, 10, 1, 4, 3, 1, 4,
-        3, 1, 4, 3, 1, 4, 3, 1,
-        5, 1, 1, 5, 1, 1, 5, 1,
-        1, 5, 1, 1, 5, 10, 5, 10,
-        5, 10, 5, 10, 5, 10, 1, 4,
-        3, 1, 4, 3, 1, 4, 3, 1,
-        4, 3, 1, 5, 1, 1, 5, 1,
-        1, 5, 1, 1, 5, 1, 1, 5,
-        10, 5, 10, 5, 10, 5, 10, 5,
-        1, 4, 3, 1, 4, 3, 1, 4,
+        1, 5, 3, 1, 4, 3, 1, 4,
         3, 1, 4, 3, 1, 5, 1, 1,
         5, 1, 1, 5, 1, 1, 5, 1,
-        1, 5, 10, 5, 10, 5, 10, 5,
-        10, 5, 10, 10, 4, 4, 3, 4,
-        3, 1, 4, 3, 1, 4, 3, 1,
+        1, 10, 5, 10, 5, 10, 5, 10,
+        5, 10, 1, 5, 3, 1, 4, 3,
+        1, 4, 3, 1, 4, 3, 1, 5,
+        1, 1, 5, 1, 1, 5, 1, 1,
+        5, 1, 1, 10, 5, 10, 5, 10,
+        5, 10, 5, 10, 1, 5, 3, 1,
+        4, 3, 1, 4, 3, 1, 4, 3,
         1, 5, 1, 1, 5, 1, 1, 5,
-        1, 1, 5, 1, 1, 1, 19, 15,
-        15, 14, 16, 15, 15, 14, 16, 15,
-        15, 14, 16, 15, 15, 14, 16, 15,
-        15, 14, 6, 6, 6, 1, 1, 1,
-        6, 8, 8, 7, 6, 8, 7, 6,
-        8, 7, 6, 8, 7, 6, 8, 7,
-        15, 15, 16, 16, 16, 16, 15, 15,
-        16, 16, 16, 16, 15, 15, 16, 16,
-        16, 16, 15, 15, 16, 16, 16, 16,
-        15, 15, 15, 15, 14, 16, 15, 15,
-        14, 16, 15, 15, 14, 16, 15, 15,
-        14, 16, 15, 15, 14, 6, 6, 6,
-        1, 1, 1, 6, 8, 8, 7, 6,
+        1, 1, 5, 1, 1, 10, 5, 10,
+        5, 10, 5, 10, 5, 1, 5, 3,
+        1, 4, 3, 1, 4, 3, 1, 4,
+        3, 1, 5, 1, 1, 5, 1, 1,
+        5, 1, 1, 5, 1, 1, 10, 5,
+        10, 5, 10, 5, 10, 5, 10, 10,
+        4, 1, 19, 11, 8, 7, 16, 11,
+        8, 7, 16, 11, 8, 7, 16, 11,
+        8, 7, 16, 11, 8, 7, 6, 6,
+        6, 1, 1, 1, 6, 8, 6, 8,
+        7, 6, 8, 7, 6, 8, 7, 6,
+        8, 7, 8, 11, 16, 16, 16, 8,
+        11, 16, 16, 16, 8, 11, 16, 16,
+        16, 8, 11, 16, 16, 16, 8, 11,
+        11, 8, 7, 16, 11, 8, 7, 16,
+        11, 8, 7, 16, 11, 8, 7, 16,
+        11, 8, 7, 6, 6, 6, 1, 1,
+        1, 6, 8, 6, 8, 7, 6, 8,
+        7, 6, 8, 7, 6, 8, 7, 8,
+        11, 16, 16, 16, 8, 11, 16, 16,
+        16, 8, 11, 16, 16, 16, 8, 11,
+        16, 16, 16, 5, 8, 8, 7, 16,
+        11, 8, 7, 16, 11, 8, 7, 16,
+        11, 8, 7, 16, 11, 8, 7, 6,
+        6, 6, 1, 1, 1, 6, 8, 6,
         8, 7, 6, 8, 7, 6, 8, 7,
-        6, 8, 7, 15, 15, 16, 16, 16,
-        16, 15, 15, 16, 16, 16, 16, 15,
-        15, 16, 16, 16, 16, 15, 15, 16,
-        16, 16, 16, 5, 15, 15, 14, 16,
-        15, 15, 14, 16, 15, 15, 14, 16,
-        15, 15, 14, 16, 15, 15, 14, 6,
-        6, 6, 1, 1, 1, 6, 8, 8,
-        7, 6, 8, 7, 6, 8, 7, 6,
-        8, 7, 6, 8, 7, 15, 15, 16,
-        16, 16, 16, 15, 15, 16, 16, 16,
-        16, 15, 15, 16, 16, 16, 16, 15,
-        15, 16, 16, 16, 16, 10, 15, 5,
-        15, 15, 14, 16, 15, 15, 14, 16,
-        15, 15, 14, 16, 15, 15, 14, 16,
-        15, 15, 14, 6, 6, 6, 1, 1,
-        1, 6, 8, 8, 7, 6, 8, 7,
+        6, 8, 7, 8, 11, 16, 16, 16,
+        8, 11, 16, 16, 16, 8, 11, 16,
+        16, 16, 8, 11, 16, 16, 16, 10,
+        8, 5, 11, 8, 7, 16, 11, 8,
+        7, 16, 11, 8, 7, 16, 11, 8,
+        7, 16, 11, 8, 7, 6, 6, 6,
+        1, 1, 1, 6, 8, 6, 8, 7,
         6, 8, 7, 6, 8, 7, 6, 8,
-        7, 15, 15, 16, 16, 16, 16, 15,
-        15, 16, 16, 16, 16, 15, 15, 16,
-        16, 16, 16, 15, 15, 16, 16, 16,
-        16, 15, 17, 15, 17, 10, 6, 1,
-        1, 1, 6, 16, 8, 7, 6, 8,
-        7, 6, 8, 7, 6, 8, 7, 6,
+        7, 8, 11, 16, 16, 16, 8, 11,
+        16, 16, 16, 8, 11, 16, 16, 16,
+        8, 11, 16, 16, 16, 8, 16, 11,
+        16, 10, 6, 1, 1, 1, 6, 16,
         8, 6, 6, 1, 1, 1, 6, 16
 };
 
 static const short _indic_syllable_machine_index_offsets[] = {
-        0, 2, 7, 11, 13, 18, 22, 24,
-        29, 33, 35, 40, 44, 46, 52, 54,
-        56, 62, 64, 66, 72, 74, 76, 82,
-        84, 86, 92, 103, 109, 120, 126, 137,
-        143, 154, 160, 171, 173, 178, 182, 184,
-        189, 193, 195, 200, 204, 206, 211, 215,
-        217, 223, 225, 227, 233, 235, 237, 243,
-        245, 247, 253, 255, 257, 263, 274, 280,
-        291, 297, 308, 314, 325, 331, 342, 344,
-        349, 353, 355, 360, 364, 366, 371, 375,
-        377, 382, 386, 388, 394, 396, 398, 404,
-        406, 408, 414, 416, 418, 424, 426, 428,
-        434, 445, 451, 462, 468, 479, 485, 496,
-        502, 504, 509, 513, 515, 520, 524, 526,
-        531, 535, 537, 542, 546, 548, 554, 556,
-        558, 564, 566, 568, 574, 576, 578, 584,
-        586, 588, 594, 605, 611, 622, 628, 639,
-        645, 656, 662, 673, 684, 689, 694, 698,
-        703, 707, 709, 714, 718, 720, 725, 729,
-        731, 733, 739, 741, 743, 749, 751, 753,
-        759, 761, 763, 769, 771, 773, 775, 795,
-        811, 827, 842, 859, 875, 891, 906, 923,
-        939, 955, 970, 987, 1003, 1019, 1034, 1051,
-        1067, 1083, 1098, 1105, 1112, 1119, 1121, 1123,
-        1125, 1132, 1141, 1150, 1158, 1165, 1174, 1182,
-        1189, 1198, 1206, 1213, 1222, 1230, 1237, 1246,
-        1254, 1270, 1286, 1303, 1320, 1337, 1354, 1370,
-        1386, 1403, 1420, 1437, 1454, 1470, 1486, 1503,
-        1520, 1537, 1554, 1570, 1586, 1603, 1620, 1637,
-        1654, 1670, 1686, 1702, 1718, 1733, 1750, 1766,
-        1782, 1797, 1814, 1830, 1846, 1861, 1878, 1894,
-        1910, 1925, 1942, 1958, 1974, 1989, 1996, 2003,
-        2010, 2012, 2014, 2016, 2023, 2032, 2041, 2049,
-        2056, 2065, 2073, 2080, 2089, 2097, 2104, 2113,
-        2121, 2128, 2137, 2145, 2161, 2177, 2194, 2211,
-        2228, 2245, 2261, 2277, 2294, 2311, 2328, 2345,
-        2361, 2377, 2394, 2411, 2428, 2445, 2461, 2477,
-        2494, 2511, 2528, 2545, 2551, 2567, 2583, 2598,
-        2615, 2631, 2647, 2662, 2679, 2695, 2711, 2726,
-        2743, 2759, 2775, 2790, 2807, 2823, 2839, 2854,
-        2861, 2868, 2875, 2877, 2879, 2881, 2888, 2897,
-        2906, 2914, 2921, 2930, 2938, 2945, 2954, 2962,
-        2969, 2978, 2986, 2993, 3002, 3010, 3026, 3042,
-        3059, 3076, 3093, 3110, 3126, 3142, 3159, 3176,
-        3193, 3210, 3226, 3242, 3259, 3276, 3293, 3310,
-        3326, 3342, 3359, 3376, 3393, 3410, 3421, 3437,
-        3443, 3459, 3475, 3490, 3507, 3523, 3539, 3554,
-        3571, 3587, 3603, 3618, 3635, 3651, 3667, 3682,
-        3699, 3715, 3731, 3746, 3753, 3760, 3767, 3769,
-        3771, 3773, 3780, 3789, 3798, 3806, 3813, 3822,
-        3830, 3837, 3846, 3854, 3861, 3870, 3878, 3885,
-        3894, 3902, 3918, 3934, 3951, 3968, 3985, 4002,
-        4018, 4034, 4051, 4068, 4085, 4102, 4118, 4134,
-        4151, 4168, 4185, 4202, 4218, 4234, 4251, 4268,
-        4285, 4302, 4318, 4336, 4352, 4370, 4381, 4388,
-        4390, 4392, 4394, 4401, 4418, 4427, 4435, 4442,
-        4451, 4459, 4466, 4475, 4483, 4490, 4499, 4507,
-        4514, 4523, 4530, 4537, 4539, 4541, 4543, 4550
+        0, 2, 8, 12, 14, 19, 23, 25,
+        30, 34, 36, 41, 45, 47, 53, 55,
+        57, 63, 65, 67, 73, 75, 77, 83,
+        85, 87, 98, 104, 115, 121, 132, 138,
+        149, 155, 166, 168, 174, 178, 180, 185,
+        189, 191, 196, 200, 202, 207, 211, 213,
+        219, 221, 223, 229, 231, 233, 239, 241,
+        243, 249, 251, 253, 264, 270, 281, 287,
+        298, 304, 315, 321, 332, 334, 340, 344,
+        346, 351, 355, 357, 362, 366, 368, 373,
+        377, 379, 385, 387, 389, 395, 397, 399,
+        405, 407, 409, 415, 417, 419, 430, 436,
+        447, 453, 464, 470, 481, 487, 489, 495,
+        499, 501, 506, 510, 512, 517, 521, 523,
+        528, 532, 534, 540, 542, 544, 550, 552,
+        554, 560, 562, 564, 570, 572, 574, 585,
+        591, 602, 608, 619, 625, 636, 642, 653,
+        664, 669, 671, 691, 703, 712, 720, 737,
+        749, 758, 766, 783, 795, 804, 812, 829,
+        841, 850, 858, 875, 887, 896, 904, 911,
+        918, 925, 927, 929, 931, 938, 947, 954,
+        963, 971, 978, 987, 995, 1002, 1011, 1019,
+        1026, 1035, 1043, 1052, 1064, 1081, 1098, 1115,
+        1124, 1136, 1153, 1170, 1187, 1196, 1208, 1225,
+        1242, 1259, 1268, 1280, 1297, 1314, 1331, 1340,
+        1352, 1364, 1373, 1381, 1398, 1410, 1419, 1427,
+        1444, 1456, 1465, 1473, 1490, 1502, 1511, 1519,
+        1536, 1548, 1557, 1565, 1572, 1579, 1586, 1588,
+        1590, 1592, 1599, 1608, 1615, 1624, 1632, 1639,
+        1648, 1656, 1663, 1672, 1680, 1687, 1696, 1704,
+        1713, 1725, 1742, 1759, 1776, 1785, 1797, 1814,
+        1831, 1848, 1857, 1869, 1886, 1903, 1920, 1929,
+        1941, 1958, 1975, 1992, 1998, 2007, 2016, 2024,
+        2041, 2053, 2062, 2070, 2087, 2099, 2108, 2116,
+        2133, 2145, 2154, 2162, 2179, 2191, 2200, 2208,
+        2215, 2222, 2229, 2231, 2233, 2235, 2242, 2251,
+        2258, 2267, 2275, 2282, 2291, 2299, 2306, 2315,
+        2323, 2330, 2339, 2347, 2356, 2368, 2385, 2402,
+        2419, 2428, 2440, 2457, 2474, 2491, 2500, 2512,
+        2529, 2546, 2563, 2572, 2584, 2601, 2618, 2635,
+        2646, 2655, 2661, 2673, 2682, 2690, 2707, 2719,
+        2728, 2736, 2753, 2765, 2774, 2782, 2799, 2811,
+        2820, 2828, 2845, 2857, 2866, 2874, 2881, 2888,
+        2895, 2897, 2899, 2901, 2908, 2917, 2924, 2933,
+        2941, 2948, 2957, 2965, 2972, 2981, 2989, 2996,
+        3005, 3013, 3022, 3034, 3051, 3068, 3085, 3094,
+        3106, 3123, 3140, 3157, 3166, 3178, 3195, 3212,
+        3229, 3238, 3250, 3267, 3284, 3301, 3310, 3327,
+        3339, 3356, 3367, 3374, 3376, 3378, 3380, 3387,
+        3404, 3413, 3420, 3427, 3429, 3431, 3433, 3440
 };
 
 static const short _indic_syllable_machine_indicies[] = {
-        1, 0, 2, 2, 3, 1, 0, 4,
-        4, 3, 0, 3, 0, 5, 5, 6,
-        1, 0, 7, 7, 6, 0, 6, 0,
-        8, 8, 9, 1, 0, 10, 10, 9,
-        0, 9, 0, 11, 11, 12, 1, 0,
-        13, 13, 12, 0, 12, 0, 14, 0,
-        0, 0, 1, 0, 15, 0, 16, 0,
-        17, 11, 11, 12, 1, 0, 18, 0,
-        19, 0, 20, 8, 8, 9, 1, 0,
-        21, 0, 22, 0, 23, 5, 5, 6,
-        1, 0, 24, 0, 25, 0, 26, 2,
-        2, 3, 1, 0, 26, 2, 2, 3,
-        1, 0, 0, 0, 0, 27, 0, 28,
-        2, 2, 3, 1, 0, 28, 2, 2,
-        3, 1, 0, 0, 0, 0, 29, 0,
-        30, 2, 2, 3, 1, 0, 30, 2,
-        2, 3, 1, 0, 0, 0, 0, 31,
-        0, 32, 2, 2, 3, 1, 0, 32,
-        2, 2, 3, 1, 0, 0, 0, 0,
-        33, 0, 34, 2, 2, 3, 1, 0,
-        34, 2, 2, 3, 1, 0, 0, 0,
-        0, 35, 0, 37, 36, 38, 38, 39,
-        37, 36, 40, 40, 39, 36, 39, 36,
-        41, 41, 42, 37, 36, 43, 43, 42,
-        36, 42, 36, 44, 44, 45, 37, 36,
-        46, 46, 45, 36, 45, 36, 47, 47,
-        48, 37, 36, 49, 49, 48, 36, 48,
-        36, 50, 36, 36, 36, 37, 36, 51,
-        36, 52, 36, 53, 47, 47, 48, 37,
-        36, 54, 36, 55, 36, 56, 44, 44,
-        45, 37, 36, 57, 36, 58, 36, 59,
-        41, 41, 42, 37, 36, 60, 36, 61,
-        36, 62, 38, 38, 39, 37, 36, 62,
-        38, 38, 39, 37, 36, 36, 36, 36,
-        63, 36, 64, 38, 38, 39, 37, 36,
-        64, 38, 38, 39, 37, 36, 36, 36,
-        36, 65, 36, 66, 38, 38, 39, 37,
-        36, 66, 38, 38, 39, 37, 36, 36,
-        36, 36, 67, 36, 68, 38, 38, 39,
-        37, 36, 68, 38, 38, 39, 37, 36,
-        36, 36, 36, 69, 36, 70, 38, 38,
-        39, 37, 36, 70, 38, 38, 39, 37,
-        36, 36, 36, 36, 71, 36, 73, 72,
-        74, 74, 75, 73, 72, 77, 77, 75,
-        76, 75, 76, 78, 78, 79, 73, 72,
-        80, 80, 79, 72, 79, 72, 81, 81,
-        82, 73, 72, 83, 83, 82, 72, 82,
-        72, 84, 84, 85, 73, 72, 86, 86,
-        85, 72, 85, 72, 87, 72, 72, 72,
-        73, 72, 88, 72, 89, 72, 90, 84,
-        84, 85, 73, 72, 91, 72, 92, 72,
-        93, 81, 81, 82, 73, 72, 94, 72,
-        95, 72, 96, 78, 78, 79, 73, 72,
-        97, 72, 98, 72, 99, 74, 74, 75,
-        73, 72, 99, 74, 74, 75, 73, 72,
-        72, 72, 72, 100, 72, 101, 74, 74,
-        75, 73, 72, 101, 74, 74, 75, 73,
-        72, 72, 72, 72, 102, 72, 103, 74,
-        74, 75, 73, 72, 103, 74, 74, 75,
-        73, 72, 72, 72, 72, 104, 72, 105,
-        74, 74, 75, 73, 72, 105, 74, 74,
-        75, 73, 72, 72, 72, 72, 106, 72,
-        107, 74, 74, 75, 73, 72, 109, 108,
-        110, 110, 111, 109, 108, 112, 112, 111,
-        108, 111, 108, 113, 113, 114, 109, 108,
-        115, 115, 114, 108, 114, 108, 116, 116,
-        117, 109, 108, 118, 118, 117, 108, 117,
-        108, 119, 119, 120, 109, 108, 121, 121,
-        120, 108, 120, 108, 122, 108, 108, 108,
-        109, 108, 123, 108, 124, 108, 125, 119,
-        119, 120, 109, 108, 126, 108, 127, 108,
-        128, 116, 116, 117, 109, 108, 129, 108,
-        130, 108, 131, 113, 113, 114, 109, 108,
-        132, 108, 133, 108, 134, 110, 110, 111,
-        109, 108, 134, 110, 110, 111, 109, 108,
-        108, 108, 108, 135, 108, 136, 110, 110,
-        111, 109, 108, 136, 110, 110, 111, 109,
-        108, 108, 108, 108, 137, 108, 138, 110,
-        110, 111, 109, 108, 138, 110, 110, 111,
-        109, 108, 108, 108, 108, 139, 108, 140,
-        110, 110, 111, 109, 108, 140, 110, 110,
-        111, 109, 108, 108, 108, 108, 141, 108,
-        142, 110, 110, 111, 109, 108, 142, 110,
-        110, 111, 109, 108, 108, 108, 108, 143,
-        108, 107, 74, 74, 75, 73, 72, 72,
-        72, 72, 144, 72, 77, 77, 75, 1,
-        0, 145, 145, 146, 1, 0, 4, 4,
-        146, 0, 147, 147, 148, 149, 0, 150,
-        150, 148, 0, 148, 0, 151, 151, 152,
-        149, 0, 153, 153, 152, 0, 152, 0,
-        154, 154, 155, 149, 0, 156, 156, 155,
-        0, 155, 0, 149, 0, 157, 0, 0,
-        0, 149, 0, 158, 0, 159, 0, 160,
-        154, 154, 155, 149, 0, 161, 0, 162,
-        0, 163, 151, 151, 152, 149, 0, 164,
-        0, 165, 0, 166, 147, 147, 148, 149,
-        0, 167, 0, 168, 0, 170, 169, 172,
-        173, 174, 175, 176, 177, 75, 73, 171,
-        178, 179, 179, 144, 171, 180, 181, 182,
-        183, 184, 171, 186, 187, 188, 189, 3,
-        1, 185, 190, 185, 185, 35, 185, 185,
-        185, 191, 185, 192, 187, 193, 193, 3,
-        1, 185, 190, 185, 185, 185, 185, 185,
-        185, 191, 185, 187, 193, 193, 3, 1,
-        185, 190, 185, 185, 185, 185, 185, 185,
-        191, 185, 194, 185, 185, 185, 16, 195,
-        185, 1, 185, 190, 185, 185, 185, 185,
-        185, 194, 185, 196, 197, 198, 199, 3,
-        1, 185, 190, 185, 185, 33, 185, 185,
-        185, 191, 185, 200, 197, 201, 201, 3,
-        1, 185, 190, 185, 185, 185, 185, 185,
-        185, 191, 185, 197, 201, 201, 3, 1,
-        185, 190, 185, 185, 185, 185, 185, 185,
-        191, 185, 202, 185, 185, 185, 16, 203,
-        185, 1, 185, 190, 185, 185, 185, 185,
-        185, 202, 185, 204, 205, 206, 207, 3,
-        1, 185, 190, 185, 185, 31, 185, 185,
-        185, 191, 185, 208, 205, 209, 209, 3,
-        1, 185, 190, 185, 185, 185, 185, 185,
-        185, 191, 185, 205, 209, 209, 3, 1,
-        185, 190, 185, 185, 185, 185, 185, 185,
-        191, 185, 210, 185, 185, 185, 16, 211,
-        185, 1, 185, 190, 185, 185, 185, 185,
-        185, 210, 185, 212, 213, 214, 215, 3,
-        1, 185, 190, 185, 185, 29, 185, 185,
-        185, 191, 185, 216, 213, 217, 217, 3,
-        1, 185, 190, 185, 185, 185, 185, 185,
-        185, 191, 185, 213, 217, 217, 3, 1,
-        185, 190, 185, 185, 185, 185, 185, 185,
-        191, 185, 218, 185, 185, 185, 16, 219,
-        185, 1, 185, 190, 185, 185, 185, 185,
-        185, 218, 185, 220, 221, 222, 223, 3,
-        1, 185, 190, 185, 185, 27, 185, 185,
-        185, 191, 185, 224, 221, 225, 225, 3,
-        1, 185, 190, 185, 185, 185, 185, 185,
-        185, 191, 185, 221, 225, 225, 3, 1,
-        185, 190, 185, 185, 185, 185, 185, 185,
-        191, 185, 16, 226, 185, 1, 185, 190,
-        185, 227, 227, 185, 1, 185, 190, 185,
-        228, 185, 185, 229, 185, 190, 185, 190,
-        185, 230, 185, 231, 185, 228, 185, 185,
-        185, 185, 190, 185, 16, 185, 232, 232,
-        3, 1, 185, 190, 185, 233, 25, 234,
-        235, 6, 1, 185, 190, 185, 25, 234,
-        235, 6, 1, 185, 190, 185, 234, 234,
-        6, 1, 185, 190, 185, 236, 22, 237,
-        238, 9, 1, 185, 190, 185, 22, 237,
-        238, 9, 1, 185, 190, 185, 237, 237,
-        9, 1, 185, 190, 185, 239, 19, 240,
-        241, 12, 1, 185, 190, 185, 19, 240,
-        241, 12, 1, 185, 190, 185, 240, 240,
-        12, 1, 185, 190, 185, 242, 16, 227,
-        243, 185, 1, 185, 190, 185, 16, 227,
-        243, 185, 1, 185, 190, 185, 227, 244,
-        185, 1, 185, 190, 185, 16, 185, 227,
-        227, 185, 1, 185, 190, 185, 221, 225,
-        225, 3, 1, 185, 190, 185, 220, 221,
-        225, 225, 3, 1, 185, 190, 185, 185,
-        185, 185, 185, 185, 191, 185, 220, 221,
-        222, 225, 3, 1, 185, 190, 185, 185,
-        27, 185, 185, 185, 191, 185, 218, 185,
-        245, 185, 232, 232, 3, 1, 185, 190,
-        185, 185, 185, 185, 185, 218, 185, 218,
-        185, 185, 185, 227, 227, 185, 1, 185,
-        190, 185, 185, 185, 185, 185, 218, 185,
-        218, 185, 185, 185, 227, 246, 185, 1,
-        185, 190, 185, 185, 185, 185, 185, 218,
-        185, 218, 185, 245, 185, 227, 227, 185,
-        1, 185, 190, 185, 185, 185, 185, 185,
-        218, 185, 212, 213, 217, 217, 3, 1,
-        185, 190, 185, 185, 185, 185, 185, 185,
-        191, 185, 212, 213, 214, 217, 3, 1,
-        185, 190, 185, 185, 29, 185, 185, 185,
-        191, 185, 210, 185, 247, 185, 232, 232,
-        3, 1, 185, 190, 185, 185, 185, 185,
-        185, 210, 185, 210, 185, 185, 185, 227,
-        227, 185, 1, 185, 190, 185, 185, 185,
-        185, 185, 210, 185, 210, 185, 185, 185,
-        227, 248, 185, 1, 185, 190, 185, 185,
-        185, 185, 185, 210, 185, 210, 185, 247,
-        185, 227, 227, 185, 1, 185, 190, 185,
-        185, 185, 185, 185, 210, 185, 204, 205,
-        209, 209, 3, 1, 185, 190, 185, 185,
-        185, 185, 185, 185, 191, 185, 204, 205,
-        206, 209, 3, 1, 185, 190, 185, 185,
-        31, 185, 185, 185, 191, 185, 202, 185,
-        249, 185, 232, 232, 3, 1, 185, 190,
-        185, 185, 185, 185, 185, 202, 185, 202,
-        185, 185, 185, 227, 227, 185, 1, 185,
-        190, 185, 185, 185, 185, 185, 202, 185,
-        202, 185, 185, 185, 227, 250, 185, 1,
-        185, 190, 185, 185, 185, 185, 185, 202,
-        185, 202, 185, 249, 185, 227, 227, 185,
-        1, 185, 190, 185, 185, 185, 185, 185,
-        202, 185, 196, 197, 201, 201, 3, 1,
-        185, 190, 185, 185, 185, 185, 185, 185,
-        191, 185, 196, 197, 198, 201, 3, 1,
-        185, 190, 185, 185, 33, 185, 185, 185,
-        191, 185, 194, 185, 251, 185, 232, 232,
-        3, 1, 185, 190, 185, 185, 185, 185,
-        185, 194, 185, 194, 185, 185, 185, 227,
-        227, 185, 1, 185, 190, 185, 185, 185,
-        185, 185, 194, 185, 194, 185, 185, 185,
-        227, 252, 185, 1, 185, 190, 185, 185,
-        185, 185, 185, 194, 185, 194, 185, 251,
-        185, 227, 227, 185, 1, 185, 190, 185,
-        185, 185, 185, 185, 194, 185, 186, 187,
-        193, 193, 3, 1, 185, 190, 185, 185,
-        185, 185, 185, 185, 191, 185, 186, 187,
-        188, 193, 3, 1, 185, 190, 185, 185,
-        35, 185, 185, 185, 191, 185, 254, 255,
-        256, 257, 39, 37, 253, 258, 253, 253,
-        71, 253, 253, 253, 259, 253, 260, 255,
-        261, 257, 39, 37, 253, 258, 253, 253,
-        253, 253, 253, 253, 259, 253, 255, 261,
-        257, 39, 37, 253, 258, 253, 253, 253,
-        253, 253, 253, 259, 253, 262, 253, 253,
-        253, 52, 263, 253, 37, 253, 258, 253,
-        253, 253, 253, 253, 262, 253, 264, 265,
-        266, 267, 39, 37, 253, 258, 253, 253,
-        69, 253, 253, 253, 259, 253, 268, 265,
-        269, 269, 39, 37, 253, 258, 253, 253,
-        253, 253, 253, 253, 259, 253, 265, 269,
-        269, 39, 37, 253, 258, 253, 253, 253,
-        253, 253, 253, 259, 253, 270, 253, 253,
-        253, 52, 271, 253, 37, 253, 258, 253,
-        253, 253, 253, 253, 270, 253, 272, 273,
-        274, 275, 39, 37, 253, 258, 253, 253,
-        67, 253, 253, 253, 259, 253, 276, 273,
-        277, 277, 39, 37, 253, 258, 253, 253,
-        253, 253, 253, 253, 259, 253, 273, 277,
-        277, 39, 37, 253, 258, 253, 253, 253,
-        253, 253, 253, 259, 253, 278, 253, 253,
-        253, 52, 279, 253, 37, 253, 258, 253,
-        253, 253, 253, 253, 278, 253, 280, 281,
-        282, 283, 39, 37, 253, 258, 253, 253,
-        65, 253, 253, 253, 259, 253, 284, 281,
-        285, 285, 39, 37, 253, 258, 253, 253,
-        253, 253, 253, 253, 259, 253, 281, 285,
-        285, 39, 37, 253, 258, 253, 253, 253,
-        253, 253, 253, 259, 253, 286, 253, 253,
-        253, 52, 287, 253, 37, 253, 258, 253,
-        253, 253, 253, 253, 286, 253, 288, 289,
-        290, 291, 39, 37, 253, 258, 253, 253,
-        63, 253, 253, 253, 259, 253, 292, 289,
-        293, 293, 39, 37, 253, 258, 253, 253,
-        253, 253, 253, 253, 259, 253, 289, 293,
-        293, 39, 37, 253, 258, 253, 253, 253,
-        253, 253, 253, 259, 253, 52, 294, 253,
-        37, 253, 258, 253, 295, 295, 253, 37,
-        253, 258, 253, 296, 253, 253, 297, 253,
-        258, 253, 258, 253, 298, 253, 299, 253,
-        296, 253, 253, 253, 253, 258, 253, 52,
-        253, 300, 300, 39, 37, 253, 258, 253,
-        301, 61, 302, 303, 42, 37, 253, 258,
-        253, 61, 302, 303, 42, 37, 253, 258,
-        253, 302, 302, 42, 37, 253, 258, 253,
-        304, 58, 305, 306, 45, 37, 253, 258,
-        253, 58, 305, 306, 45, 37, 253, 258,
-        253, 305, 305, 45, 37, 253, 258, 253,
-        307, 55, 308, 309, 48, 37, 253, 258,
-        253, 55, 308, 309, 48, 37, 253, 258,
-        253, 308, 308, 48, 37, 253, 258, 253,
-        310, 52, 295, 311, 253, 37, 253, 258,
-        253, 52, 295, 311, 253, 37, 253, 258,
-        253, 295, 312, 253, 37, 253, 258, 253,
-        52, 253, 295, 295, 253, 37, 253, 258,
-        253, 289, 293, 293, 39, 37, 253, 258,
-        253, 288, 289, 293, 293, 39, 37, 253,
-        258, 253, 253, 253, 253, 253, 253, 259,
-        253, 288, 289, 290, 293, 39, 37, 253,
-        258, 253, 253, 63, 253, 253, 253, 259,
-        253, 286, 253, 313, 253, 300, 300, 39,
-        37, 253, 258, 253, 253, 253, 253, 253,
-        286, 253, 286, 253, 253, 253, 295, 295,
-        253, 37, 253, 258, 253, 253, 253, 253,
-        253, 286, 253, 286, 253, 253, 253, 295,
-        314, 253, 37, 253, 258, 253, 253, 253,
-        253, 253, 286, 253, 286, 253, 313, 253,
-        295, 295, 253, 37, 253, 258, 253, 253,
-        253, 253, 253, 286, 253, 280, 281, 285,
-        285, 39, 37, 253, 258, 253, 253, 253,
-        253, 253, 253, 259, 253, 280, 281, 282,
-        285, 39, 37, 253, 258, 253, 253, 65,
-        253, 253, 253, 259, 253, 278, 253, 315,
-        253, 300, 300, 39, 37, 253, 258, 253,
-        253, 253, 253, 253, 278, 253, 278, 253,
-        253, 253, 295, 295, 253, 37, 253, 258,
-        253, 253, 253, 253, 253, 278, 253, 278,
-        253, 253, 253, 295, 316, 253, 37, 253,
-        258, 253, 253, 253, 253, 253, 278, 253,
-        278, 253, 315, 253, 295, 295, 253, 37,
-        253, 258, 253, 253, 253, 253, 253, 278,
-        253, 272, 273, 277, 277, 39, 37, 253,
-        258, 253, 253, 253, 253, 253, 253, 259,
-        253, 272, 273, 274, 277, 39, 37, 253,
-        258, 253, 253, 67, 253, 253, 253, 259,
-        253, 270, 253, 317, 253, 300, 300, 39,
-        37, 253, 258, 253, 253, 253, 253, 253,
-        270, 253, 270, 253, 253, 253, 295, 295,
-        253, 37, 253, 258, 253, 253, 253, 253,
-        253, 270, 253, 270, 253, 253, 253, 295,
-        318, 253, 37, 253, 258, 253, 253, 253,
-        253, 253, 270, 253, 270, 253, 317, 253,
-        295, 295, 253, 37, 253, 258, 253, 253,
-        253, 253, 253, 270, 253, 264, 265, 269,
-        269, 39, 37, 253, 258, 253, 253, 253,
-        253, 253, 253, 259, 253, 264, 265, 266,
-        269, 39, 37, 253, 258, 253, 253, 69,
-        253, 253, 253, 259, 253, 262, 253, 319,
-        253, 300, 300, 39, 37, 253, 258, 253,
-        253, 253, 253, 253, 262, 253, 262, 253,
-        253, 253, 295, 295, 253, 37, 253, 258,
-        253, 253, 253, 253, 253, 262, 253, 262,
-        253, 253, 253, 295, 320, 253, 37, 253,
-        258, 253, 253, 253, 253, 253, 262, 253,
-        262, 253, 319, 253, 295, 295, 253, 37,
-        253, 258, 253, 253, 253, 253, 253, 262,
-        253, 70, 38, 38, 39, 37, 253, 254,
-        255, 261, 257, 39, 37, 253, 258, 253,
-        253, 253, 253, 253, 253, 259, 253, 322,
-        175, 323, 323, 75, 73, 321, 178, 321,
-        321, 321, 321, 321, 321, 182, 321, 175,
-        323, 323, 75, 73, 321, 178, 321, 321,
-        321, 321, 321, 321, 182, 321, 324, 321,
-        321, 321, 89, 325, 321, 73, 321, 178,
-        321, 321, 321, 321, 321, 324, 321, 326,
-        327, 328, 329, 75, 73, 321, 178, 321,
-        321, 106, 321, 321, 321, 182, 321, 330,
-        327, 331, 331, 75, 73, 321, 178, 321,
-        321, 321, 321, 321, 321, 182, 321, 327,
-        331, 331, 75, 73, 321, 178, 321, 321,
-        321, 321, 321, 321, 182, 321, 332, 321,
-        321, 321, 89, 333, 321, 73, 321, 178,
-        321, 321, 321, 321, 321, 332, 321, 334,
-        335, 336, 337, 75, 73, 321, 178, 321,
-        321, 104, 321, 321, 321, 182, 321, 338,
-        335, 339, 339, 75, 73, 321, 178, 321,
-        321, 321, 321, 321, 321, 182, 321, 335,
-        339, 339, 75, 73, 321, 178, 321, 321,
-        321, 321, 321, 321, 182, 321, 340, 321,
-        321, 321, 89, 341, 321, 73, 321, 178,
-        321, 321, 321, 321, 321, 340, 321, 342,
-        343, 344, 345, 75, 73, 321, 178, 321,
-        321, 102, 321, 321, 321, 182, 321, 346,
-        343, 347, 347, 75, 73, 321, 178, 321,
-        321, 321, 321, 321, 321, 182, 321, 343,
-        347, 347, 75, 73, 321, 178, 321, 321,
-        321, 321, 321, 321, 182, 321, 348, 321,
-        321, 321, 89, 349, 321, 73, 321, 178,
-        321, 321, 321, 321, 321, 348, 321, 350,
-        351, 352, 353, 75, 73, 321, 178, 321,
-        321, 100, 321, 321, 321, 182, 321, 354,
-        351, 355, 355, 75, 73, 321, 178, 321,
-        321, 321, 321, 321, 321, 182, 321, 351,
-        355, 355, 75, 73, 321, 178, 321, 321,
-        321, 321, 321, 321, 182, 321, 89, 356,
-        321, 73, 321, 178, 321, 357, 357, 321,
-        73, 321, 178, 321, 358, 321, 321, 359,
-        321, 178, 321, 178, 321, 360, 321, 361,
-        321, 358, 321, 321, 321, 321, 178, 321,
-        89, 321, 362, 362, 75, 73, 321, 178,
-        321, 363, 98, 364, 365, 79, 73, 321,
-        178, 321, 98, 364, 365, 79, 73, 321,
-        178, 321, 364, 364, 79, 73, 321, 178,
-        321, 366, 95, 367, 368, 82, 73, 321,
-        178, 321, 95, 367, 368, 82, 73, 321,
-        178, 321, 367, 367, 82, 73, 321, 178,
-        321, 369, 92, 370, 371, 85, 73, 321,
-        178, 321, 92, 370, 371, 85, 73, 321,
-        178, 321, 370, 370, 85, 73, 321, 178,
-        321, 372, 89, 357, 373, 321, 73, 321,
-        178, 321, 89, 357, 373, 321, 73, 321,
-        178, 321, 357, 374, 321, 73, 321, 178,
-        321, 89, 321, 357, 357, 321, 73, 321,
-        178, 321, 351, 355, 355, 75, 73, 321,
-        178, 321, 350, 351, 355, 355, 75, 73,
-        321, 178, 321, 321, 321, 321, 321, 321,
-        182, 321, 350, 351, 352, 355, 75, 73,
-        321, 178, 321, 321, 100, 321, 321, 321,
-        182, 321, 348, 321, 375, 321, 362, 362,
-        75, 73, 321, 178, 321, 321, 321, 321,
-        321, 348, 321, 348, 321, 321, 321, 357,
-        357, 321, 73, 321, 178, 321, 321, 321,
-        321, 321, 348, 321, 348, 321, 321, 321,
-        357, 376, 321, 73, 321, 178, 321, 321,
-        321, 321, 321, 348, 321, 348, 321, 375,
-        321, 357, 357, 321, 73, 321, 178, 321,
-        321, 321, 321, 321, 348, 321, 342, 343,
-        347, 347, 75, 73, 321, 178, 321, 321,
-        321, 321, 321, 321, 182, 321, 342, 343,
-        344, 347, 75, 73, 321, 178, 321, 321,
-        102, 321, 321, 321, 182, 321, 340, 321,
-        377, 321, 362, 362, 75, 73, 321, 178,
-        321, 321, 321, 321, 321, 340, 321, 340,
-        321, 321, 321, 357, 357, 321, 73, 321,
-        178, 321, 321, 321, 321, 321, 340, 321,
-        340, 321, 321, 321, 357, 378, 321, 73,
-        321, 178, 321, 321, 321, 321, 321, 340,
-        321, 340, 321, 377, 321, 357, 357, 321,
-        73, 321, 178, 321, 321, 321, 321, 321,
-        340, 321, 334, 335, 339, 339, 75, 73,
-        321, 178, 321, 321, 321, 321, 321, 321,
-        182, 321, 334, 335, 336, 339, 75, 73,
-        321, 178, 321, 321, 104, 321, 321, 321,
-        182, 321, 332, 321, 379, 321, 362, 362,
-        75, 73, 321, 178, 321, 321, 321, 321,
-        321, 332, 321, 332, 321, 321, 321, 357,
-        357, 321, 73, 321, 178, 321, 321, 321,
-        321, 321, 332, 321, 332, 321, 321, 321,
-        357, 380, 321, 73, 321, 178, 321, 321,
-        321, 321, 321, 332, 321, 332, 321, 379,
-        321, 357, 357, 321, 73, 321, 178, 321,
-        321, 321, 321, 321, 332, 321, 326, 327,
-        331, 331, 75, 73, 321, 178, 321, 321,
-        321, 321, 321, 321, 182, 321, 326, 327,
-        328, 331, 75, 73, 321, 178, 321, 321,
-        106, 321, 321, 321, 182, 321, 324, 321,
-        381, 321, 362, 362, 75, 73, 321, 178,
-        321, 321, 321, 321, 321, 324, 321, 324,
-        321, 321, 321, 357, 357, 321, 73, 321,
-        178, 321, 321, 321, 321, 321, 324, 321,
-        324, 321, 321, 321, 357, 382, 321, 73,
-        321, 178, 321, 321, 321, 321, 321, 324,
-        321, 324, 321, 381, 321, 357, 357, 321,
-        73, 321, 178, 321, 321, 321, 321, 321,
-        324, 321, 107, 74, 74, 75, 73, 383,
-        383, 383, 383, 144, 383, 174, 175, 323,
-        323, 75, 73, 321, 178, 321, 321, 321,
-        321, 321, 321, 182, 321, 107, 74, 74,
-        75, 73, 383, 385, 386, 387, 388, 111,
-        109, 384, 389, 384, 384, 143, 384, 384,
-        384, 390, 384, 391, 386, 388, 388, 111,
-        109, 384, 389, 384, 384, 384, 384, 384,
-        384, 390, 384, 386, 388, 388, 111, 109,
-        384, 389, 384, 384, 384, 384, 384, 384,
-        390, 384, 392, 384, 384, 384, 124, 393,
-        384, 109, 384, 389, 384, 384, 384, 384,
-        384, 392, 384, 394, 395, 396, 397, 111,
-        109, 384, 389, 384, 384, 141, 384, 384,
-        384, 390, 384, 398, 395, 399, 399, 111,
-        109, 384, 389, 384, 384, 384, 384, 384,
-        384, 390, 384, 395, 399, 399, 111, 109,
-        384, 389, 384, 384, 384, 384, 384, 384,
-        390, 384, 400, 384, 384, 384, 124, 401,
-        384, 109, 384, 389, 384, 384, 384, 384,
-        384, 400, 384, 402, 403, 404, 405, 111,
-        109, 384, 389, 384, 384, 139, 384, 384,
-        384, 390, 384, 406, 403, 407, 407, 111,
-        109, 384, 389, 384, 384, 384, 384, 384,
-        384, 390, 384, 403, 407, 407, 111, 109,
-        384, 389, 384, 384, 384, 384, 384, 384,
-        390, 384, 408, 384, 384, 384, 124, 409,
-        384, 109, 384, 389, 384, 384, 384, 384,
-        384, 408, 384, 410, 411, 412, 413, 111,
-        109, 384, 389, 384, 384, 137, 384, 384,
-        384, 390, 384, 414, 411, 415, 415, 111,
-        109, 384, 389, 384, 384, 384, 384, 384,
-        384, 390, 384, 411, 415, 415, 111, 109,
-        384, 389, 384, 384, 384, 384, 384, 384,
-        390, 384, 416, 384, 384, 384, 124, 417,
-        384, 109, 384, 389, 384, 384, 384, 384,
-        384, 416, 384, 418, 419, 420, 421, 111,
-        109, 384, 389, 384, 384, 135, 384, 384,
-        384, 390, 384, 422, 419, 423, 423, 111,
-        109, 384, 389, 384, 384, 384, 384, 384,
-        384, 390, 384, 419, 423, 423, 111, 109,
-        384, 389, 384, 384, 384, 384, 384, 384,
-        390, 384, 124, 424, 384, 109, 384, 389,
-        384, 425, 425, 384, 109, 384, 389, 384,
-        426, 384, 384, 427, 384, 389, 384, 389,
-        384, 428, 384, 429, 384, 426, 384, 384,
-        384, 384, 389, 384, 124, 384, 430, 430,
-        111, 109, 384, 389, 384, 431, 133, 432,
-        433, 114, 109, 384, 389, 384, 133, 432,
-        433, 114, 109, 384, 389, 384, 432, 432,
-        114, 109, 384, 389, 384, 434, 130, 435,
-        436, 117, 109, 384, 389, 384, 130, 435,
-        436, 117, 109, 384, 389, 384, 435, 435,
-        117, 109, 384, 389, 384, 437, 127, 438,
-        439, 120, 109, 384, 389, 384, 127, 438,
-        439, 120, 109, 384, 389, 384, 438, 438,
-        120, 109, 384, 389, 384, 440, 124, 425,
-        441, 384, 109, 384, 389, 384, 124, 425,
-        441, 384, 109, 384, 389, 384, 425, 442,
-        384, 109, 384, 389, 384, 124, 384, 425,
-        425, 384, 109, 384, 389, 384, 419, 423,
-        423, 111, 109, 384, 389, 384, 418, 419,
-        423, 423, 111, 109, 384, 389, 384, 384,
-        384, 384, 384, 384, 390, 384, 418, 419,
-        420, 423, 111, 109, 384, 389, 384, 384,
-        135, 384, 384, 384, 390, 384, 416, 384,
-        443, 384, 430, 430, 111, 109, 384, 389,
-        384, 384, 384, 384, 384, 416, 384, 416,
-        384, 384, 384, 425, 425, 384, 109, 384,
-        389, 384, 384, 384, 384, 384, 416, 384,
-        416, 384, 384, 384, 425, 444, 384, 109,
-        384, 389, 384, 384, 384, 384, 384, 416,
-        384, 416, 384, 443, 384, 425, 425, 384,
-        109, 384, 389, 384, 384, 384, 384, 384,
-        416, 384, 410, 411, 415, 415, 111, 109,
-        384, 389, 384, 384, 384, 384, 384, 384,
-        390, 384, 410, 411, 412, 415, 111, 109,
-        384, 389, 384, 384, 137, 384, 384, 384,
-        390, 384, 408, 384, 445, 384, 430, 430,
-        111, 109, 384, 389, 384, 384, 384, 384,
-        384, 408, 384, 408, 384, 384, 384, 425,
-        425, 384, 109, 384, 389, 384, 384, 384,
-        384, 384, 408, 384, 408, 384, 384, 384,
-        425, 446, 384, 109, 384, 389, 384, 384,
-        384, 384, 384, 408, 384, 408, 384, 445,
-        384, 425, 425, 384, 109, 384, 389, 384,
-        384, 384, 384, 384, 408, 384, 402, 403,
-        407, 407, 111, 109, 384, 389, 384, 384,
-        384, 384, 384, 384, 390, 384, 402, 403,
-        404, 407, 111, 109, 384, 389, 384, 384,
-        139, 384, 384, 384, 390, 384, 400, 384,
-        447, 384, 430, 430, 111, 109, 384, 389,
-        384, 384, 384, 384, 384, 400, 384, 400,
-        384, 384, 384, 425, 425, 384, 109, 384,
-        389, 384, 384, 384, 384, 384, 400, 384,
-        400, 384, 384, 384, 425, 448, 384, 109,
-        384, 389, 384, 384, 384, 384, 384, 400,
-        384, 400, 384, 447, 384, 425, 425, 384,
-        109, 384, 389, 384, 384, 384, 384, 384,
-        400, 384, 394, 395, 399, 399, 111, 109,
-        384, 389, 384, 384, 384, 384, 384, 384,
-        390, 384, 394, 395, 396, 399, 111, 109,
-        384, 389, 384, 384, 141, 384, 384, 384,
-        390, 384, 392, 384, 449, 384, 430, 430,
-        111, 109, 384, 389, 384, 384, 384, 384,
-        384, 392, 384, 392, 384, 384, 384, 425,
-        425, 384, 109, 384, 389, 384, 384, 384,
-        384, 384, 392, 384, 392, 384, 384, 384,
-        425, 450, 384, 109, 384, 389, 384, 384,
-        384, 384, 384, 392, 384, 392, 384, 449,
-        384, 425, 425, 384, 109, 384, 389, 384,
-        384, 384, 384, 384, 392, 384, 385, 386,
-        388, 388, 111, 109, 384, 389, 384, 384,
-        384, 384, 384, 384, 390, 384, 172, 173,
-        174, 175, 451, 323, 75, 73, 321, 178,
-        179, 179, 144, 321, 321, 172, 182, 321,
-        186, 452, 188, 189, 3, 1, 185, 190,
-        185, 185, 35, 185, 185, 185, 191, 185,
-        194, 173, 174, 175, 453, 454, 75, 149,
-        185, 455, 185, 179, 144, 185, 185, 194,
-        182, 185, 107, 456, 456, 75, 149, 185,
-        190, 185, 185, 144, 185, 457, 185, 185,
-        458, 185, 455, 185, 455, 185, 459, 185,
-        231, 185, 457, 185, 185, 185, 185, 455,
-        185, 194, 185, 251, 107, 460, 460, 146,
-        149, 185, 190, 185, 185, 185, 185, 185,
-        194, 185, 461, 168, 462, 463, 148, 149,
-        185, 455, 185, 168, 462, 463, 148, 149,
-        185, 455, 185, 462, 462, 148, 149, 185,
-        455, 185, 464, 165, 465, 466, 152, 149,
-        185, 455, 185, 165, 465, 466, 152, 149,
-        185, 455, 185, 465, 465, 152, 149, 185,
-        455, 185, 467, 162, 468, 469, 155, 149,
-        185, 455, 185, 162, 468, 469, 155, 149,
-        185, 455, 185, 468, 468, 155, 149, 185,
-        455, 185, 470, 159, 471, 472, 185, 149,
-        185, 455, 185, 159, 471, 472, 185, 149,
-        185, 455, 185, 471, 471, 185, 149, 185,
-        455, 185, 474, 473, 475, 475, 473, 170,
-        473, 476, 473, 475, 475, 473, 170, 473,
-        476, 473, 477, 473, 473, 478, 473, 476,
-        473, 476, 473, 479, 473, 480, 473, 477,
-        473, 473, 473, 473, 476, 473, 172, 383,
-        383, 383, 383, 383, 383, 383, 383, 383,
-        179, 383, 383, 383, 383, 172, 383, 0
+        1, 0, 2, 3, 3, 4, 1, 0,
+        5, 5, 4, 0, 4, 0, 6, 6,
+        7, 1, 0, 8, 8, 7, 0, 7,
+        0, 9, 9, 10, 1, 0, 11, 11,
+        10, 0, 10, 0, 12, 12, 13, 1,
+        0, 14, 14, 13, 0, 13, 0, 15,
+        0, 0, 0, 1, 0, 16, 0, 17,
+        0, 18, 12, 12, 13, 1, 0, 19,
+        0, 20, 0, 21, 9, 9, 10, 1,
+        0, 22, 0, 23, 0, 24, 6, 6,
+        7, 1, 0, 25, 0, 26, 0, 2,
+        3, 3, 4, 1, 0, 0, 0, 0,
+        27, 0, 28, 3, 3, 4, 1, 0,
+        28, 3, 3, 4, 1, 0, 0, 0,
+        0, 29, 0, 30, 3, 3, 4, 1,
+        0, 30, 3, 3, 4, 1, 0, 0,
+        0, 0, 31, 0, 32, 3, 3, 4,
+        1, 0, 32, 3, 3, 4, 1, 0,
+        0, 0, 0, 33, 0, 34, 3, 3,
+        4, 1, 0, 34, 3, 3, 4, 1,
+        0, 0, 0, 0, 35, 0, 37, 36,
+        38, 39, 39, 40, 37, 36, 41, 41,
+        40, 36, 40, 36, 42, 42, 43, 37,
+        36, 44, 44, 43, 36, 43, 36, 45,
+        45, 46, 37, 36, 47, 47, 46, 36,
+        46, 36, 48, 48, 49, 37, 36, 50,
+        50, 49, 36, 49, 36, 51, 36, 36,
+        36, 37, 36, 52, 36, 53, 36, 54,
+        48, 48, 49, 37, 36, 55, 36, 56,
+        36, 57, 45, 45, 46, 37, 36, 58,
+        36, 59, 36, 60, 42, 42, 43, 37,
+        36, 61, 36, 62, 36, 38, 39, 39,
+        40, 37, 36, 36, 36, 36, 63, 36,
+        64, 39, 39, 40, 37, 36, 64, 39,
+        39, 40, 37, 36, 36, 36, 36, 65,
+        36, 66, 39, 39, 40, 37, 36, 66,
+        39, 39, 40, 37, 36, 36, 36, 36,
+        67, 36, 68, 39, 39, 40, 37, 36,
+        68, 39, 39, 40, 37, 36, 36, 36,
+        36, 69, 36, 70, 39, 39, 40, 37,
+        36, 70, 39, 39, 40, 37, 36, 36,
+        36, 36, 71, 36, 73, 72, 74, 75,
+        75, 76, 73, 72, 78, 78, 76, 77,
+        76, 77, 79, 79, 80, 73, 72, 81,
+        81, 80, 72, 80, 72, 82, 82, 83,
+        73, 72, 84, 84, 83, 72, 83, 72,
+        85, 85, 86, 73, 72, 87, 87, 86,
+        72, 86, 72, 88, 72, 72, 72, 73,
+        72, 89, 72, 90, 72, 91, 85, 85,
+        86, 73, 72, 92, 72, 93, 72, 94,
+        82, 82, 83, 73, 72, 95, 72, 96,
+        72, 97, 79, 79, 80, 73, 72, 98,
+        72, 99, 72, 74, 75, 75, 76, 73,
+        72, 72, 72, 72, 100, 72, 101, 75,
+        75, 76, 73, 72, 101, 75, 75, 76,
+        73, 72, 72, 72, 72, 102, 72, 103,
+        75, 75, 76, 73, 72, 103, 75, 75,
+        76, 73, 72, 72, 72, 72, 104, 72,
+        105, 75, 75, 76, 73, 72, 105, 75,
+        75, 76, 73, 72, 72, 72, 72, 106,
+        72, 107, 75, 75, 76, 73, 72, 109,
+        108, 110, 111, 111, 112, 109, 108, 113,
+        113, 112, 108, 112, 108, 114, 114, 115,
+        109, 108, 116, 116, 115, 108, 115, 108,
+        117, 117, 118, 109, 108, 119, 119, 118,
+        108, 118, 108, 120, 120, 121, 109, 108,
+        122, 122, 121, 108, 121, 108, 123, 108,
+        108, 108, 109, 108, 124, 108, 125, 108,
+        126, 120, 120, 121, 109, 108, 127, 108,
+        128, 108, 129, 117, 117, 118, 109, 108,
+        130, 108, 131, 108, 132, 114, 114, 115,
+        109, 108, 133, 108, 134, 108, 110, 111,
+        111, 112, 109, 108, 108, 108, 108, 135,
+        108, 136, 111, 111, 112, 109, 108, 136,
+        111, 111, 112, 109, 108, 108, 108, 108,
+        137, 108, 138, 111, 111, 112, 109, 108,
+        138, 111, 111, 112, 109, 108, 108, 108,
+        108, 139, 108, 140, 111, 111, 112, 109,
+        108, 140, 111, 111, 112, 109, 108, 108,
+        108, 108, 141, 108, 142, 111, 111, 112,
+        109, 108, 142, 111, 111, 112, 109, 108,
+        108, 108, 108, 143, 108, 107, 75, 75,
+        76, 73, 72, 72, 72, 72, 144, 72,
+        78, 78, 76, 1, 0, 146, 145, 148,
+        149, 150, 151, 152, 153, 76, 73, 147,
+        154, 155, 155, 144, 147, 156, 157, 147,
+        158, 159, 147, 161, 162, 163, 164, 4,
+        1, 160, 165, 160, 160, 35, 160, 166,
+        162, 167, 167, 4, 1, 160, 165, 160,
+        162, 167, 167, 4, 1, 160, 165, 160,
+        168, 160, 160, 160, 17, 169, 160, 1,
+        160, 165, 160, 160, 160, 160, 160, 168,
+        160, 170, 171, 172, 173, 4, 1, 160,
+        165, 160, 160, 33, 160, 174, 171, 175,
+        175, 4, 1, 160, 165, 160, 171, 175,
+        175, 4, 1, 160, 165, 160, 176, 160,
+        160, 160, 17, 177, 160, 1, 160, 165,
+        160, 160, 160, 160, 160, 176, 160, 178,
+        179, 180, 181, 4, 1, 160, 165, 160,
+        160, 31, 160, 182, 179, 183, 183, 4,
+        1, 160, 165, 160, 179, 183, 183, 4,
+        1, 160, 165, 160, 184, 160, 160, 160,
+        17, 185, 160, 1, 160, 165, 160, 160,
+        160, 160, 160, 184, 160, 186, 187, 188,
+        189, 4, 1, 160, 165, 160, 160, 29,
+        160, 190, 187, 191, 191, 4, 1, 160,
+        165, 160, 187, 191, 191, 4, 1, 160,
+        165, 160, 192, 160, 160, 160, 17, 193,
+        160, 1, 160, 165, 160, 160, 160, 160,
+        160, 192, 160, 194, 195, 196, 197, 4,
+        1, 160, 165, 160, 160, 27, 160, 198,
+        195, 199, 199, 4, 1, 160, 165, 160,
+        195, 199, 199, 4, 1, 160, 165, 160,
+        17, 200, 160, 1, 160, 165, 160, 201,
+        201, 160, 1, 160, 165, 160, 202, 160,
+        160, 203, 160, 165, 160, 165, 160, 204,
+        160, 205, 160, 202, 160, 160, 160, 160,
+        165, 160, 17, 160, 201, 201, 160, 1,
+        160, 165, 160, 201, 200, 160, 1, 160,
+        165, 160, 206, 26, 207, 208, 7, 1,
+        160, 165, 160, 26, 207, 208, 7, 1,
+        160, 165, 160, 207, 207, 7, 1, 160,
+        165, 160, 209, 23, 210, 211, 10, 1,
+        160, 165, 160, 23, 210, 211, 10, 1,
+        160, 165, 160, 210, 210, 10, 1, 160,
+        165, 160, 212, 20, 213, 214, 13, 1,
+        160, 165, 160, 20, 213, 214, 13, 1,
+        160, 165, 160, 213, 213, 13, 1, 160,
+        165, 160, 215, 17, 201, 216, 160, 1,
+        160, 165, 160, 17, 201, 216, 160, 1,
+        160, 165, 160, 194, 195, 199, 199, 4,
+        1, 160, 165, 160, 194, 195, 196, 199,
+        4, 1, 160, 165, 160, 160, 27, 160,
+        192, 160, 217, 160, 201, 201, 160, 1,
+        160, 165, 160, 160, 160, 160, 160, 192,
+        160, 192, 160, 160, 160, 201, 201, 160,
+        1, 160, 165, 160, 160, 160, 160, 160,
+        192, 160, 192, 160, 160, 160, 201, 193,
+        160, 1, 160, 165, 160, 160, 160, 160,
+        160, 192, 160, 186, 187, 191, 191, 4,
+        1, 160, 165, 160, 186, 187, 188, 191,
+        4, 1, 160, 165, 160, 160, 29, 160,
+        184, 160, 218, 160, 201, 201, 160, 1,
+        160, 165, 160, 160, 160, 160, 160, 184,
+        160, 184, 160, 160, 160, 201, 201, 160,
+        1, 160, 165, 160, 160, 160, 160, 160,
+        184, 160, 184, 160, 160, 160, 201, 185,
+        160, 1, 160, 165, 160, 160, 160, 160,
+        160, 184, 160, 178, 179, 183, 183, 4,
+        1, 160, 165, 160, 178, 179, 180, 183,
+        4, 1, 160, 165, 160, 160, 31, 160,
+        176, 160, 219, 160, 201, 201, 160, 1,
+        160, 165, 160, 160, 160, 160, 160, 176,
+        160, 176, 160, 160, 160, 201, 201, 160,
+        1, 160, 165, 160, 160, 160, 160, 160,
+        176, 160, 176, 160, 160, 160, 201, 177,
+        160, 1, 160, 165, 160, 160, 160, 160,
+        160, 176, 160, 170, 171, 175, 175, 4,
+        1, 160, 165, 160, 170, 171, 172, 175,
+        4, 1, 160, 165, 160, 160, 33, 160,
+        168, 160, 220, 160, 201, 201, 160, 1,
+        160, 165, 160, 160, 160, 160, 160, 168,
+        160, 168, 160, 160, 160, 201, 201, 160,
+        1, 160, 165, 160, 160, 160, 160, 160,
+        168, 160, 168, 160, 160, 160, 201, 169,
+        160, 1, 160, 165, 160, 160, 160, 160,
+        160, 168, 160, 161, 162, 167, 167, 4,
+        1, 160, 165, 160, 161, 162, 163, 167,
+        4, 1, 160, 165, 160, 160, 35, 160,
+        222, 223, 224, 225, 40, 37, 221, 226,
+        221, 221, 71, 221, 227, 223, 228, 225,
+        40, 37, 221, 226, 221, 223, 228, 225,
+        40, 37, 221, 226, 221, 229, 221, 221,
+        221, 53, 230, 221, 37, 221, 226, 221,
+        221, 221, 221, 221, 229, 221, 231, 232,
+        233, 234, 40, 37, 221, 226, 221, 221,
+        69, 221, 235, 232, 236, 236, 40, 37,
+        221, 226, 221, 232, 236, 236, 40, 37,
+        221, 226, 221, 237, 221, 221, 221, 53,
+        238, 221, 37, 221, 226, 221, 221, 221,
+        221, 221, 237, 221, 239, 240, 241, 242,
+        40, 37, 221, 226, 221, 221, 67, 221,
+        243, 240, 244, 244, 40, 37, 221, 226,
+        221, 240, 244, 244, 40, 37, 221, 226,
+        221, 245, 221, 221, 221, 53, 246, 221,
+        37, 221, 226, 221, 221, 221, 221, 221,
+        245, 221, 247, 248, 249, 250, 40, 37,
+        221, 226, 221, 221, 65, 221, 251, 248,
+        252, 252, 40, 37, 221, 226, 221, 248,
+        252, 252, 40, 37, 221, 226, 221, 253,
+        221, 221, 221, 53, 254, 221, 37, 221,
+        226, 221, 221, 221, 221, 221, 253, 221,
+        255, 256, 257, 258, 40, 37, 221, 226,
+        221, 221, 63, 221, 259, 256, 260, 260,
+        40, 37, 221, 226, 221, 256, 260, 260,
+        40, 37, 221, 226, 221, 53, 261, 221,
+        37, 221, 226, 221, 262, 262, 221, 37,
+        221, 226, 221, 263, 221, 221, 264, 221,
+        226, 221, 226, 221, 265, 221, 266, 221,
+        263, 221, 221, 221, 221, 226, 221, 53,
+        221, 262, 262, 221, 37, 221, 226, 221,
+        262, 261, 221, 37, 221, 226, 221, 267,
+        62, 268, 269, 43, 37, 221, 226, 221,
+        62, 268, 269, 43, 37, 221, 226, 221,
+        268, 268, 43, 37, 221, 226, 221, 270,
+        59, 271, 272, 46, 37, 221, 226, 221,
+        59, 271, 272, 46, 37, 221, 226, 221,
+        271, 271, 46, 37, 221, 226, 221, 273,
+        56, 274, 275, 49, 37, 221, 226, 221,
+        56, 274, 275, 49, 37, 221, 226, 221,
+        274, 274, 49, 37, 221, 226, 221, 276,
+        53, 262, 277, 221, 37, 221, 226, 221,
+        53, 262, 277, 221, 37, 221, 226, 221,
+        255, 256, 260, 260, 40, 37, 221, 226,
+        221, 255, 256, 257, 260, 40, 37, 221,
+        226, 221, 221, 63, 221, 253, 221, 278,
+        221, 262, 262, 221, 37, 221, 226, 221,
+        221, 221, 221, 221, 253, 221, 253, 221,
+        221, 221, 262, 262, 221, 37, 221, 226,
+        221, 221, 221, 221, 221, 253, 221, 253,
+        221, 221, 221, 262, 254, 221, 37, 221,
+        226, 221, 221, 221, 221, 221, 253, 221,
+        247, 248, 252, 252, 40, 37, 221, 226,
+        221, 247, 248, 249, 252, 40, 37, 221,
+        226, 221, 221, 65, 221, 245, 221, 279,
+        221, 262, 262, 221, 37, 221, 226, 221,
+        221, 221, 221, 221, 245, 221, 245, 221,
+        221, 221, 262, 262, 221, 37, 221, 226,
+        221, 221, 221, 221, 221, 245, 221, 245,
+        221, 221, 221, 262, 246, 221, 37, 221,
+        226, 221, 221, 221, 221, 221, 245, 221,
+        239, 240, 244, 244, 40, 37, 221, 226,
+        221, 239, 240, 241, 244, 40, 37, 221,
+        226, 221, 221, 67, 221, 237, 221, 280,
+        221, 262, 262, 221, 37, 221, 226, 221,
+        221, 221, 221, 221, 237, 221, 237, 221,
+        221, 221, 262, 262, 221, 37, 221, 226,
+        221, 221, 221, 221, 221, 237, 221, 237,
+        221, 221, 221, 262, 238, 221, 37, 221,
+        226, 221, 221, 221, 221, 221, 237, 221,
+        231, 232, 236, 236, 40, 37, 221, 226,
+        221, 231, 232, 233, 236, 40, 37, 221,
+        226, 221, 221, 69, 221, 229, 221, 281,
+        221, 262, 262, 221, 37, 221, 226, 221,
+        221, 221, 221, 221, 229, 221, 229, 221,
+        221, 221, 262, 262, 221, 37, 221, 226,
+        221, 221, 221, 221, 221, 229, 221, 229,
+        221, 221, 221, 262, 230, 221, 37, 221,
+        226, 221, 221, 221, 221, 221, 229, 221,
+        70, 39, 39, 40, 37, 221, 222, 223,
+        228, 225, 40, 37, 221, 226, 221, 283,
+        151, 284, 284, 76, 73, 282, 154, 282,
+        151, 284, 284, 76, 73, 282, 154, 282,
+        285, 282, 282, 282, 90, 286, 282, 73,
+        282, 154, 282, 282, 282, 282, 282, 285,
+        282, 287, 288, 289, 290, 76, 73, 282,
+        154, 282, 282, 106, 282, 291, 288, 292,
+        292, 76, 73, 282, 154, 282, 288, 292,
+        292, 76, 73, 282, 154, 282, 293, 282,
+        282, 282, 90, 294, 282, 73, 282, 154,
+        282, 282, 282, 282, 282, 293, 282, 295,
+        296, 297, 298, 76, 73, 282, 154, 282,
+        282, 104, 282, 299, 296, 300, 300, 76,
+        73, 282, 154, 282, 296, 300, 300, 76,
+        73, 282, 154, 282, 301, 282, 282, 282,
+        90, 302, 282, 73, 282, 154, 282, 282,
+        282, 282, 282, 301, 282, 303, 304, 305,
+        306, 76, 73, 282, 154, 282, 282, 102,
+        282, 307, 304, 308, 308, 76, 73, 282,
+        154, 282, 304, 308, 308, 76, 73, 282,
+        154, 282, 309, 282, 282, 282, 90, 310,
+        282, 73, 282, 154, 282, 282, 282, 282,
+        282, 309, 282, 311, 312, 313, 314, 76,
+        73, 282, 154, 282, 282, 100, 282, 315,
+        312, 316, 316, 76, 73, 282, 154, 282,
+        312, 316, 316, 76, 73, 282, 154, 282,
+        90, 317, 282, 73, 282, 154, 282, 318,
+        318, 282, 73, 282, 154, 282, 319, 282,
+        282, 320, 282, 154, 282, 154, 282, 321,
+        282, 322, 282, 319, 282, 282, 282, 282,
+        154, 282, 90, 282, 318, 318, 282, 73,
+        282, 154, 282, 318, 317, 282, 73, 282,
+        154, 282, 323, 99, 324, 325, 80, 73,
+        282, 154, 282, 99, 324, 325, 80, 73,
+        282, 154, 282, 324, 324, 80, 73, 282,
+        154, 282, 326, 96, 327, 328, 83, 73,
+        282, 154, 282, 96, 327, 328, 83, 73,
+        282, 154, 282, 327, 327, 83, 73, 282,
+        154, 282, 329, 93, 330, 331, 86, 73,
+        282, 154, 282, 93, 330, 331, 86, 73,
+        282, 154, 282, 330, 330, 86, 73, 282,
+        154, 282, 332, 90, 318, 333, 282, 73,
+        282, 154, 282, 90, 318, 333, 282, 73,
+        282, 154, 282, 311, 312, 316, 316, 76,
+        73, 282, 154, 282, 311, 312, 313, 316,
+        76, 73, 282, 154, 282, 282, 100, 282,
+        309, 282, 334, 282, 318, 318, 282, 73,
+        282, 154, 282, 282, 282, 282, 282, 309,
+        282, 309, 282, 282, 282, 318, 318, 282,
+        73, 282, 154, 282, 282, 282, 282, 282,
+        309, 282, 309, 282, 282, 282, 318, 310,
+        282, 73, 282, 154, 282, 282, 282, 282,
+        282, 309, 282, 303, 304, 308, 308, 76,
+        73, 282, 154, 282, 303, 304, 305, 308,
+        76, 73, 282, 154, 282, 282, 102, 282,
+        301, 282, 335, 282, 318, 318, 282, 73,
+        282, 154, 282, 282, 282, 282, 282, 301,
+        282, 301, 282, 282, 282, 318, 318, 282,
+        73, 282, 154, 282, 282, 282, 282, 282,
+        301, 282, 301, 282, 282, 282, 318, 302,
+        282, 73, 282, 154, 282, 282, 282, 282,
+        282, 301, 282, 295, 296, 300, 300, 76,
+        73, 282, 154, 282, 295, 296, 297, 300,
+        76, 73, 282, 154, 282, 282, 104, 282,
+        293, 282, 336, 282, 318, 318, 282, 73,
+        282, 154, 282, 282, 282, 282, 282, 293,
+        282, 293, 282, 282, 282, 318, 318, 282,
+        73, 282, 154, 282, 282, 282, 282, 282,
+        293, 282, 293, 282, 282, 282, 318, 294,
+        282, 73, 282, 154, 282, 282, 282, 282,
+        282, 293, 282, 287, 288, 292, 292, 76,
+        73, 282, 154, 282, 287, 288, 289, 292,
+        76, 73, 282, 154, 282, 282, 106, 282,
+        285, 282, 337, 282, 318, 318, 282, 73,
+        282, 154, 282, 282, 282, 282, 282, 285,
+        282, 285, 282, 282, 282, 318, 318, 282,
+        73, 282, 154, 282, 282, 282, 282, 282,
+        285, 282, 285, 282, 282, 282, 318, 286,
+        282, 73, 282, 154, 282, 282, 282, 282,
+        282, 285, 282, 107, 75, 75, 76, 73,
+        338, 338, 338, 338, 144, 338, 150, 151,
+        284, 284, 76, 73, 282, 154, 282, 107,
+        75, 75, 76, 73, 338, 340, 341, 342,
+        343, 112, 109, 339, 344, 339, 339, 143,
+        339, 345, 341, 343, 343, 112, 109, 339,
+        344, 339, 341, 343, 343, 112, 109, 339,
+        344, 339, 346, 339, 339, 339, 125, 347,
+        339, 109, 339, 344, 339, 339, 339, 339,
+        339, 346, 339, 348, 349, 350, 351, 112,
+        109, 339, 344, 339, 339, 141, 339, 352,
+        349, 353, 353, 112, 109, 339, 344, 339,
+        349, 353, 353, 112, 109, 339, 344, 339,
+        354, 339, 339, 339, 125, 355, 339, 109,
+        339, 344, 339, 339, 339, 339, 339, 354,
+        339, 356, 357, 358, 359, 112, 109, 339,
+        344, 339, 339, 139, 339, 360, 357, 361,
+        361, 112, 109, 339, 344, 339, 357, 361,
+        361, 112, 109, 339, 344, 339, 362, 339,
+        339, 339, 125, 363, 339, 109, 339, 344,
+        339, 339, 339, 339, 339, 362, 339, 364,
+        365, 366, 367, 112, 109, 339, 344, 339,
+        339, 137, 339, 368, 365, 369, 369, 112,
+        109, 339, 344, 339, 365, 369, 369, 112,
+        109, 339, 344, 339, 370, 339, 339, 339,
+        125, 371, 339, 109, 339, 344, 339, 339,
+        339, 339, 339, 370, 339, 372, 373, 374,
+        375, 112, 109, 339, 344, 339, 339, 135,
+        339, 376, 373, 377, 377, 112, 109, 339,
+        344, 339, 373, 377, 377, 112, 109, 339,
+        344, 339, 125, 378, 339, 109, 339, 344,
+        339, 379, 379, 339, 109, 339, 344, 339,
+        380, 339, 339, 381, 339, 344, 339, 344,
+        339, 382, 339, 383, 339, 380, 339, 339,
+        339, 339, 344, 339, 125, 339, 379, 379,
+        339, 109, 339, 344, 339, 379, 378, 339,
+        109, 339, 344, 339, 384, 134, 385, 386,
+        115, 109, 339, 344, 339, 134, 385, 386,
+        115, 109, 339, 344, 339, 385, 385, 115,
+        109, 339, 344, 339, 387, 131, 388, 389,
+        118, 109, 339, 344, 339, 131, 388, 389,
+        118, 109, 339, 344, 339, 388, 388, 118,
+        109, 339, 344, 339, 390, 128, 391, 392,
+        121, 109, 339, 344, 339, 128, 391, 392,
+        121, 109, 339, 344, 339, 391, 391, 121,
+        109, 339, 344, 339, 393, 125, 379, 394,
+        339, 109, 339, 344, 339, 125, 379, 394,
+        339, 109, 339, 344, 339, 372, 373, 377,
+        377, 112, 109, 339, 344, 339, 372, 373,
+        374, 377, 112, 109, 339, 344, 339, 339,
+        135, 339, 370, 339, 395, 339, 379, 379,
+        339, 109, 339, 344, 339, 339, 339, 339,
+        339, 370, 339, 370, 339, 339, 339, 379,
+        379, 339, 109, 339, 344, 339, 339, 339,
+        339, 339, 370, 339, 370, 339, 339, 339,
+        379, 371, 339, 109, 339, 344, 339, 339,
+        339, 339, 339, 370, 339, 364, 365, 369,
+        369, 112, 109, 339, 344, 339, 364, 365,
+        366, 369, 112, 109, 339, 344, 339, 339,
+        137, 339, 362, 339, 396, 339, 379, 379,
+        339, 109, 339, 344, 339, 339, 339, 339,
+        339, 362, 339, 362, 339, 339, 339, 379,
+        379, 339, 109, 339, 344, 339, 339, 339,
+        339, 339, 362, 339, 362, 339, 339, 339,
+        379, 363, 339, 109, 339, 344, 339, 339,
+        339, 339, 339, 362, 339, 356, 357, 361,
+        361, 112, 109, 339, 344, 339, 356, 357,
+        358, 361, 112, 109, 339, 344, 339, 339,
+        139, 339, 354, 339, 397, 339, 379, 379,
+        339, 109, 339, 344, 339, 339, 339, 339,
+        339, 354, 339, 354, 339, 339, 339, 379,
+        379, 339, 109, 339, 344, 339, 339, 339,
+        339, 339, 354, 339, 354, 339, 339, 339,
+        379, 355, 339, 109, 339, 344, 339, 339,
+        339, 339, 339, 354, 339, 348, 349, 353,
+        353, 112, 109, 339, 344, 339, 348, 349,
+        350, 353, 112, 109, 339, 344, 339, 339,
+        141, 339, 346, 339, 398, 339, 379, 379,
+        339, 109, 339, 344, 339, 339, 339, 339,
+        339, 346, 339, 346, 339, 339, 339, 379,
+        379, 339, 109, 339, 344, 339, 339, 339,
+        339, 339, 346, 339, 346, 339, 339, 339,
+        379, 347, 339, 109, 339, 344, 339, 339,
+        339, 339, 339, 346, 339, 340, 341, 343,
+        343, 112, 109, 339, 344, 339, 148, 149,
+        150, 151, 399, 284, 76, 73, 282, 154,
+        155, 155, 144, 282, 282, 148, 282, 161,
+        400, 163, 164, 4, 1, 160, 165, 160,
+        160, 35, 160, 168, 149, 150, 151, 401,
+        402, 76, 403, 160, 404, 160, 155, 144,
+        160, 160, 168, 160, 107, 405, 405, 76,
+        403, 160, 165, 160, 160, 144, 160, 406,
+        160, 160, 407, 160, 404, 160, 404, 160,
+        408, 160, 205, 160, 406, 160, 160, 160,
+        160, 404, 160, 168, 160, 220, 107, 405,
+        405, 76, 403, 160, 165, 160, 160, 160,
+        160, 160, 168, 160, 410, 409, 411, 411,
+        409, 146, 409, 412, 409, 411, 411, 409,
+        146, 409, 412, 409, 413, 409, 409, 414,
+        409, 412, 409, 412, 409, 415, 409, 416,
+        409, 413, 409, 409, 409, 409, 412, 409,
+        148, 338, 338, 338, 338, 338, 338, 338,
+        338, 338, 155, 338, 338, 338, 338, 148,
+        338, 0
 };
 
 static const short _indic_syllable_machine_trans_targs[] = {
-        166, 188, 2, 194, 3, 5, 197, 6,
-        8, 200, 9, 11, 203, 12, 14, 15,
-        187, 17, 18, 202, 20, 21, 199, 23,
-        24, 196, 205, 208, 212, 214, 218, 220,
-        224, 226, 230, 232, 166, 255, 37, 261,
-        38, 40, 264, 41, 43, 267, 44, 46,
-        270, 47, 49, 50, 254, 52, 53, 269,
-        55, 56, 266, 58, 59, 263, 272, 275,
-        279, 281, 285, 287, 291, 293, 297, 300,
-        166, 321, 72, 327, 166, 73, 75, 330,
-        76, 78, 333, 79, 81, 336, 82, 84,
-        85, 320, 87, 88, 335, 90, 91, 332,
-        93, 94, 329, 338, 341, 345, 347, 351,
-        353, 357, 359, 363, 166, 389, 106, 395,
-        107, 109, 398, 110, 112, 401, 113, 115,
-        404, 116, 118, 119, 388, 121, 122, 403,
-        124, 125, 400, 127, 128, 397, 406, 409,
-        413, 415, 419, 421, 425, 427, 431, 433,
-        366, 142, 444, 144, 447, 438, 145, 147,
-        450, 148, 150, 453, 151, 154, 155, 455,
-        157, 158, 452, 160, 161, 449, 163, 164,
-        446, 166, 458, 166, 167, 234, 301, 303,
-        365, 367, 323, 368, 434, 435, 340, 456,
-        463, 166, 168, 170, 34, 233, 190, 207,
-        169, 33, 171, 228, 172, 174, 32, 227,
-        173, 31, 175, 222, 176, 178, 30, 221,
-        177, 29, 179, 216, 180, 182, 28, 215,
-        181, 27, 183, 210, 184, 186, 26, 209,
-        185, 25, 193, 0, 189, 192, 191, 166,
-        1, 195, 4, 22, 198, 7, 19, 201,
-        10, 16, 204, 13, 206, 211, 213, 217,
-        219, 223, 225, 229, 231, 166, 235, 237,
-        69, 299, 257, 274, 236, 68, 238, 295,
-        239, 241, 67, 294, 240, 66, 242, 289,
-        243, 245, 65, 288, 244, 64, 246, 283,
-        247, 249, 63, 282, 248, 62, 250, 277,
-        251, 253, 61, 276, 252, 60, 260, 35,
-        256, 259, 258, 166, 36, 262, 39, 57,
-        265, 42, 54, 268, 45, 51, 271, 48,
-        273, 278, 280, 284, 286, 290, 292, 296,
-        298, 166, 302, 103, 304, 361, 305, 307,
-        102, 360, 306, 101, 308, 355, 309, 311,
-        100, 354, 310, 99, 312, 349, 313, 315,
-        98, 348, 314, 97, 316, 343, 317, 319,
-        96, 342, 318, 95, 326, 70, 322, 325,
-        324, 166, 71, 328, 74, 92, 331, 77,
-        89, 334, 80, 86, 337, 83, 339, 344,
-        346, 350, 352, 356, 358, 362, 364, 166,
-        166, 369, 371, 138, 137, 391, 408, 370,
-        372, 429, 373, 375, 136, 428, 374, 135,
-        376, 423, 377, 379, 134, 422, 378, 133,
-        380, 417, 381, 383, 132, 416, 382, 131,
-        384, 411, 385, 387, 130, 410, 386, 129,
-        394, 104, 390, 393, 392, 166, 105, 396,
-        108, 126, 399, 111, 123, 402, 114, 120,
-        405, 117, 407, 412, 414, 418, 420, 424,
-        426, 430, 432, 139, 436, 437, 443, 440,
-        140, 439, 442, 441, 141, 445, 143, 162,
-        448, 146, 159, 451, 149, 156, 454, 152,
-        153, 166, 457, 165, 460, 459, 462, 461,
-        166
+        138, 160, 166, 2, 167, 3, 5, 170,
+        6, 8, 173, 9, 11, 176, 12, 14,
+        15, 159, 17, 18, 175, 20, 21, 172,
+        23, 24, 169, 178, 182, 183, 187, 188,
+        192, 193, 197, 198, 138, 221, 227, 36,
+        228, 37, 39, 231, 40, 42, 234, 43,
+        45, 237, 46, 48, 49, 220, 51, 52,
+        236, 54, 55, 233, 57, 58, 230, 239,
+        243, 244, 248, 249, 253, 254, 258, 260,
+        138, 281, 287, 70, 288, 138, 71, 73,
+        291, 74, 76, 294, 77, 79, 297, 80,
+        82, 83, 280, 85, 86, 296, 88, 89,
+        293, 91, 92, 290, 299, 303, 304, 308,
+        309, 313, 314, 318, 138, 343, 349, 103,
+        350, 104, 106, 353, 107, 109, 356, 110,
+        112, 359, 113, 115, 116, 342, 118, 119,
+        358, 121, 122, 355, 124, 125, 352, 361,
+        365, 366, 370, 371, 375, 376, 380, 381,
+        320, 138, 394, 138, 139, 200, 261, 263,
+        319, 321, 283, 322, 382, 383, 392, 399,
+        138, 140, 142, 33, 199, 162, 141, 32,
+        143, 195, 144, 146, 31, 194, 145, 30,
+        147, 190, 148, 150, 29, 189, 149, 28,
+        151, 185, 152, 154, 27, 184, 153, 26,
+        155, 180, 156, 158, 25, 179, 157, 1,
+        165, 0, 161, 164, 163, 138, 168, 4,
+        22, 171, 7, 19, 174, 10, 16, 177,
+        13, 181, 186, 191, 196, 138, 201, 203,
+        67, 259, 223, 202, 66, 204, 256, 205,
+        207, 65, 255, 206, 64, 208, 251, 209,
+        211, 63, 250, 210, 62, 212, 246, 213,
+        215, 61, 245, 214, 60, 216, 241, 217,
+        219, 59, 240, 218, 35, 226, 34, 222,
+        225, 224, 138, 229, 38, 56, 232, 41,
+        53, 235, 44, 50, 238, 47, 242, 247,
+        252, 257, 138, 262, 100, 264, 316, 265,
+        267, 99, 315, 266, 98, 268, 311, 269,
+        271, 97, 310, 270, 96, 272, 306, 273,
+        275, 95, 305, 274, 94, 276, 301, 277,
+        279, 93, 300, 278, 69, 286, 68, 282,
+        285, 284, 138, 289, 72, 90, 292, 75,
+        87, 295, 78, 84, 298, 81, 302, 307,
+        312, 317, 138, 138, 323, 325, 134, 133,
+        345, 324, 326, 378, 327, 329, 132, 377,
+        328, 131, 330, 373, 331, 333, 130, 372,
+        332, 129, 334, 368, 335, 337, 128, 367,
+        336, 127, 338, 363, 339, 341, 126, 362,
+        340, 102, 348, 101, 344, 347, 346, 138,
+        351, 105, 123, 354, 108, 120, 357, 111,
+        117, 360, 114, 364, 369, 374, 379, 135,
+        384, 385, 391, 386, 388, 136, 387, 390,
+        389, 138, 393, 137, 396, 395, 398, 397,
+        138
 };
 
 static const char _indic_syllable_machine_trans_actions[] = {
-        1, 0, 0, 2, 0, 0, 2, 0,
-        0, 2, 0, 0, 2, 0, 0, 0,
-        2, 0, 0, 2, 0, 0, 2, 0,
-        0, 2, 2, 2, 2, 2, 2, 2,
-        2, 2, 2, 2, 3, 0, 0, 2,
-        0, 0, 2, 0, 0, 2, 0, 0,
-        2, 0, 0, 0, 2, 0, 0, 2,
-        0, 0, 2, 0, 0, 2, 2, 2,
-        2, 2, 2, 2, 2, 2, 2, 2,
-        4, 0, 0, 2, 5, 0, 0, 2,
+        1, 0, 2, 0, 2, 0, 0, 2,
         0, 0, 2, 0, 0, 2, 0, 0,
         0, 2, 0, 0, 2, 0, 0, 2,
-        0, 0, 2, 2, 6, 2, 6, 2,
-        6, 2, 6, 2, 7, 0, 0, 2,
-        0, 0, 2, 0, 0, 2, 0, 0,
-        2, 0, 0, 0, 2, 0, 0, 2,
-        0, 0, 2, 0, 0, 2, 2, 2,
+        0, 0, 2, 2, 2, 2, 2, 2,
+        2, 2, 2, 2, 3, 0, 2, 0,
+        2, 0, 0, 2, 0, 0, 2, 0,
+        0, 2, 0, 0, 0, 2, 0, 0,
+        2, 0, 0, 2, 0, 0, 2, 2,
         2, 2, 2, 2, 2, 2, 2, 2,
-        6, 0, 2, 0, 2, 0, 0, 0,
-        2, 0, 0, 2, 0, 0, 0, 2,
+        4, 0, 2, 0, 2, 5, 0, 0,
+        2, 0, 0, 2, 0, 0, 2, 0,
         0, 0, 2, 0, 0, 2, 0, 0,
-        2, 8, 0, 11, 2, 2, 6, 0,
-        12, 12, 0, 2, 6, 2, 6, 2,
-        0, 13, 2, 0, 0, 2, 0, 2,
-        2, 0, 2, 2, 2, 0, 0, 2,
-        2, 0, 2, 2, 2, 0, 0, 2,
-        2, 0, 2, 2, 2, 0, 0, 2,
-        2, 0, 2, 2, 2, 0, 0, 2,
-        2, 0, 2, 0, 0, 0, 0, 14,
-        0, 2, 0, 0, 2, 0, 0, 2,
-        0, 0, 2, 0, 2, 2, 2, 2,
-        2, 2, 2, 2, 2, 15, 2, 0,
-        0, 2, 0, 2, 2, 0, 2, 2,
-        2, 0, 0, 2, 2, 0, 2, 2,
-        2, 0, 0, 2, 2, 0, 2, 2,
-        2, 0, 0, 2, 2, 0, 2, 2,
-        2, 0, 0, 2, 2, 0, 2, 0,
-        0, 0, 0, 16, 0, 2, 0, 0,
+        2, 0, 0, 2, 6, 2, 6, 2,
+        6, 2, 6, 2, 7, 0, 2, 0,
         2, 0, 0, 2, 0, 0, 2, 0,
+        0, 2, 0, 0, 0, 2, 0, 0,
+        2, 0, 0, 2, 0, 0, 2, 2,
         2, 2, 2, 2, 2, 2, 2, 2,
-        2, 17, 6, 0, 6, 6, 6, 0,
-        0, 6, 6, 0, 6, 6, 6, 0,
-        0, 6, 6, 0, 6, 6, 6, 0,
-        0, 6, 6, 0, 6, 6, 6, 0,
-        0, 6, 6, 0, 6, 0, 0, 0,
-        0, 18, 0, 2, 0, 0, 2, 0,
-        0, 2, 0, 0, 2, 0, 2, 2,
-        2, 2, 2, 2, 2, 2, 2, 19,
-        20, 2, 0, 0, 0, 0, 2, 2,
+        6, 8, 0, 11, 2, 2, 6, 0,
+        12, 12, 0, 2, 6, 2, 2, 0,
+        13, 2, 0, 0, 2, 0, 2, 0,
         2, 2, 2, 0, 0, 2, 2, 0,
         2, 2, 2, 0, 0, 2, 2, 0,
         2, 2, 2, 0, 0, 2, 2, 0,
         2, 2, 2, 0, 0, 2, 2, 0,
-        2, 0, 0, 0, 0, 21, 0, 2,
-        0, 0, 2, 0, 0, 2, 0, 0,
-        2, 0, 2, 2, 2, 2, 2, 2,
-        2, 2, 2, 0, 0, 22, 2, 0,
-        0, 0, 0, 0, 0, 2, 0, 0,
+        2, 0, 0, 0, 0, 14, 2, 0,
+        0, 2, 0, 0, 2, 0, 0, 2,
+        0, 2, 2, 2, 2, 15, 2, 0,
+        0, 2, 0, 2, 0, 2, 2, 2,
+        0, 0, 2, 2, 0, 2, 2, 2,
+        0, 0, 2, 2, 0, 2, 2, 2,
+        0, 0, 2, 2, 0, 2, 2, 2,
+        0, 0, 2, 2, 0, 2, 0, 0,
+        0, 0, 16, 2, 0, 0, 2, 0,
+        0, 2, 0, 0, 2, 0, 2, 2,
+        2, 2, 17, 6, 0, 6, 2, 6,
+        0, 0, 6, 6, 0, 6, 2, 6,
+        0, 0, 6, 6, 0, 6, 2, 6,
+        0, 0, 6, 6, 0, 6, 2, 6,
+        0, 0, 6, 6, 0, 2, 0, 0,
+        0, 0, 18, 2, 0, 0, 2, 0,
+        0, 2, 0, 0, 2, 0, 2, 2,
+        2, 2, 19, 20, 2, 0, 0, 0,
+        0, 2, 2, 2, 2, 0, 0, 2,
+        2, 0, 2, 2, 2, 0, 0, 2,
+        2, 0, 2, 2, 2, 0, 0, 2,
+        2, 0, 2, 2, 2, 0, 0, 2,
+        2, 0, 2, 0, 0, 0, 0, 21,
         2, 0, 0, 2, 0, 0, 2, 0,
+        0, 2, 0, 2, 2, 2, 2, 0,
+        0, 22, 22, 0, 0, 0, 0, 0,
         0, 23, 2, 0, 0, 0, 0, 0,
         24
 };
@@ -937,15 +759,7 @@
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 9, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 9, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
@@ -998,15 +812,7 @@
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 10, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 10, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
@@ -1046,67 +852,59 @@
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 37, 37, 37, 37, 37,
+        1, 1, 37, 37, 37, 37, 37, 37,
         37, 37, 37, 37, 37, 37, 37, 37,
         37, 37, 37, 37, 37, 37, 37, 37,
         37, 37, 37, 37, 37, 37, 37, 37,
-        37, 37, 37, 37, 37, 37, 73, 73,
-        77, 77, 73, 73, 73, 73, 73, 73,
+        37, 37, 37, 37, 73, 73, 78, 78,
         73, 73, 73, 73, 73, 73, 73, 73,
         73, 73, 73, 73, 73, 73, 73, 73,
         73, 73, 73, 73, 73, 73, 73, 73,
-        109, 109, 109, 109, 109, 109, 109, 109,
+        73, 73, 73, 73, 73, 109, 109, 109,
         109, 109, 109, 109, 109, 109, 109, 109,
         109, 109, 109, 109, 109, 109, 109, 109,
         109, 109, 109, 109, 109, 109, 109, 109,
-        109, 109, 109, 73, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 170, 0, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 322, 322, 322,
-        322, 322, 322, 322, 322, 322, 322, 322,
-        322, 322, 322, 322, 322, 322, 322, 322,
-        322, 322, 322, 322, 322, 322, 322, 322,
-        322, 322, 322, 322, 322, 322, 322, 322,
-        322, 322, 322, 322, 322, 322, 322, 322,
-        322, 322, 322, 322, 322, 322, 322, 322,
-        322, 322, 322, 322, 322, 322, 322, 322,
-        322, 322, 322, 322, 322, 384, 322, 384,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 322, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        474, 474, 474, 474, 474, 474, 474, 384
+        109, 109, 109, 109, 109, 109, 109, 73,
+        1, 146, 0, 161, 161, 161, 161, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        222, 222, 222, 222, 222, 222, 222, 222,
+        222, 222, 222, 222, 222, 222, 222, 222,
+        222, 222, 222, 222, 222, 222, 222, 222,
+        222, 222, 222, 222, 222, 222, 222, 222,
+        222, 222, 222, 222, 222, 222, 222, 222,
+        222, 222, 222, 222, 222, 222, 222, 222,
+        222, 222, 222, 222, 222, 222, 222, 222,
+        222, 222, 222, 222, 222, 283, 283, 283,
+        283, 283, 283, 283, 283, 283, 283, 283,
+        283, 283, 283, 283, 283, 283, 283, 283,
+        283, 283, 283, 283, 283, 283, 283, 283,
+        283, 283, 283, 283, 283, 283, 283, 283,
+        283, 283, 283, 283, 283, 283, 283, 283,
+        283, 283, 283, 283, 283, 283, 283, 283,
+        283, 283, 283, 283, 283, 283, 283, 339,
+        283, 339, 340, 340, 340, 340, 340, 340,
+        340, 340, 340, 340, 340, 340, 340, 340,
+        340, 340, 340, 340, 340, 340, 340, 340,
+        340, 340, 340, 340, 340, 340, 340, 340,
+        340, 340, 340, 340, 340, 340, 340, 340,
+        340, 340, 340, 340, 340, 340, 340, 340,
+        340, 340, 340, 340, 340, 340, 340, 340,
+        340, 340, 340, 340, 340, 340, 283, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        410, 410, 410, 410, 410, 410, 410, 339
 };
 
-static const int indic_syllable_machine_start = 166;
-static const int indic_syllable_machine_first_final = 166;
+static const int indic_syllable_machine_start = 138;
+static const int indic_syllable_machine_first_final = 138;
 static const int indic_syllable_machine_error = -1;
 
-static const int indic_syllable_machine_en_main = 166;
+static const int indic_syllable_machine_en_main = 138;
 
 
 #line 36 "hb-ot-shape-complex-indic-machine.rl"
@@ -1118,10 +916,9 @@
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -1129,11 +926,11 @@
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
 
-#line 1137 "hb-ot-shape-complex-indic-machine.hh"
+#line 934 "hb-ot-shape-complex-indic-machine.hh"
         {
         cs = indic_syllable_machine_start;
         ts = 0;
@@ -1141,16 +938,15 @@
         act = 0;
         }
 
-#line 113 "hb-ot-shape-complex-indic-machine.rl"
+#line 112 "hb-ot-shape-complex-indic-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
 
-#line 1154 "hb-ot-shape-complex-indic-machine.hh"
+#line 950 "hb-ot-shape-complex-indic-machine.hh"
         {
         int _slen;
         int _trans;
@@ -1164,7 +960,7 @@
 #line 1 "NONE"
         {ts = p;}
         break;
-#line 1168 "hb-ot-shape-complex-indic-machine.hh"
+#line 964 "hb-ot-shape-complex-indic-machine.hh"
         }
 
         _keys = _indic_syllable_machine_trans_keys + (cs<<1);
@@ -1287,7 +1083,7 @@
 #line 88 "hb-ot-shape-complex-indic-machine.rl"
         {act = 6;}
         break;
-#line 1291 "hb-ot-shape-complex-indic-machine.hh"
+#line 1087 "hb-ot-shape-complex-indic-machine.hh"
         }
 
 _again:
@@ -1296,7 +1092,7 @@
 #line 1 "NONE"
         {ts = 0;}
         break;
-#line 1300 "hb-ot-shape-complex-indic-machine.hh"
+#line 1096 "hb-ot-shape-complex-indic-machine.hh"
         }
 
         if ( ++p != pe )
@@ -1312,7 +1108,7 @@
 
         }
 
-#line 122 "hb-ot-shape-complex-indic-machine.rl"
+#line 120 "hb-ot-shape-complex-indic-machine.rl"
 
 }
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,401 +0,0 @@
-/*
- * Copyright © 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-#include "hb-ot-shape-complex-private.hh"
-#include "hb-ot-shape-private.hh" /* XXX Remove */
-
-
-/* buffer var allocations */
-#define indic_category() complex_var_u8_0() /* indic_category_t */
-#define indic_position() complex_var_u8_1() /* indic_position_t */
-
-
-#define INDIC_TABLE_ELEMENT_TYPE uint16_t
-
-/* Cateories used in the OpenType spec:
- * https://docs.microsoft.com/en-us/typography/script-development/devanagari
- */
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum indic_category_t {
-  OT_X = 0,
-  OT_C = 1,
-  OT_V = 2,
-  OT_N = 3,
-  OT_H = 4,
-  OT_ZWNJ = 5,
-  OT_ZWJ = 6,
-  OT_M = 7,
-  OT_SM = 8,
-  /* OT_VD = 9, UNUSED; we use OT_A instead. */
-  OT_A = 10,
-  OT_PLACEHOLDER = 11,
-  OT_DOTTEDCIRCLE = 12,
-  OT_RS = 13, /* Register Shifter, used in Khmer OT spec. */
-  OT_Coeng = 14, /* Khmer-style Virama. */
-  OT_Repha = 15, /* Atomically-encoded logical or visual repha. */
-  OT_Ra = 16,
-  OT_CM = 17,  /* Consonant-Medial. */
-  OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
-  OT_CS = 19
-};
-
-#define MEDIAL_FLAGS (FLAG (OT_CM))
-
-/* Note:
- *
- * We treat Vowels and placeholders as if they were consonants.  This is safe because Vowels
- * cannot happen in a consonant syllable.  The plus side however is, we can call the
- * consonant syllable logic from the vowel syllable function and get it all right! */
-#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CS) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE))
-#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
-
-
-/* Visual positions in a syllable from left to right. */
-enum indic_position_t {
-  POS_START = 0,
-
-  POS_RA_TO_BECOME_REPH = 1,
-  POS_PRE_M = 2,
-  POS_PRE_C = 3,
-
-  POS_BASE_C = 4,
-  POS_AFTER_MAIN = 5,
-
-  POS_ABOVE_C = 6,
-
-  POS_BEFORE_SUB = 7,
-  POS_BELOW_C = 8,
-  POS_AFTER_SUB = 9,
-
-  POS_BEFORE_POST = 10,
-  POS_POST_C = 11,
-  POS_AFTER_POST = 12,
-
-  POS_FINAL_C = 13,
-  POS_SMVD = 14,
-
-  POS_END = 15
-};
-
-/* Categories used in IndicSyllabicCategory.txt from UCD. */
-enum indic_syllabic_category_t {
-  INDIC_SYLLABIC_CATEGORY_OTHER                         = OT_X,
-
-  INDIC_SYLLABIC_CATEGORY_AVAGRAHA                      = OT_Symbol,
-  INDIC_SYLLABIC_CATEGORY_BINDU                         = OT_SM,
-  INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER         = OT_PLACEHOLDER, /* Don't care. */
-  INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK             = OT_A,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT                     = OT_C,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD                = OT_C,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL               = OT_CM,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER         = OT_C,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER              = OT_M, /* U+17CD only. */
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL              = OT_CM,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER         = OT_PLACEHOLDER,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA     = OT_Repha,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED            = OT_X, /* Don't care. */
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED           = OT_CM,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA    = OT_N,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER        = OT_CS,
-  INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK               = OT_SM, /* https://github.com/harfbuzz/harfbuzz/issues/552 */
-  INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER             = OT_Coeng,
-  INDIC_SYLLABIC_CATEGORY_JOINER                        = OT_ZWJ,
-  INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER              = OT_X,
-  INDIC_SYLLABIC_CATEGORY_NON_JOINER                    = OT_ZWNJ,
-  INDIC_SYLLABIC_CATEGORY_NUKTA                         = OT_N,
-  INDIC_SYLLABIC_CATEGORY_NUMBER                        = OT_PLACEHOLDER,
-  INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER                 = OT_PLACEHOLDER, /* Don't care. */
-  INDIC_SYLLABIC_CATEGORY_PURE_KILLER                   = OT_M, /* Is like a vowel matra. */
-  INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER              = OT_RS,
-  INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER             = OT_SM,
-  INDIC_SYLLABIC_CATEGORY_TONE_LETTER                   = OT_X,
-  INDIC_SYLLABIC_CATEGORY_TONE_MARK                     = OT_N,
-  INDIC_SYLLABIC_CATEGORY_VIRAMA                        = OT_H,
-  INDIC_SYLLABIC_CATEGORY_VISARGA                       = OT_SM,
-  INDIC_SYLLABIC_CATEGORY_VOWEL                         = OT_V,
-  INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT               = OT_M,
-  INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT             = OT_V
-};
-
-/* Categories used in IndicSMatraCategory.txt from UCD */
-enum indic_matra_category_t {
-  INDIC_MATRA_CATEGORY_NOT_APPLICABLE                   = POS_END,
-
-  INDIC_MATRA_CATEGORY_LEFT                             = POS_PRE_C,
-  INDIC_MATRA_CATEGORY_TOP                              = POS_ABOVE_C,
-  INDIC_MATRA_CATEGORY_BOTTOM                           = POS_BELOW_C,
-  INDIC_MATRA_CATEGORY_RIGHT                            = POS_POST_C,
-
-  /* These should resolve to the position of the last part of the split sequence. */
-  INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT                 = INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT                   = INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM                   = INDIC_MATRA_CATEGORY_BOTTOM,
-  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT         = INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_TOP_AND_LEFT                     = INDIC_MATRA_CATEGORY_TOP,
-  INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT           = INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_TOP_AND_RIGHT                    = INDIC_MATRA_CATEGORY_RIGHT,
-
-  INDIC_MATRA_CATEGORY_OVERSTRUCK                       = POS_AFTER_MAIN,
-  INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT                = POS_PRE_M
-};
-
-#define INDIC_COMBINE_CATEGORIES(S,M) \
-  ( \
-    ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
-    ( S | \
-     ( \
-      ( \
-       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
-       S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
-       S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
-       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
-       S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
-       S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
-       false \
-       ? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \
-      ) << 8 \
-     ) \
-    ) \
-   )
-
-HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE
-hb_indic_get_categories (hb_codepoint_t u);
-
-
-static inline bool
-is_one_of (const hb_glyph_info_t &info, unsigned int flags)
-{
-  /* If it ligated, all bets are off. */
-  if (_hb_glyph_info_ligated (&info)) return false;
-  return !!(FLAG_UNSAFE (info.indic_category()) & flags);
-}
-
-static inline bool
-is_joiner (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, JOINER_FLAGS);
-}
-
-static inline bool
-is_consonant (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, CONSONANT_FLAGS);
-}
-
-static inline bool
-is_halant (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, FLAG (OT_H));
-}
-
-#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base))
-
-#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u))
-#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u))
-#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u))
-#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u))
-#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u))
-#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u))
-#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u))
-#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u))
-#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u))
-#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u))
-
-
-#define MATRA_POS_LEFT(u)       POS_PRE_M
-#define MATRA_POS_RIGHT(u)      ( \
-                                  IS_DEVA(u) ? POS_AFTER_SUB  : \
-                                  IS_BENG(u) ? POS_AFTER_POST : \
-                                  IS_GURU(u) ? POS_AFTER_POST : \
-                                  IS_GUJR(u) ? POS_AFTER_POST : \
-                                  IS_ORYA(u) ? POS_AFTER_POST : \
-                                  IS_TAML(u) ? POS_AFTER_POST : \
-                                  IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
-                                  IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
-                                  IS_MLYM(u) ? POS_AFTER_POST : \
-                                  IS_SINH(u) ? POS_AFTER_SUB  : \
-                                  /*default*/  POS_AFTER_SUB    \
-                                )
-#define MATRA_POS_TOP(u)        ( /* BENG and MLYM don't have top matras. */ \
-                                  IS_DEVA(u) ? POS_AFTER_SUB  : \
-                                  IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \
-                                  IS_GUJR(u) ? POS_AFTER_SUB  : \
-                                  IS_ORYA(u) ? POS_AFTER_MAIN : \
-                                  IS_TAML(u) ? POS_AFTER_SUB  : \
-                                  IS_TELU(u) ? POS_BEFORE_SUB : \
-                                  IS_KNDA(u) ? POS_BEFORE_SUB : \
-                                  IS_SINH(u) ? POS_AFTER_SUB  : \
-                                  /*default*/  POS_AFTER_SUB    \
-                                )
-#define MATRA_POS_BOTTOM(u)     ( \
-                                  IS_DEVA(u) ? POS_AFTER_SUB  : \
-                                  IS_BENG(u) ? POS_AFTER_SUB  : \
-                                  IS_GURU(u) ? POS_AFTER_POST : \
-                                  IS_GUJR(u) ? POS_AFTER_POST : \
-                                  IS_ORYA(u) ? POS_AFTER_SUB  : \
-                                  IS_TAML(u) ? POS_AFTER_POST : \
-                                  IS_TELU(u) ? POS_BEFORE_SUB : \
-                                  IS_KNDA(u) ? POS_BEFORE_SUB : \
-                                  IS_MLYM(u) ? POS_AFTER_POST : \
-                                  IS_SINH(u) ? POS_AFTER_SUB  : \
-                                  /*default*/  POS_AFTER_SUB    \
-                                )
-
-static inline indic_position_t
-matra_position_indic (hb_codepoint_t u, indic_position_t side)
-{
-  switch ((int) side)
-  {
-    case POS_PRE_C:     return MATRA_POS_LEFT (u);
-    case POS_POST_C:    return MATRA_POS_RIGHT (u);
-    case POS_ABOVE_C:   return MATRA_POS_TOP (u);
-    case POS_BELOW_C:   return MATRA_POS_BOTTOM (u);
-  };
-  return side;
-}
-
-/* XXX
- * This is a hack for now.  We should move this data into the main Indic table.
- * Or completely remove it and just check in the tables.
- */
-static const hb_codepoint_t ra_chars[] = {
-  0x0930u, /* Devanagari */
-  0x09B0u, /* Bengali */
-  0x09F0u, /* Bengali */
-  0x0A30u, /* Gurmukhi */       /* No Reph */
-  0x0AB0u, /* Gujarati */
-  0x0B30u, /* Oriya */
-  0x0BB0u, /* Tamil */          /* No Reph */
-  0x0C30u, /* Telugu */         /* Reph formed only with ZWJ */
-  0x0CB0u, /* Kannada */
-  0x0D30u, /* Malayalam */      /* No Reph, Logical Repha */
-
-  0x0DBBu, /* Sinhala */                /* Reph formed only with ZWJ */
-};
-
-static inline bool
-is_ra (hb_codepoint_t u)
-{
-  for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++)
-    if (u == ra_chars[i])
-      return true;
-  return false;
-}
-
-static inline void
-set_indic_properties (hb_glyph_info_t &info)
-{
-  hb_codepoint_t u = info.codepoint;
-  unsigned int type = hb_indic_get_categories (u);
-  indic_category_t cat = (indic_category_t) (type & 0x7Fu);
-  indic_position_t pos = (indic_position_t) (type >> 8);
-
-
-  /*
-   * Re-assign category
-   */
-
-  /* The following act more like the Bindus. */
-  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0953u, 0x0954u)))
-    cat = OT_SM;
-  /* The following act like consonants. */
-  else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x0A72u, 0x0A73u,
-                                      0x1CF5u, 0x1CF6u)))
-    cat = OT_C;
-  /* TODO: The following should only be allowed after a Visarga.
-   * For now, just treat them like regular tone marks. */
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1CE2u, 0x1CE8u)))
-    cat = OT_A;
-  /* TODO: The following should only be allowed after some of
-   * the nasalization marks, maybe only for U+1CE9..U+1CF1.
-   * For now, just treat them like tone marks. */
-  else if (unlikely (u == 0x1CEDu))
-    cat = OT_A;
-  /* The following take marks in standalone clusters, similar to Avagraha. */
-  else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0xA8F2u, 0xA8F7u,
-                                      0x1CE9u, 0x1CECu,
-                                      0x1CEEu, 0x1CF1u)))
-  {
-    cat = OT_Symbol;
-    static_assert (((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol), "");
-  }
-  else if (unlikely (u == 0x0A51u))
-  {
-    /* https://github.com/harfbuzz/harfbuzz/issues/524 */
-    cat = OT_M;
-    pos = POS_BELOW_C;
-  }
-
-  /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
-   * so the Indic shaper needs to know their categories. */
-  else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM;
-  else if (unlikely (u == 0x1133cu)) cat = OT_N;
-
-  else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */
-
-  else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
-  else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
-                                    cat = OT_PLACEHOLDER;
-  else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
-
-
-  /*
-   * Re-assign position.
-   */
-
-  if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
-  {
-    pos = POS_BASE_C;
-    if (is_ra (u))
-      cat = OT_Ra;
-  }
-  else if (cat == OT_M)
-  {
-    pos = matra_position_indic (u, pos);
-  }
-  else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) /* | FLAG (OT_VD) */ | FLAG (OT_A) | FLAG (OT_Symbol))))
-  {
-    pos = POS_SMVD;
-  }
-
-  if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
-
-
-
-  info.indic_category() = cat;
-  info.indic_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-table.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-table.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -14,8 +14,10 @@
  * # Date: 2017-10-16, 24:39:00 GMT [KW]
  */
 
-#include "hb-ot-shape-complex-indic-private.hh"
+#include "hb-ot-shape-complex-indic.hh"
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
 
 #define ISC_A   INDIC_SYLLABIC_CATEGORY_AVAGRAHA                /*  16 chars; Avagraha */
 #define ISC_Bi  INDIC_SYLLABIC_CATEGORY_BINDU                   /*  83 chars; Bindu */
@@ -69,6 +71,7 @@
 #define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT     /*   4 chars; Top_And_Left_And_Right */
 #define IMC_TR  INDIC_MATRA_CATEGORY_TOP_AND_RIGHT              /*  13 chars; Top_And_Right */
 #define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT          /*  19 chars; Visual_Order_Left */
+#pragma GCC diagnostic pop
 
 #define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,8 +24,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-indic-private.hh"
-#include "hb-ot-layout-private.hh"
+#include "hb-ot-shape-complex-indic.hh"
+#include "hb-ot-shape-complex-vowel-constraints.hh"
+#include "hb-ot-layout.hh"
 
 
 /*
@@ -95,42 +96,41 @@
  * Indic shaper.
  */
 
-struct feature_list_t {
-  hb_tag_t tag;
-  hb_ot_map_feature_flags_t flags;
-};
-
-static const feature_list_t
+static const hb_ot_map_feature_t
 indic_features[] =
 {
   /*
    * Basic features.
    * These features are applied in order, one at a time, after initial_reordering.
    */
-  {HB_TAG('n','u','k','t'), F_GLOBAL},
-  {HB_TAG('a','k','h','n'), F_GLOBAL},
-  {HB_TAG('r','p','h','f'), F_NONE},
-  {HB_TAG('r','k','r','f'), F_GLOBAL},
-  {HB_TAG('p','r','e','f'), F_NONE},
-  {HB_TAG('b','l','w','f'), F_NONE},
-  {HB_TAG('a','b','v','f'), F_NONE},
-  {HB_TAG('h','a','l','f'), F_NONE},
-  {HB_TAG('p','s','t','f'), F_NONE},
-  {HB_TAG('v','a','t','u'), F_GLOBAL},
-  {HB_TAG('c','j','c','t'), F_GLOBAL},
+  {HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('r','p','h','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('r','k','r','f'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('p','r','e','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('b','l','w','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('a','b','v','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('h','a','l','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('p','s','t','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('v','a','t','u'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS},
   /*
    * Other features.
-   * These features are applied all at once, after final_reordering.
+   * These features are applied all at once, after final_reordering
+   * but before clearing syllables.
    * Default Bengali font in Windows for example has intermixed
    * lookups for init,pres,abvs,blws features.
    */
-  {HB_TAG('i','n','i','t'), F_NONE},
-  {HB_TAG('p','r','e','s'), F_GLOBAL},
-  {HB_TAG('a','b','v','s'), F_GLOBAL},
-  {HB_TAG('b','l','w','s'), F_GLOBAL},
-  {HB_TAG('p','s','t','s'), F_GLOBAL},
-  {HB_TAG('h','a','l','n'), F_GLOBAL},
-  /* Positioning features, though we don't care about the types. */
+  {HB_TAG('i','n','i','t'),        F_MANUAL_JOINERS},
+  {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS},
+  /*
+   * Positioning features.
+   * We don't care about the types.
+   */
   {HB_TAG('d','i','s','t'), F_GLOBAL},
   {HB_TAG('a','b','v','m'), F_GLOBAL},
   {HB_TAG('b','l','w','m'), F_GLOBAL},
@@ -158,12 +158,13 @@
   _BLWS,
   _PSTS,
   _HALN,
+
   _DIST,
   _ABVM,
   _BLWM,
 
   INDIC_NUM_FEATURES,
-  INDIC_BASIC_FEATURES = INIT /* Don't forget to update this! */
+  INDIC_BASIC_FEATURES = INIT, /* Don't forget to update this! */
 };
 
 static void
@@ -191,25 +192,27 @@
   /* Do this before any lookups have been applied. */
   map->add_gsub_pause (setup_syllables);
 
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('l','o','c','l'));
   /* The Indic specs do not require ccmp, but we apply it here since if
    * there is a use of it, it's typically at the beginning. */
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
 
 
   unsigned int i = 0;
   map->add_gsub_pause (initial_reordering);
+
   for (; i < INDIC_BASIC_FEATURES; i++) {
-    map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
+    map->add_feature (indic_features[i]);
     map->add_gsub_pause (nullptr);
   }
+
   map->add_gsub_pause (final_reordering);
-  for (; i < INDIC_NUM_FEATURES; i++) {
-    map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-  }
 
-  map->add_global_bool_feature (HB_TAG('c','a','l','t'));
-  map->add_global_bool_feature (HB_TAG('c','l','i','g'));
+  for (; i < INDIC_NUM_FEATURES; i++)
+    map->add_feature (indic_features[i]);
+
+  map->enable_feature (HB_TAG('c','a','l','t'));
+  map->enable_feature (HB_TAG('c','l','i','g'));
 
   map->add_gsub_pause (clear_syllables);
 }
@@ -217,13 +220,13 @@
 static void
 override_features_indic (hb_ot_shape_planner_t *plan)
 {
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
+  plan->map.disable_feature (HB_TAG('l','i','g','a'));
 }
 
 
 struct would_substitute_feature_t
 {
-  inline void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
+  void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
   {
     zero_context = zero_context_;
     map->get_stage_lookups (0/*GSUB*/,
@@ -231,9 +234,9 @@
                             &lookups, &count);
   }
 
-  inline bool would_substitute (const hb_codepoint_t *glyphs,
-                                unsigned int          glyphs_count,
-                                hb_face_t            *face) const
+  bool would_substitute (const hb_codepoint_t *glyphs,
+                         unsigned int          glyphs_count,
+                         hb_face_t            *face) const
   {
     for (unsigned int i = 0; i < count; i++)
       if (hb_ot_layout_lookup_would_substitute_fast (face, lookups[i].index, glyphs, glyphs_count, zero_context))
@@ -249,12 +252,10 @@
 
 struct indic_shape_plan_t
 {
-  ASSERT_POD ();
-
-  inline bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
+  bool load_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
   {
-    hb_codepoint_t glyph = virama_glyph;
-    if (unlikely (virama_glyph == (hb_codepoint_t) -1))
+    hb_codepoint_t glyph = virama_glyph.get_relaxed ();
+    if (unlikely (glyph == (hb_codepoint_t) -1))
     {
       if (!config->virama || !font->get_nominal_glyph (config->virama, &glyph))
         glyph = 0;
@@ -262,8 +263,8 @@
        * Maybe one day... */
 
       /* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
-       * during shape planning...  Instead, overwrite it here.  It's safe.  Don't worry! */
-      virama_glyph = glyph;
+       * during shape planning...  Instead, overwrite it here. */
+      virama_glyph.set_relaxed ((int) glyph);
     }
 
     *pglyph = glyph;
@@ -273,7 +274,8 @@
   const indic_config_t *config;
 
   bool is_old_spec;
-  mutable hb_codepoint_t virama_glyph;
+  bool uniscribe_bug_compatible;
+  mutable hb_atomic_int_t virama_glyph;
 
   would_substitute_feature_t rphf;
   would_substitute_feature_t pref;
@@ -298,7 +300,8 @@
     }
 
   indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
-  indic_plan->virama_glyph = (hb_codepoint_t) -1;
+  indic_plan->uniscribe_bug_compatible = hb_options ().uniscribe_bug_compatible;
+  indic_plan->virama_glyph.set_relaxed (-1);
 
   /* Use zero-context would_substitute() matching for new-spec of the main
    * Indic scripts, and scripts with one spec only, but not for old-specs.
@@ -419,7 +422,7 @@
     return;
 
   hb_codepoint_t virama;
-  if (indic_plan->get_virama_glyph (font, &virama))
+  if (indic_plan->load_virama_glyph (font, &virama))
   {
     hb_face_t *face = font->face;
     unsigned int count = buffer->len;
@@ -667,10 +670,10 @@
    * last consonant.
    *
    * Reports suggest that in some scripts Uniscribe does this only if there
-   * is *not* a Halant after last consonant already (eg. Kannada), while it
-   * does it unconditionally in other scripts (eg. Malayalam, Bengali).  We
-   * don't currently know about other scripts, so we whitelist Malayalam and
-   * Bengali for now.
+   * is *not* a Halant after last consonant already.  We know that is the
+   * case for Kannada, while it reorders unconditionally in other scripts,
+   * eg. Malayalam, Bengali, and Devanagari.  We don't currently know about
+   * other scripts, so we blacklist Kannada.
    *
    * Kannada test case:
    * U+0C9A,U+0CCD,U+0C9A,U+0CCD
@@ -681,15 +684,19 @@
    * U+0D38,U+0D4D,U+0D31,U+0D4D,U+0D31,U+0D4D
    * With lohit-ttf-20121122/Lohit-Malayalam.ttf
    *
-   * Bengali test case
+   * Bengali test case:
    * U+0998,U+09CD,U+09AF,U+09CD
    * With Windows XP vrinda.ttf
    * https://github.com/harfbuzz/harfbuzz/issues/1073
+   *
+   * Devanagari test case:
+   * U+091F,U+094D,U+0930,U+094D
+   * With chandas.ttf
+   * https://github.com/harfbuzz/harfbuzz/issues/1071
    */
   if (indic_plan->is_old_spec)
   {
-    bool disallow_double_halants = buffer->props.script != HB_SCRIPT_MALAYALAM &&
-                                   buffer->props.script != HB_SCRIPT_BENGALI;
+    bool disallow_double_halants = buffer->props.script == HB_SCRIPT_KANNADA;
     for (unsigned int i = base + 1; i < end; i++)
       if (info[i].indic_category() == OT_H)
       {
@@ -713,7 +720,7 @@
     indic_position_t last_pos = POS_START;
     for (unsigned int i = start; i < end; i++)
     {
-      if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_H))))
+      if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | FLAG (OT_H))))
       {
         info[i].indic_position() = last_pos;
         if (unlikely (info[i].indic_category() == OT_H &&
@@ -779,8 +786,10 @@
      *
      * We could use buffer->sort() for this, if there was no special
      * reordering of pre-base stuff happening later...
+     * We don't want to merge_clusters all of that, which buffer->sort()
+     * would.
      */
-    if (indic_plan->is_old_spec || end - base > 127)
+    if (indic_plan->is_old_spec || end - start > 127)
       buffer->merge_clusters (base, end);
     else
     {
@@ -909,10 +918,12 @@
                                        hb_buffer_t *buffer,
                                        unsigned int start, unsigned int end)
 {
+  const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
+
   /* We treat placeholder/dotted-circle as if they are consonants, so we
    * should just chain.  Only if not in compatibility mode that is... */
 
-  if (hb_options ().uniscribe_bug_compatible)
+  if (indic_plan->uniscribe_bug_compatible)
   {
     /* For dotted-circle, this is what Uniscribe does:
      * If dotted-circle is the last glyph, it just does nothing.
@@ -954,7 +965,8 @@
                        hb_font_t *font,
                        hb_buffer_t *buffer)
 {
-  /* Note: This loop is extra overhead, but should not be measurable. */
+  /* Note: This loop is extra overhead, but should not be measurable.
+   * TODO Use a buffer scratch flag to remove the loop. */
   bool has_broken_syllables = false;
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
@@ -1006,7 +1018,6 @@
     else
       buffer->next_glyph ();
   }
-
   buffer->swap_buffers ();
 }
 
@@ -1036,9 +1047,11 @@
    * phase, and that might have messed up our properties.  Recover
    * from a particular case of that where we're fairly sure that a
    * class of OT_H is desired but has been lost. */
-  if (indic_plan->virama_glyph)
+  /* We don't call load_virama_glyph(), since we know it's already
+   * loaded. */
+  hb_codepoint_t virama_glyph = indic_plan->virama_glyph.get_relaxed ();
+  if (virama_glyph)
   {
-    unsigned int virama_glyph = indic_plan->virama_glyph;
     for (unsigned int i = start; i < end; i++)
       if (info[i].codepoint == virama_glyph &&
           _hb_glyph_info_ligated (&info[i]) &&
@@ -1127,6 +1140,24 @@
    *     defined as “after last standalone halant glyph, after initial matra
    *     position and before the main consonant”. If ZWJ or ZWNJ follow this
    *     halant, position is moved after it.
+   *
+   * IMPLEMENTATION NOTES:
+   *
+   * It looks like the last sentence is wrong.  Testing, with Windows 7 Uniscribe
+   * and Devanagari shows that the behavior is best described as:
+   *
+   * "If ZWJ follows this halant, matra is NOT repositioned after this halant.
+   *  If ZWNJ follows this halant, position is moved after it."
+   *
+   * Test case, with Adobe Devanagari or Nirmala UI:
+   *
+   *   U+091F,U+094D,U+200C,U+092F,U+093F
+   *   (Matra moves to the middle, after ZWNJ.)
+   *
+   *   U+091F,U+094D,U+200D,U+092F,U+093F
+   *   (Matra does NOT move, stays to the left.)
+   *
+   * https://github.com/harfbuzz/harfbuzz/issues/1070
    */
 
   if (start + 1 < end && start < base) /* Otherwise there can't be any pre-base matra characters. */
@@ -1140,6 +1171,7 @@
      */
     if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL)
     {
+    search:
       while (new_pos > start &&
              !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_H)))))
         new_pos--;
@@ -1150,9 +1182,27 @@
       if (is_halant (info[new_pos]) &&
           info[new_pos].indic_position() != POS_PRE_M)
       {
+#if 0 // See comment above
         /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
         if (new_pos + 1 < end && is_joiner (info[new_pos + 1]))
           new_pos++;
+#endif
+        if (new_pos + 1 < end)
+        {
+          /* -> If ZWJ follows this halant, matra is NOT repositioned after this halant. */
+          if (info[new_pos + 1].indic_category() == OT_ZWJ)
+          {
+            /* Keep searching. */
+            if (new_pos > start)
+            {
+              new_pos--;
+              goto search;
+            }
+          }
+          /* -> If ZWNJ follows this halant, position is moved after it. */
+          if (info[new_pos + 1].indic_category() == OT_ZWNJ)
+            new_pos++;
+        }
       }
       else
         new_pos = start; /* No move. */
@@ -1313,7 +1363,7 @@
        * Uniscribe doesn't do this.
        * TEST: U+0930,U+094D,U+0915,U+094B,U+094D
        */
-      if (!hb_options ().uniscribe_bug_compatible &&
+      if (!indic_plan->uniscribe_bug_compatible &&
           unlikely (is_halant (info[new_reph_pos]))) {
         for (unsigned int i = base + 1; i < new_reph_pos; i++)
           if (info[i].indic_category() == OT_M) {
@@ -1419,7 +1469,7 @@
   /*
    * Finish off the clusters and go home!
    */
-  if (hb_options ().uniscribe_bug_compatible)
+  if (indic_plan->uniscribe_bug_compatible)
   {
     switch ((hb_tag_t) plan->props.script)
     {
@@ -1467,6 +1517,14 @@
 }
 
 
+static void
+preprocess_text_indic (const hb_ot_shape_plan_t *plan,
+                       hb_buffer_t              *buffer,
+                       hb_font_t                *font)
+{
+  _hb_preprocess_text_vowel_constraints (plan, buffer, font);
+}
+
 static bool
 decompose_indic (const hb_ot_shape_normalize_context_t *c,
                  hb_codepoint_t  ab,
@@ -1566,13 +1624,13 @@
   override_features_indic,
   data_create_indic,
   data_destroy_indic,
-  nullptr, /* preprocess_text */
+  preprocess_text_indic,
   nullptr, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
   decompose_indic,
   compose_indic,
   setup_masks_indic,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,399 @@
+/*
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_INDIC_HH
+#define HB_OT_SHAPE_COMPLEX_INDIC_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex.hh"
+
+
+/* buffer var allocations */
+#define indic_category() complex_var_u8_0() /* indic_category_t */
+#define indic_position() complex_var_u8_1() /* indic_position_t */
+
+
+#define INDIC_TABLE_ELEMENT_TYPE uint16_t
+
+/* Cateories used in the OpenType spec:
+ * https://docs.microsoft.com/en-us/typography/script-development/devanagari
+ */
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum indic_category_t {
+  OT_X = 0,
+  OT_C = 1,
+  OT_V = 2,
+  OT_N = 3,
+  OT_H = 4,
+  OT_ZWNJ = 5,
+  OT_ZWJ = 6,
+  OT_M = 7,
+  OT_SM = 8,
+  /* OT_VD = 9, UNUSED; we use OT_A instead. */
+  OT_A = 10,
+  OT_PLACEHOLDER = 11,
+  OT_DOTTEDCIRCLE = 12,
+  OT_RS = 13, /* Register Shifter, used in Khmer OT spec. */
+  OT_Coeng = 14, /* Khmer-style Virama. */
+  OT_Repha = 15, /* Atomically-encoded logical or visual repha. */
+  OT_Ra = 16,
+  OT_CM = 17,  /* Consonant-Medial; Unused by Indic shaper. */
+  OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
+  OT_CS = 19
+};
+
+/* Note:
+ *
+ * We treat Vowels and placeholders as if they were consonants.  This is safe because Vowels
+ * cannot happen in a consonant syllable.  The plus side however is, we can call the
+ * consonant syllable logic from the vowel syllable function and get it all right! */
+#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CS) | FLAG (OT_Ra) | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE))
+#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
+
+
+/* Visual positions in a syllable from left to right. */
+enum indic_position_t {
+  POS_START = 0,
+
+  POS_RA_TO_BECOME_REPH = 1,
+  POS_PRE_M = 2,
+  POS_PRE_C = 3,
+
+  POS_BASE_C = 4,
+  POS_AFTER_MAIN = 5,
+
+  POS_ABOVE_C = 6,
+
+  POS_BEFORE_SUB = 7,
+  POS_BELOW_C = 8,
+  POS_AFTER_SUB = 9,
+
+  POS_BEFORE_POST = 10,
+  POS_POST_C = 11,
+  POS_AFTER_POST = 12,
+
+  POS_FINAL_C = 13,
+  POS_SMVD = 14,
+
+  POS_END = 15
+};
+
+/* Categories used in IndicSyllabicCategory.txt from UCD. */
+enum indic_syllabic_category_t {
+  INDIC_SYLLABIC_CATEGORY_OTHER                         = OT_X,
+
+  INDIC_SYLLABIC_CATEGORY_AVAGRAHA                      = OT_Symbol,
+  INDIC_SYLLABIC_CATEGORY_BINDU                         = OT_SM,
+  INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER         = OT_PLACEHOLDER, /* Don't care. */
+  INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK             = OT_A,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT                     = OT_C,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD                = OT_C,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL               = OT_CM,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER         = OT_C,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER              = OT_M, /* U+17CD only. */
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL              = OT_CM,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER         = OT_PLACEHOLDER,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA     = OT_Repha,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED            = OT_X, /* Don't care. */
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED           = OT_CM,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA    = OT_CM,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER        = OT_CS,
+  INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK               = OT_SM, /* https://github.com/harfbuzz/harfbuzz/issues/552 */
+  INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER             = OT_Coeng,
+  INDIC_SYLLABIC_CATEGORY_JOINER                        = OT_ZWJ,
+  INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER              = OT_X,
+  INDIC_SYLLABIC_CATEGORY_NON_JOINER                    = OT_ZWNJ,
+  INDIC_SYLLABIC_CATEGORY_NUKTA                         = OT_N,
+  INDIC_SYLLABIC_CATEGORY_NUMBER                        = OT_PLACEHOLDER,
+  INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER                 = OT_PLACEHOLDER, /* Don't care. */
+  INDIC_SYLLABIC_CATEGORY_PURE_KILLER                   = OT_M, /* Is like a vowel matra. */
+  INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER              = OT_RS,
+  INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER             = OT_SM,
+  INDIC_SYLLABIC_CATEGORY_TONE_LETTER                   = OT_X,
+  INDIC_SYLLABIC_CATEGORY_TONE_MARK                     = OT_N,
+  INDIC_SYLLABIC_CATEGORY_VIRAMA                        = OT_H,
+  INDIC_SYLLABIC_CATEGORY_VISARGA                       = OT_SM,
+  INDIC_SYLLABIC_CATEGORY_VOWEL                         = OT_V,
+  INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT               = OT_M,
+  INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT             = OT_V
+};
+
+/* Categories used in IndicSMatraCategory.txt from UCD */
+enum indic_matra_category_t {
+  INDIC_MATRA_CATEGORY_NOT_APPLICABLE                   = POS_END,
+
+  INDIC_MATRA_CATEGORY_LEFT                             = POS_PRE_C,
+  INDIC_MATRA_CATEGORY_TOP                              = POS_ABOVE_C,
+  INDIC_MATRA_CATEGORY_BOTTOM                           = POS_BELOW_C,
+  INDIC_MATRA_CATEGORY_RIGHT                            = POS_POST_C,
+
+  /* These should resolve to the position of the last part of the split sequence. */
+  INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT                 = INDIC_MATRA_CATEGORY_RIGHT,
+  INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT                   = INDIC_MATRA_CATEGORY_RIGHT,
+  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM                   = INDIC_MATRA_CATEGORY_BOTTOM,
+  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT         = INDIC_MATRA_CATEGORY_RIGHT,
+  INDIC_MATRA_CATEGORY_TOP_AND_LEFT                     = INDIC_MATRA_CATEGORY_TOP,
+  INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT           = INDIC_MATRA_CATEGORY_RIGHT,
+  INDIC_MATRA_CATEGORY_TOP_AND_RIGHT                    = INDIC_MATRA_CATEGORY_RIGHT,
+
+  INDIC_MATRA_CATEGORY_OVERSTRUCK                       = POS_AFTER_MAIN,
+  INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT                = POS_PRE_M
+};
+
+#define INDIC_COMBINE_CATEGORIES(S,M) \
+  ( \
+    ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
+    ( S | \
+     ( \
+      ( \
+       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
+       S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
+       S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
+       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
+       S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
+       S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
+       false \
+       ? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \
+      ) << 8 \
+     ) \
+    ) \
+   )
+
+HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE
+hb_indic_get_categories (hb_codepoint_t u);
+
+
+static inline bool
+is_one_of (const hb_glyph_info_t &info, unsigned int flags)
+{
+  /* If it ligated, all bets are off. */
+  if (_hb_glyph_info_ligated (&info)) return false;
+  return !!(FLAG_UNSAFE (info.indic_category()) & flags);
+}
+
+static inline bool
+is_joiner (const hb_glyph_info_t &info)
+{
+  return is_one_of (info, JOINER_FLAGS);
+}
+
+static inline bool
+is_consonant (const hb_glyph_info_t &info)
+{
+  return is_one_of (info, CONSONANT_FLAGS);
+}
+
+static inline bool
+is_halant (const hb_glyph_info_t &info)
+{
+  return is_one_of (info, FLAG (OT_H));
+}
+
+#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base))
+
+#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u))
+#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u))
+#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u))
+#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u))
+#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u))
+#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u))
+#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u))
+#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u))
+#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u))
+#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u))
+
+
+#define MATRA_POS_LEFT(u)       POS_PRE_M
+#define MATRA_POS_RIGHT(u)      ( \
+                                  IS_DEVA(u) ? POS_AFTER_SUB  : \
+                                  IS_BENG(u) ? POS_AFTER_POST : \
+                                  IS_GURU(u) ? POS_AFTER_POST : \
+                                  IS_GUJR(u) ? POS_AFTER_POST : \
+                                  IS_ORYA(u) ? POS_AFTER_POST : \
+                                  IS_TAML(u) ? POS_AFTER_POST : \
+                                  IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
+                                  IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
+                                  IS_MLYM(u) ? POS_AFTER_POST : \
+                                  IS_SINH(u) ? POS_AFTER_SUB  : \
+                                  /*default*/  POS_AFTER_SUB    \
+                                )
+#define MATRA_POS_TOP(u)        ( /* BENG and MLYM don't have top matras. */ \
+                                  IS_DEVA(u) ? POS_AFTER_SUB  : \
+                                  IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \
+                                  IS_GUJR(u) ? POS_AFTER_SUB  : \
+                                  IS_ORYA(u) ? POS_AFTER_MAIN : \
+                                  IS_TAML(u) ? POS_AFTER_SUB  : \
+                                  IS_TELU(u) ? POS_BEFORE_SUB : \
+                                  IS_KNDA(u) ? POS_BEFORE_SUB : \
+                                  IS_SINH(u) ? POS_AFTER_SUB  : \
+                                  /*default*/  POS_AFTER_SUB    \
+                                )
+#define MATRA_POS_BOTTOM(u)     ( \
+                                  IS_DEVA(u) ? POS_AFTER_SUB  : \
+                                  IS_BENG(u) ? POS_AFTER_SUB  : \
+                                  IS_GURU(u) ? POS_AFTER_POST : \
+                                  IS_GUJR(u) ? POS_AFTER_POST : \
+                                  IS_ORYA(u) ? POS_AFTER_SUB  : \
+                                  IS_TAML(u) ? POS_AFTER_POST : \
+                                  IS_TELU(u) ? POS_BEFORE_SUB : \
+                                  IS_KNDA(u) ? POS_BEFORE_SUB : \
+                                  IS_MLYM(u) ? POS_AFTER_POST : \
+                                  IS_SINH(u) ? POS_AFTER_SUB  : \
+                                  /*default*/  POS_AFTER_SUB    \
+                                )
+
+static inline indic_position_t
+matra_position_indic (hb_codepoint_t u, indic_position_t side)
+{
+  switch ((int) side)
+  {
+    case POS_PRE_C:     return MATRA_POS_LEFT (u);
+    case POS_POST_C:    return MATRA_POS_RIGHT (u);
+    case POS_ABOVE_C:   return MATRA_POS_TOP (u);
+    case POS_BELOW_C:   return MATRA_POS_BOTTOM (u);
+  };
+  return side;
+}
+
+/* XXX
+ * This is a hack for now.  We should move this data into the main Indic table.
+ * Or completely remove it and just check in the tables.
+ */
+static const hb_codepoint_t ra_chars[] = {
+  0x0930u, /* Devanagari */
+  0x09B0u, /* Bengali */
+  0x09F0u, /* Bengali */
+  0x0A30u, /* Gurmukhi */       /* No Reph */
+  0x0AB0u, /* Gujarati */
+  0x0B30u, /* Oriya */
+  0x0BB0u, /* Tamil */          /* No Reph */
+  0x0C30u, /* Telugu */         /* Reph formed only with ZWJ */
+  0x0CB0u, /* Kannada */
+  0x0D30u, /* Malayalam */      /* No Reph, Logical Repha */
+
+  0x0DBBu, /* Sinhala */        /* Reph formed only with ZWJ */
+
+  0x179Au, /* Khmer */
+};
+
+static inline bool
+is_ra (hb_codepoint_t u)
+{
+  for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++)
+    if (u == ra_chars[i])
+      return true;
+  return false;
+}
+
+static inline void
+set_indic_properties (hb_glyph_info_t &info)
+{
+  hb_codepoint_t u = info.codepoint;
+  unsigned int type = hb_indic_get_categories (u);
+  indic_category_t cat = (indic_category_t) (type & 0x7Fu);
+  indic_position_t pos = (indic_position_t) (type >> 8);
+
+
+  /*
+   * Re-assign category
+   */
+
+  /* The following act more like the Bindus. */
+  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0953u, 0x0954u)))
+    cat = OT_SM;
+  /* The following act like consonants. */
+  else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x0A72u, 0x0A73u,
+                                      0x1CF5u, 0x1CF6u)))
+    cat = OT_C;
+  /* TODO: The following should only be allowed after a Visarga.
+   * For now, just treat them like regular tone marks. */
+  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1CE2u, 0x1CE8u)))
+    cat = OT_A;
+  /* TODO: The following should only be allowed after some of
+   * the nasalization marks, maybe only for U+1CE9..U+1CF1.
+   * For now, just treat them like tone marks. */
+  else if (unlikely (u == 0x1CEDu))
+    cat = OT_A;
+  /* The following take marks in standalone clusters, similar to Avagraha. */
+  else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0xA8F2u, 0xA8F7u,
+                                      0x1CE9u, 0x1CECu,
+                                      0x1CEEu, 0x1CF1u)))
+  {
+    cat = OT_Symbol;
+    static_assert (((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol), "");
+  }
+  else if (unlikely (u == 0x0A51u))
+  {
+    /* https://github.com/harfbuzz/harfbuzz/issues/524 */
+    cat = OT_M;
+    pos = POS_BELOW_C;
+  }
+
+  /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
+   * so the Indic shaper needs to know their categories. */
+  else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM;
+  else if (unlikely (u == 0x1133cu)) cat = OT_N;
+
+  else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */
+
+  else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
+  else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
+  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
+                                    cat = OT_PLACEHOLDER;
+  else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
+
+
+  /*
+   * Re-assign position.
+   */
+
+  if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
+  {
+    pos = POS_BASE_C;
+    if (is_ra (u))
+      cat = OT_Ra;
+  }
+  else if (cat == OT_M)
+  {
+    pos = matra_position_indic (u, pos);
+  }
+  else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) /* | FLAG (OT_VD) */ | FLAG (OT_A) | FLAG (OT_Symbol))))
+  {
+    pos = POS_SMVD;
+  }
+
+  if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
+
+
+
+  info.indic_category() = cat;
+  info.indic_position() = pos;
+}
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_INDIC_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer-machine.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer-machine.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -29,143 +29,212 @@
 #ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-ot-shape-complex-khmer-machine.hh"
 static const unsigned char _khmer_syllable_machine_trans_keys[] = {
-        7u, 7u, 1u, 16u, 13u, 13u, 1u, 16u, 7u, 13u, 7u, 7u, 1u, 16u, 13u, 13u,
-        1u, 16u, 7u, 13u, 1u, 16u, 3u, 14u, 3u, 14u, 5u, 14u, 3u, 14u, 5u, 14u,
-        8u, 8u, 3u, 13u, 3u, 8u, 8u, 8u, 3u, 8u, 3u, 14u, 3u, 14u, 5u, 14u,
-        3u, 14u, 5u, 14u, 8u, 8u, 3u, 13u, 3u, 8u, 8u, 8u, 3u, 8u, 3u, 14u,
-        3u, 14u, 7u, 13u, 7u, 7u, 1u, 16u, 0
+        5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u,
+        5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u,
+        5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 5u, 26u, 1u, 16u, 1u, 29u, 5u, 29u,
+        5u, 29u, 5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 5u, 29u, 5u, 26u,
+        5u, 29u, 5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 29u,
+        5u, 29u, 0
 };
 
 static const char _khmer_syllable_machine_key_spans[] = {
-        1, 16, 1, 16, 7, 1, 16, 1,
-        16, 7, 16, 12, 12, 10, 12, 10,
-        1, 11, 6, 1, 6, 12, 12, 10,
-        12, 10, 1, 11, 6, 1, 6, 12,
-        12, 7, 1, 16
+        22, 17, 22, 17, 16, 17, 22, 17,
+        22, 17, 16, 17, 22, 17, 16, 17,
+        22, 17, 22, 17, 22, 16, 29, 25,
+        25, 25, 1, 18, 25, 25, 25, 22,
+        25, 25, 1, 18, 25, 25, 16, 25,
+        25
 };
 
 static const short _khmer_syllable_machine_index_offsets[] = {
-        0, 2, 19, 21, 38, 46, 48, 65,
-        67, 84, 92, 109, 122, 135, 146, 159,
-        170, 172, 184, 191, 193, 200, 213, 226,
-        237, 250, 261, 263, 275, 282, 284, 291,
-        304, 317, 325, 327
+        0, 23, 41, 64, 82, 99, 117, 140,
+        158, 181, 199, 216, 234, 257, 275, 292,
+        310, 333, 351, 374, 392, 415, 432, 462,
+        488, 514, 540, 542, 561, 587, 613, 639,
+        662, 688, 714, 716, 735, 761, 787, 804,
+        830
 };
 
 static const char _khmer_syllable_machine_indicies[] = {
-        1, 0, 2, 2, 0, 0, 0, 0,
+        1, 1, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 2,
+        3, 0, 0, 0, 0, 4, 0, 1,
+        1, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 3,
+        0, 1, 1, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 3, 0, 0, 0, 0, 4, 0,
+        5, 5, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        4, 0, 6, 6, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 2, 0, 3, 0, 4, 4, 0,
+        0, 6, 0, 7, 7, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 8, 0, 9, 9, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 10, 0, 0,
+        0, 0, 4, 0, 9, 9, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 10, 0, 11, 11,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 12, 0,
+        0, 0, 0, 4, 0, 11, 11, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 4, 0, 1, 0,
-        0, 0, 0, 0, 5, 0, 7, 6,
-        8, 8, 6, 6, 6, 6, 6, 6,
-        6, 6, 6, 6, 6, 6, 6, 8,
-        6, 9, 6, 10, 10, 6, 6, 6,
-        6, 6, 6, 6, 6, 6, 6, 6,
-        6, 6, 10, 6, 7, 6, 6, 6,
-        6, 6, 11, 6, 4, 4, 13, 12,
-        14, 15, 7, 16, 12, 12, 4, 4,
-        11, 17, 12, 4, 12, 19, 18, 20,
-        21, 1, 22, 18, 18, 18, 18, 5,
-        23, 18, 24, 18, 21, 21, 1, 22,
-        18, 18, 18, 18, 18, 23, 18, 21,
-        21, 1, 22, 18, 18, 18, 18, 18,
-        23, 18, 25, 18, 21, 21, 1, 22,
-        18, 18, 18, 18, 18, 26, 18, 21,
-        21, 1, 22, 18, 18, 18, 18, 18,
-        26, 18, 27, 18, 28, 18, 29, 18,
-        18, 22, 18, 18, 18, 18, 3, 18,
-        30, 18, 18, 18, 18, 22, 18, 22,
-        18, 28, 18, 18, 18, 18, 22, 18,
-        19, 18, 21, 21, 1, 22, 18, 18,
-        18, 18, 18, 23, 18, 32, 31, 33,
-        33, 7, 16, 31, 31, 31, 31, 31,
-        34, 31, 33, 33, 7, 16, 31, 31,
-        31, 31, 31, 34, 31, 35, 31, 33,
-        33, 7, 16, 31, 31, 31, 31, 31,
-        36, 31, 33, 33, 7, 16, 31, 31,
-        31, 31, 31, 36, 31, 37, 31, 38,
-        31, 39, 31, 31, 16, 31, 31, 31,
-        31, 9, 31, 40, 31, 31, 31, 31,
-        16, 31, 16, 31, 38, 31, 31, 31,
-        31, 16, 31, 13, 31, 41, 33, 7,
-        16, 31, 31, 31, 31, 11, 34, 31,
-        13, 31, 33, 33, 7, 16, 31, 31,
-        31, 31, 31, 34, 31, 7, 42, 42,
-        42, 42, 42, 11, 42, 7, 42, 10,
-        10, 42, 42, 42, 42, 42, 42, 42,
-        42, 42, 42, 42, 42, 42, 10, 42,
+        0, 0, 0, 0, 0, 12, 0, 13,
+        13, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 13, 0,
+        15, 15, 14, 14, 14, 14, 14, 14,
+        14, 14, 14, 14, 14, 14, 14, 14,
+        16, 14, 15, 15, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 16, 17, 17, 17, 17, 18,
+        17, 19, 19, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17,
+        17, 18, 17, 20, 20, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 20, 17, 21, 21, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 22, 17, 23, 23,
+        17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 24, 17,
+        17, 17, 17, 18, 17, 23, 23, 17,
+        17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 24, 17, 25,
+        25, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 26,
+        17, 17, 17, 17, 18, 17, 25, 25,
+        17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 26, 17,
+        15, 15, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 27,
+        16, 17, 17, 17, 17, 18, 17, 28,
+        28, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 28, 17,
+        13, 13, 29, 29, 30, 30, 29, 29,
+        29, 29, 2, 2, 29, 31, 29, 13,
+        29, 29, 29, 29, 16, 20, 29, 29,
+        29, 18, 24, 26, 22, 29, 33, 33,
+        32, 32, 32, 32, 32, 32, 32, 34,
+        32, 32, 32, 32, 32, 2, 3, 6,
+        32, 32, 32, 4, 10, 12, 8, 32,
+        35, 35, 32, 32, 32, 32, 32, 32,
+        32, 36, 32, 32, 32, 32, 32, 32,
+        3, 6, 32, 32, 32, 4, 10, 12,
+        8, 32, 5, 5, 32, 32, 32, 32,
+        32, 32, 32, 36, 32, 32, 32, 32,
+        32, 32, 4, 6, 32, 32, 32, 32,
+        32, 32, 8, 32, 6, 32, 7, 7,
+        32, 32, 32, 32, 32, 32, 32, 36,
+        32, 32, 32, 32, 32, 32, 8, 6,
+        32, 37, 37, 32, 32, 32, 32, 32,
+        32, 32, 36, 32, 32, 32, 32, 32,
+        32, 10, 6, 32, 32, 32, 4, 32,
+        32, 8, 32, 38, 38, 32, 32, 32,
+        32, 32, 32, 32, 36, 32, 32, 32,
+        32, 32, 32, 12, 6, 32, 32, 32,
+        4, 10, 32, 8, 32, 35, 35, 32,
+        32, 32, 32, 32, 32, 32, 34, 32,
+        32, 32, 32, 32, 32, 3, 6, 32,
+        32, 32, 4, 10, 12, 8, 32, 15,
+        15, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 16,
+        39, 39, 39, 39, 18, 39, 41, 41,
+        40, 40, 40, 40, 40, 40, 40, 42,
+        40, 40, 40, 40, 40, 40, 16, 20,
+        40, 40, 40, 18, 24, 26, 22, 40,
+        19, 19, 40, 40, 40, 40, 40, 40,
+        40, 42, 40, 40, 40, 40, 40, 40,
+        18, 20, 40, 40, 40, 40, 40, 40,
+        22, 40, 20, 40, 21, 21, 40, 40,
+        40, 40, 40, 40, 40, 42, 40, 40,
+        40, 40, 40, 40, 22, 20, 40, 43,
+        43, 40, 40, 40, 40, 40, 40, 40,
+        42, 40, 40, 40, 40, 40, 40, 24,
+        20, 40, 40, 40, 18, 40, 40, 22,
+        40, 44, 44, 40, 40, 40, 40, 40,
+        40, 40, 42, 40, 40, 40, 40, 40,
+        40, 26, 20, 40, 40, 40, 18, 24,
+        40, 22, 40, 28, 28, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 28, 39, 45, 45, 40, 40,
+        40, 40, 40, 40, 40, 46, 40, 40,
+        40, 40, 40, 27, 16, 20, 40, 40,
+        40, 18, 24, 26, 22, 40, 41, 41,
+        40, 40, 40, 40, 40, 40, 40, 46,
+        40, 40, 40, 40, 40, 40, 16, 20,
+        40, 40, 40, 18, 24, 26, 22, 40,
         0
 };
 
 static const char _khmer_syllable_machine_trans_targs[] = {
-        10, 14, 17, 20, 11, 21, 10, 24,
-        27, 30, 31, 32, 10, 22, 33, 34,
-        26, 35, 10, 12, 4, 0, 16, 3,
-        13, 15, 1, 10, 18, 2, 19, 10,
-        23, 5, 8, 25, 6, 10, 28, 7,
-        29, 9, 10
+        22, 1, 30, 24, 25, 3, 26, 5,
+        27, 7, 28, 9, 29, 23, 22, 11,
+        32, 22, 33, 13, 34, 15, 35, 17,
+        36, 19, 37, 40, 39, 22, 31, 38,
+        22, 0, 10, 2, 4, 6, 8, 22,
+        22, 12, 14, 16, 18, 20, 21
 };
 
 static const char _khmer_syllable_machine_trans_actions[] = {
-        1, 2, 2, 0, 2, 2, 3, 2,
-        2, 0, 2, 2, 6, 2, 0, 0,
-        0, 0, 7, 2, 0, 0, 0, 0,
-        2, 2, 0, 8, 0, 0, 0, 9,
-        2, 0, 0, 2, 0, 10, 0, 0,
-        0, 0, 11
+        1, 0, 2, 2, 2, 0, 0, 0,
+        2, 0, 2, 0, 2, 2, 3, 0,
+        4, 5, 2, 0, 0, 0, 2, 0,
+        2, 0, 2, 4, 4, 8, 9, 0,
+        10, 0, 0, 0, 0, 0, 0, 11,
+        12, 0, 0, 0, 0, 0, 0
 };
 
 static const char _khmer_syllable_machine_to_state_actions[] = {
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 4, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 6, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0
+        0
 };
 
 static const char _khmer_syllable_machine_from_state_actions[] = {
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 5, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 7, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0
+        0
 };
 
 static const unsigned char _khmer_syllable_machine_eof_trans[] = {
-        1, 1, 1, 1, 1, 7, 7, 7,
-        7, 7, 0, 19, 19, 19, 19, 19,
-        19, 19, 19, 19, 19, 19, 32, 32,
-        32, 32, 32, 32, 32, 32, 32, 32,
-        32, 43, 43, 43
+        1, 1, 1, 1, 1, 1, 1, 1,
+        1, 1, 1, 15, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 0, 33,
+        33, 33, 33, 33, 33, 33, 33, 40,
+        41, 41, 41, 41, 41, 41, 40, 41,
+        41
 };
 
-static const int khmer_syllable_machine_start = 10;
-static const int khmer_syllable_machine_first_final = 10;
+static const int khmer_syllable_machine_start = 22;
+static const int khmer_syllable_machine_first_final = 22;
 static const int khmer_syllable_machine_error = -1;
 
-static const int khmer_syllable_machine_en_main = 10;
+static const int khmer_syllable_machine_en_main = 22;
 
 
 #line 36 "hb-ot-shape-complex-khmer-machine.rl"
 
 
 
-#line 74 "hb-ot-shape-complex-khmer-machine.rl"
+#line 80 "hb-ot-shape-complex-khmer-machine.rl"
 
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -173,11 +242,11 @@
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
 
-#line 181 "hb-ot-shape-complex-khmer-machine.hh"
+#line 250 "hb-ot-shape-complex-khmer-machine.hh"
         {
         cs = khmer_syllable_machine_start;
         ts = 0;
@@ -185,16 +254,15 @@
         act = 0;
         }
 
-#line 95 "hb-ot-shape-complex-khmer-machine.rl"
+#line 100 "hb-ot-shape-complex-khmer-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
 
-#line 198 "hb-ot-shape-complex-khmer-machine.hh"
+#line 266 "hb-ot-shape-complex-khmer-machine.hh"
         {
         int _slen;
         int _trans;
@@ -204,11 +272,11 @@
                 goto _test_eof;
 _resume:
         switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
-        case 5:
+        case 7:
 #line 1 "NONE"
         {ts = p;}
         break;
-#line 212 "hb-ot-shape-complex-khmer-machine.hh"
+#line 280 "hb-ot-shape-complex-khmer-machine.hh"
         }
 
         _keys = _khmer_syllable_machine_trans_keys + (cs<<1);
@@ -231,47 +299,63 @@
         {te = p+1;}
         break;
         case 8:
-#line 68 "hb-ot-shape-complex-khmer-machine.rl"
-        {te = p+1;{ found_syllable (consonant_syllable); }}
+#line 76 "hb-ot-shape-complex-khmer-machine.rl"
+        {te = p+1;{ found_syllable (non_khmer_cluster); }}
         break;
         case 10:
-#line 69 "hb-ot-shape-complex-khmer-machine.rl"
-        {te = p+1;{ found_syllable (broken_cluster); }}
-        break;
-        case 6:
-#line 70 "hb-ot-shape-complex-khmer-machine.rl"
-        {te = p+1;{ found_syllable (non_khmer_cluster); }}
-        break;
-        case 7:
-#line 68 "hb-ot-shape-complex-khmer-machine.rl"
+#line 74 "hb-ot-shape-complex-khmer-machine.rl"
         {te = p;p--;{ found_syllable (consonant_syllable); }}
         break;
-        case 9:
-#line 69 "hb-ot-shape-complex-khmer-machine.rl"
+        case 12:
+#line 75 "hb-ot-shape-complex-khmer-machine.rl"
         {te = p;p--;{ found_syllable (broken_cluster); }}
         break;
         case 11:
-#line 70 "hb-ot-shape-complex-khmer-machine.rl"
+#line 76 "hb-ot-shape-complex-khmer-machine.rl"
         {te = p;p--;{ found_syllable (non_khmer_cluster); }}
         break;
         case 1:
-#line 68 "hb-ot-shape-complex-khmer-machine.rl"
+#line 74 "hb-ot-shape-complex-khmer-machine.rl"
         {{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
         break;
+        case 5:
+#line 75 "hb-ot-shape-complex-khmer-machine.rl"
+        {{p = ((te))-1;}{ found_syllable (broken_cluster); }}
+        break;
+        case 3:
+#line 1 "NONE"
+        {       switch( act ) {
+        case 2:
+        {{p = ((te))-1;} found_syllable (broken_cluster); }
+        break;
         case 3:
-#line 69 "hb-ot-shape-complex-khmer-machine.rl"
-        {{p = ((te))-1;}{ found_syllable (broken_cluster); }}
+        {{p = ((te))-1;} found_syllable (non_khmer_cluster); }
+        break;
+        }
+        }
         break;
-#line 266 "hb-ot-shape-complex-khmer-machine.hh"
+        case 4:
+#line 1 "NONE"
+        {te = p+1;}
+#line 75 "hb-ot-shape-complex-khmer-machine.rl"
+        {act = 2;}
+        break;
+        case 9:
+#line 1 "NONE"
+        {te = p+1;}
+#line 76 "hb-ot-shape-complex-khmer-machine.rl"
+        {act = 3;}
+        break;
+#line 350 "hb-ot-shape-complex-khmer-machine.hh"
         }
 
 _again:
         switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
-        case 4:
+        case 6:
 #line 1 "NONE"
         {ts = 0;}
         break;
-#line 275 "hb-ot-shape-complex-khmer-machine.hh"
+#line 359 "hb-ot-shape-complex-khmer-machine.hh"
         }
 
         if ( ++p != pe )
@@ -287,7 +371,7 @@
 
         }
 
-#line 104 "hb-ot-shape-complex-khmer-machine.rl"
+#line 108 "hb-ot-shape-complex-khmer-machine.rl"
 
 }
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-complex-indic-private.hh"
-
-
-/* buffer var allocations */
-#define khmer_category() indic_category() /* khmer_category_t */
-#define khmer_position() indic_position() /* khmer_position_t */
-
-
-typedef indic_category_t khmer_category_t;
-typedef indic_position_t khmer_position_t;
-
-
-static inline khmer_position_t
-matra_position_khmer (khmer_position_t side)
-{
-  switch ((int) side)
-  {
-    case POS_PRE_C:
-      return POS_PRE_M;
-
-    case POS_POST_C:
-    case POS_ABOVE_C:
-    case POS_BELOW_C:
-      return POS_AFTER_POST;
-
-    default:
-      return side;
-  };
-}
-
-static inline bool
-is_consonant_or_vowel (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, CONSONANT_FLAGS | FLAG (OT_V));
-}
-
-static inline bool
-is_coeng (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, FLAG (OT_Coeng));
-}
-
-static inline void
-set_khmer_properties (hb_glyph_info_t &info)
-{
-  hb_codepoint_t u = info.codepoint;
-  unsigned int type = hb_indic_get_categories (u);
-  khmer_category_t cat = (khmer_category_t) (type & 0x7Fu);
-  khmer_position_t pos = (khmer_position_t) (type >> 8);
-
-
-  /*
-   * Re-assign category
-   */
-
-  if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CDu, 0x17D1u) ||
-                     u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */
-  {
-    /* These can occur mid-syllable (eg. before matras), even though Unicode marks them as Syllable_Modifier.
-     * https://github.com/roozbehp/unicode-data/issues/5 */
-    cat = OT_M;
-    pos = POS_ABOVE_C;
-  }
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u))) cat = OT_PLACEHOLDER;
-  else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
-
-
-  /*
-   * Re-assign position.
-   */
-
-  if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
-  {
-    pos = POS_BASE_C;
-    if (u == 0x179Au)
-      cat = OT_Ra;
-  }
-  else if (cat == OT_M)
-  {
-    pos = matra_position_khmer (pos);
-  }
-  else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) | FLAG (OT_A) | FLAG (OT_Symbol))))
-  {
-    pos = POS_SMVD;
-  }
-
-  info.khmer_category() = cat;
-  info.khmer_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,42 +24,38 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-khmer-private.hh"
-#include "hb-ot-layout-private.hh"
+#include "hb-ot-shape-complex-khmer.hh"
+#include "hb-ot-layout.hh"
 
 
 /*
  * Khmer shaper.
  */
 
-struct feature_list_t {
-  hb_tag_t tag;
-  hb_ot_map_feature_flags_t flags;
-};
-
-static const feature_list_t
+static const hb_ot_map_feature_t
 khmer_features[] =
 {
   /*
    * Basic features.
-   * These features are applied in order, one at a time, after initial_reordering.
+   * These features are applied in order, one at a time, after reordering.
    */
-  {HB_TAG('p','r','e','f'), F_NONE},
-  {HB_TAG('b','l','w','f'), F_NONE},
-  {HB_TAG('a','b','v','f'), F_NONE},
-  {HB_TAG('p','s','t','f'), F_NONE},
-  {HB_TAG('c','f','a','r'), F_NONE},
+  {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS},
+  {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS},
+  {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS},
+  {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS},
+  {HB_TAG('c','f','a','r'), F_MANUAL_JOINERS},
   /*
    * Other features.
-   * These features are applied all at once, after final_reordering.
-   * Default Bengali font in Windows for example has intermixed
-   * lookups for init,pres,abvs,blws features.
+   * These features are applied all at once after clearing syllables.
    */
-  {HB_TAG('p','r','e','s'), F_GLOBAL},
-  {HB_TAG('a','b','v','s'), F_GLOBAL},
-  {HB_TAG('b','l','w','s'), F_GLOBAL},
-  {HB_TAG('p','s','t','s'), F_GLOBAL},
-  /* Positioning features, though we don't care about the types. */
+  {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
+  /*
+   * Positioning features.
+   * We don't care about the types.
+   */
   {HB_TAG('d','i','s','t'), F_GLOBAL},
   {HB_TAG('a','b','v','m'), F_GLOBAL},
   {HB_TAG('b','l','w','m'), F_GLOBAL},
@@ -79,12 +75,13 @@
   _ABVS,
   _BLWS,
   _PSTS,
+
   _DIST,
   _ABVM,
   _BLWM,
 
   KHMER_NUM_FEATURES,
-  KHMER_BASIC_FEATURES = _PRES /* Don't forget to update this! */
+  KHMER_BASIC_FEATURES = _PRES, /* Don't forget to update this! */
 };
 
 static void
@@ -92,13 +89,9 @@
                  hb_font_t *font,
                  hb_buffer_t *buffer);
 static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-                    hb_font_t *font,
-                    hb_buffer_t *buffer);
-static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-                  hb_font_t *font,
-                  hb_buffer_t *buffer);
+reorder (const hb_ot_shape_plan_t *plan,
+         hb_font_t *font,
+         hb_buffer_t *buffer);
 static void
 clear_syllables (const hb_ot_shape_plan_t *plan,
                  hb_font_t *font,
@@ -111,46 +104,54 @@
 
   /* Do this before any lookups have been applied. */
   map->add_gsub_pause (setup_syllables);
+  map->add_gsub_pause (reorder);
 
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
-  /* The Indic specs do not require ccmp, but we apply it here since if
-   * there is a use of it, it's typically at the beginning. */
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-
+  /* Testing suggests that Uniscribe does NOT pause between basic
+   * features.  Test with KhmerUI.ttf and the following three
+   * sequences:
+   *
+   *   U+1789,U+17BC
+   *   U+1789,U+17D2,U+1789
+   *   U+1789,U+17D2,U+1789,U+17BC
+   *
+   * https://github.com/harfbuzz/harfbuzz/issues/974
+   */
+  map->enable_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
 
   unsigned int i = 0;
-  map->add_gsub_pause (initial_reordering);
-  for (; i < KHMER_BASIC_FEATURES; i++) {
-    map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-    map->add_gsub_pause (nullptr);
-  }
-  map->add_gsub_pause (final_reordering);
-  for (; i < KHMER_NUM_FEATURES; i++) {
-    map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-  }
-
-  map->add_global_bool_feature (HB_TAG('c','a','l','t'));
-  map->add_global_bool_feature (HB_TAG('c','l','i','g'));
+  for (; i < KHMER_BASIC_FEATURES; i++)
+    map->add_feature (khmer_features[i]);
 
   map->add_gsub_pause (clear_syllables);
+
+  for (; i < KHMER_NUM_FEATURES; i++)
+    map->add_feature (khmer_features[i]);
 }
 
 static void
 override_features_khmer (hb_ot_shape_planner_t *plan)
 {
+  hb_ot_map_builder_t *map = &plan->map;
+
+  /* Khmer spec has 'clig' as part of required shaping features:
+   * "Apply feature 'clig' to form ligatures that are desired for
+   * typographical correctness.", hence in overrides... */
+  map->enable_feature (HB_TAG('c','l','i','g'));
+
   /* Uniscribe does not apply 'kern' in Khmer. */
   if (hb_options ().uniscribe_bug_compatible)
   {
-    plan->map.add_feature (HB_TAG('k','e','r','n'), 0, F_GLOBAL);
+    map->disable_feature (HB_TAG('k','e','r','n'));
   }
 
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
+  map->disable_feature (HB_TAG('l','i','g','a'));
 }
 
 
 struct would_substitute_feature_t
 {
-  inline void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
+  void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
   {
     zero_context = zero_context_;
     map->get_stage_lookups (0/*GSUB*/,
@@ -158,9 +159,9 @@
                             &lookups, &count);
   }
 
-  inline bool would_substitute (const hb_codepoint_t *glyphs,
-                                unsigned int          glyphs_count,
-                                hb_face_t            *face) const
+  bool would_substitute (const hb_codepoint_t *glyphs,
+                         unsigned int          glyphs_count,
+                         hb_face_t            *face) const
   {
     for (unsigned int i = 0; i < count; i++)
       if (hb_ot_layout_lookup_would_substitute_fast (face, lookups[i].index, glyphs, glyphs_count, zero_context))
@@ -176,9 +177,7 @@
 
 struct khmer_shape_plan_t
 {
-  ASSERT_POD ();
-
-  inline bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
+  bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
   {
     hb_codepoint_t glyph = virama_glyph;
     if (unlikely (virama_glyph == (hb_codepoint_t) -1))
@@ -243,7 +242,6 @@
                    hb_font_t                *font HB_UNUSED)
 {
   HB_BUFFER_ALLOCATE_VAR (buffer, khmer_category);
-  HB_BUFFER_ALLOCATE_VAR (buffer, khmer_position);
 
   /* We cannot setup masks here.  We save information about characters
    * and setup masks later on in a pause-callback. */
@@ -264,162 +262,58 @@
     buffer->unsafe_to_break (start, end);
 }
 
-static int
-compare_khmer_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
-{
-  int a = pa->khmer_position();
-  int b = pb->khmer_position();
-
-  return a < b ? -1 : a == b ? 0 : +1;
-}
-
 
 /* Rules from:
  * https://docs.microsoft.com/en-us/typography/script-development/devanagari */
 
 static void
-initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
-                                       hb_face_t *face,
-                                       hb_buffer_t *buffer,
-                                       unsigned int start, unsigned int end)
+reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
+                            hb_face_t *face HB_UNUSED,
+                            hb_buffer_t *buffer,
+                            unsigned int start, unsigned int end)
 {
   const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data;
   hb_glyph_info_t *info = buffer->info;
 
-  /* 1. Khmer shaping assumes that a syllable will begin with a Cons, IndV, or Number. */
-
-  /* The first consonant is always the base. */
-  unsigned int base = start;
-  info[base].khmer_position() = POS_BASE_C;
-
-  /* Mark all subsequent consonants as below. */
-  for (unsigned int i = base + 1; i < end; i++)
-    if (is_consonant_or_vowel (info[i]))
-      info[i].khmer_position() = POS_BELOW_C;
-
-  /* Mark final consonants.  A final consonant is one appearing after a matra,
-   * like in Khmer. */
-  for (unsigned int i = base + 1; i < end; i++)
-    if (info[i].khmer_category() == OT_M) {
-      for (unsigned int j = i + 1; j < end; j++)
-        if (is_consonant_or_vowel (info[j])) {
-          info[j].khmer_position() = POS_FINAL_C;
-          break;
-        }
-      break;
-    }
-
-  /* Attach misc marks to previous char to move with them. */
-  {
-    khmer_position_t last_pos = POS_START;
-    for (unsigned int i = start; i < end; i++)
-    {
-      if ((FLAG_UNSAFE (info[i].khmer_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_Coeng))))
-      {
-        info[i].khmer_position() = last_pos;
-        if (unlikely (info[i].khmer_category() == OT_Coeng &&
-                      info[i].khmer_position() == POS_PRE_M))
-        {
-          /*
-           * Uniscribe doesn't move the Halant with Left Matra.
-           * TEST: U+092B,U+093F,U+094DE
-           * We follow.  This is important for the Sinhala
-           * U+0DDA split matra since it decomposes to U+0DD9,U+0DCA
-           * where U+0DD9 is a left matra and U+0DCA is the virama.
-           * We don't want to move the virama with the left matra.
-           * TEST: U+0D9A,U+0DDA
-           */
-          for (unsigned int j = i; j > start; j--)
-            if (info[j - 1].khmer_position() != POS_PRE_M) {
-              info[i].khmer_position() = info[j - 1].khmer_position();
-              break;
-            }
-        }
-      } else if (info[i].khmer_position() != POS_SMVD) {
-        last_pos = (khmer_position_t) info[i].khmer_position();
-      }
-    }
-  }
-  /* For post-base consonants let them own anything before them
-   * since the last consonant or matra. */
+  /* Setup masks. */
   {
-    unsigned int last = base;
-    for (unsigned int i = base + 1; i < end; i++)
-      if (is_consonant_or_vowel (info[i]))
-      {
-        for (unsigned int j = last + 1; j < i; j++)
-          if (info[j].khmer_position() < POS_SMVD)
-            info[j].khmer_position() = info[i].khmer_position();
-        last = i;
-      } else if (info[i].khmer_category() == OT_M)
-        last = i;
-  }
-
-  {
-    /* Use syllable() for sort accounting temporarily. */
-    unsigned int syllable = info[start].syllable();
-    for (unsigned int i = start; i < end; i++)
-      info[i].syllable() = i - start;
-
-    /* Sit tight, rock 'n roll! */
-    hb_stable_sort (info + start, end - start, compare_khmer_order);
-    /* Find base again */
-    base = end;
-    for (unsigned int i = start; i < end; i++)
-      if (info[i].khmer_position() == POS_BASE_C)
-      {
-        base = i;
-        break;
-      }
-
-    if (unlikely (end - start >= 127))
-      buffer->merge_clusters (start, end);
-    else
-      /* Note!  syllable() is a one-byte field. */
-      for (unsigned int i = base; i < end; i++)
-        if (info[i].syllable() != 255)
-        {
-          unsigned int max = i;
-          unsigned int j = start + info[i].syllable();
-          while (j != i)
-          {
-            max = MAX (max, j);
-            unsigned int next = start + info[j].syllable();
-            info[j].syllable() = 255; /* So we don't process j later again. */
-            j = next;
-          }
-          if (i != max)
-            buffer->merge_clusters (i, max + 1);
-        }
-
-    /* Put syllable back in. */
-    for (unsigned int i = start; i < end; i++)
-      info[i].syllable() = syllable;
-  }
-
-  /* Setup masks now */
-
-  {
-    hb_mask_t mask;
-
     /* Post-base */
-    mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF];
-    for (unsigned int i = base + 1; i < end; i++)
+    hb_mask_t mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF];
+    for (unsigned int i = start + 1; i < end; i++)
       info[i].mask  |= mask;
   }
 
-  unsigned int pref_len = 2;
-  if (khmer_plan->mask_array[PREF] && base + pref_len < end)
+  unsigned int num_coengs = 0;
+  for (unsigned int i = start + 1; i < end; i++)
   {
-    /* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */
-    for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) {
-      hb_codepoint_t glyphs[2];
-      for (unsigned int j = 0; j < pref_len; j++)
-        glyphs[j] = info[i + j].codepoint;
-      if (khmer_plan->pref.would_substitute (glyphs, pref_len, face))
+    /* """
+     * When a COENG + (Cons | IndV) combination are found (and subscript count
+     * is less than two) the character combination is handled according to the
+     * subscript type of the character following the COENG.
+     *
+     * ...
+     *
+     * Subscript Type 2 - The COENG + RO characters are reordered to immediately
+     * before the base glyph. Then the COENG + RO characters are assigned to have
+     * the 'pref' OpenType feature applied to them.
+     * """
+     */
+    if (info[i].khmer_category() == OT_Coeng && num_coengs <= 2 && i + 1 < end)
+    {
+      num_coengs++;
+
+      if (info[i + 1].khmer_category() == OT_Ra)
       {
-        for (unsigned int j = 0; j < pref_len; j++)
-          info[i++].mask |= khmer_plan->mask_array[PREF];
+        for (unsigned int j = 0; j < 2; j++)
+          info[i + j].mask |= khmer_plan->mask_array[PREF];
+
+        /* Move the Coeng,Ro sequence to the start. */
+        buffer->merge_clusters (start, i + 2);
+        hb_glyph_info_t t0 = info[i];
+        hb_glyph_info_t t1 = info[i + 1];
+        memmove (&info[start + 2], &info[start], (i - start) * sizeof (info[0]));
+        info[start] = t0;
+        info[start + 1] = t1;
 
         /* Mark the subsequent stuff with 'cfar'.  Used in Khmer.
          * Read the feature spec.
@@ -428,11 +322,21 @@
          * U+1784,U+17D2,U+1782,U+17D2,U+179A
          */
         if (khmer_plan->mask_array[CFAR])
-          for (; i < end; i++)
-            info[i].mask |= khmer_plan->mask_array[CFAR];
+          for (unsigned int j = i + 2; j < end; j++)
+            info[j].mask |= khmer_plan->mask_array[CFAR];
+
+        num_coengs = 2; /* Done. */
+      }
+    }
 
-        break;
-      }
+    /* Reorder left matra piece. */
+    else if (info[i].khmer_category() == OT_VPre)
+    {
+      /* Move to the start. */
+      buffer->merge_clusters (start, i + 1);
+      hb_glyph_info_t t = info[i];
+      memmove (&info[start + 1], &info[start], (i - start) * sizeof (info[0]));
+      info[start] = t;
     }
   }
 }
@@ -448,7 +352,7 @@
   {
     case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
     case consonant_syllable:
-     initial_reordering_consonant_syllable (plan, face, buffer, start, end);
+     reorder_consonant_syllable (plan, face, buffer, start, end);
      break;
 
     case non_khmer_cluster:
@@ -513,263 +417,22 @@
     else
       buffer->next_glyph ();
   }
-
   buffer->swap_buffers ();
 }
 
 static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-                    hb_font_t *font,
-                    hb_buffer_t *buffer)
+reorder (const hb_ot_shape_plan_t *plan,
+         hb_font_t *font,
+         hb_buffer_t *buffer)
 {
   insert_dotted_circles (plan, font, buffer);
 
   foreach_syllable (buffer, start, end)
     initial_reordering_syllable (plan, font->face, buffer, start, end);
-}
-
-static void
-final_reordering_syllable (const hb_ot_shape_plan_t *plan,
-                           hb_buffer_t *buffer,
-                           unsigned int start, unsigned int end)
-{
-  const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data;
-  hb_glyph_info_t *info = buffer->info;
-
-
-  /* This function relies heavily on halant glyphs.  Lots of ligation
-   * and possibly multiple substitutions happened prior to this
-   * phase, and that might have messed up our properties.  Recover
-   * from a particular case of that where we're fairly sure that a
-   * class of OT_Coeng is desired but has been lost. */
-  if (khmer_plan->virama_glyph)
-  {
-    unsigned int virama_glyph = khmer_plan->virama_glyph;
-    for (unsigned int i = start; i < end; i++)
-      if (info[i].codepoint == virama_glyph &&
-          _hb_glyph_info_ligated (&info[i]) &&
-          _hb_glyph_info_multiplied (&info[i]))
-      {
-        /* This will make sure that this glyph passes is_coeng() test. */
-        info[i].khmer_category() = OT_Coeng;
-        _hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
-      }
-  }
-
-
-  /* 4. Final reordering:
-   *
-   * After the localized forms and basic shaping forms GSUB features have been
-   * applied (see below), the shaping engine performs some final glyph
-   * reordering before applying all the remaining font features to the entire
-   * syllable.
-   */
-
-  bool try_pref = !!khmer_plan->mask_array[PREF];
-
-  /* Find base again */
-  unsigned int base;
-  for (base = start; base < end; base++)
-    if (info[base].khmer_position() >= POS_BASE_C)
-    {
-      if (try_pref && base + 1 < end)
-      {
-        for (unsigned int i = base + 1; i < end; i++)
-          if ((info[i].mask & khmer_plan->mask_array[PREF]) != 0)
-          {
-            if (!(_hb_glyph_info_substituted (&info[i]) &&
-                  _hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
-            {
-              /* Ok, this was a 'pref' candidate but didn't form any.
-               * Base is around here... */
-              base = i;
-              while (base < end && is_coeng (info[base]))
-                base++;
-              info[base].khmer_position() = POS_BASE_C;
-
-              try_pref = false;
-            }
-            break;
-          }
-      }
-
-      if (start < base && info[base].khmer_position() > POS_BASE_C)
-        base--;
-      break;
-    }
-  if (base == end && start < base &&
-      is_one_of (info[base - 1], FLAG (OT_ZWJ)))
-    base--;
-  if (base < end)
-    while (start < base &&
-           is_one_of (info[base], (FLAG (OT_N) | FLAG (OT_Coeng))))
-      base--;
-
-
-  /*   o Reorder matras:
-   *
-   *     If a pre-base matra character had been reordered before applying basic
-   *     features, the glyph can be moved closer to the main consonant based on
-   *     whether half-forms had been formed. Actual position for the matra is
-   *     defined as “after last standalone halant glyph, after initial matra
-   *     position and before the main consonant”. If ZWJ or ZWNJ follow this
-   *     halant, position is moved after it.
-   */
-
-  if (start + 1 < end && start < base) /* Otherwise there can't be any pre-base matra characters. */
-  {
-    /* If we lost track of base, alas, position before last thingy. */
-    unsigned int new_pos = base == end ? base - 2 : base - 1;
-
-    while (new_pos > start &&
-           !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_Coeng)))))
-      new_pos--;
-
-    /* If we found no Halant we are done.
-     * Otherwise only proceed if the Halant does
-     * not belong to the Matra itself! */
-    if (is_coeng (info[new_pos]) &&
-        info[new_pos].khmer_position() != POS_PRE_M)
-    {
-      /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
-      if (new_pos + 1 < end && is_joiner (info[new_pos + 1]))
-        new_pos++;
-    }
-    else
-      new_pos = start; /* No move. */
-
-    if (start < new_pos && info[new_pos].khmer_position () != POS_PRE_M)
-    {
-      /* Now go see if there's actually any matras... */
-      for (unsigned int i = new_pos; i > start; i--)
-        if (info[i - 1].khmer_position () == POS_PRE_M)
-        {
-          unsigned int old_pos = i - 1;
-          if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */
-            base--;
-
-          hb_glyph_info_t tmp = info[old_pos];
-          memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0]));
-          info[new_pos] = tmp;
-
-          /* Note: this merge_clusters() is intentionally *after* the reordering.
-           * Indic matra reordering is special and tricky... */
-          buffer->merge_clusters (new_pos, MIN (end, base + 1));
-
-          new_pos--;
-        }
-    } else {
-      for (unsigned int i = start; i < base; i++)
-        if (info[i].khmer_position () == POS_PRE_M) {
-          buffer->merge_clusters (i, MIN (end, base + 1));
-          break;
-        }
-    }
-  }
-
-
-  /*   o Reorder pre-base-reordering consonants:
-   *
-   *     If a pre-base-reordering consonant is found, reorder it according to
-   *     the following rules:
-   */
-
-  if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */
-  {
-    for (unsigned int i = base + 1; i < end; i++)
-      if ((info[i].mask & khmer_plan->mask_array[PREF]) != 0)
-      {
-        /*       1. Only reorder a glyph produced by substitution during application
-         *          of the <pref> feature. (Note that a font may shape a Ra consonant with
-         *          the feature generally but block it in certain contexts.)
-         */
-        /* Note: We just check that something got substituted.  We don't check that
-         * the <pref> feature actually did it...
-         *
-         * Reorder pref only if it ligated. */
-        if (_hb_glyph_info_ligated_and_didnt_multiply (&info[i]))
-        {
-          /*
-           *       2. Try to find a target position the same way as for pre-base matra.
-           *          If it is found, reorder pre-base consonant glyph.
-           *
-           *       3. If position is not found, reorder immediately before main
-           *          consonant.
-           */
-
-          unsigned int new_pos = base;
-          while (new_pos > start &&
-                 !(is_one_of (info[new_pos - 1], FLAG(OT_M) | FLAG (OT_Coeng))))
-            new_pos--;
-
-          /* In Khmer coeng model, a H,Ra can go *after* matras.  If it goes after a
-           * split matra, it should be reordered to *before* the left part of such matra. */
-          if (new_pos > start && info[new_pos - 1].khmer_category() == OT_M)
-          {
-            unsigned int old_pos = i;
-            for (unsigned int j = base + 1; j < old_pos; j++)
-              if (info[j].khmer_category() == OT_M)
-              {
-                new_pos--;
-                break;
-              }
-          }
-
-          if (new_pos > start && is_coeng (info[new_pos - 1]))
-          {
-            /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
-            if (new_pos < end && is_joiner (info[new_pos]))
-              new_pos++;
-          }
-
-          {
-            unsigned int old_pos = i;
-
-            buffer->merge_clusters (new_pos, old_pos + 1);
-            hb_glyph_info_t tmp = info[old_pos];
-            memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0]));
-            info[new_pos] = tmp;
-
-            if (new_pos <= base && base < old_pos)
-              base++;
-          }
-        }
-
-        break;
-      }
-  }
-
-
-  /*
-   * Finish off the clusters and go home!
-   */
-  if (hb_options ().uniscribe_bug_compatible)
-  {
-    /* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala.
-     * This means, half forms are submerged into the main consonant's cluster.
-     * This is unnecessary, and makes cursor positioning harder, but that's what
-     * Uniscribe does. */
-    buffer->merge_clusters (start, end);
-  }
-}
-
-
-static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-                  hb_font_t *font HB_UNUSED,
-                  hb_buffer_t *buffer)
-{
-  unsigned int count = buffer->len;
-  if (unlikely (!count)) return;
-
-  foreach_syllable (buffer, start, end)
-    final_reordering_syllable (plan, buffer, start, end);
 
   HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_position);
 }
 
-
 static void
 clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
                  hb_font_t *font HB_UNUSED,
@@ -831,7 +494,7 @@
   decompose_khmer,
   compose_khmer,
   setup_masks_khmer,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,114 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_KHMER_HH
+#define HB_OT_SHAPE_COMPLEX_KHMER_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex-indic.hh"
+
+
+/* buffer var allocations */
+#define khmer_category() indic_category() /* khmer_category_t */
+
+
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum khmer_category_t
+{
+  OT_Robatic = 20,
+  OT_Xgroup  = 21,
+  OT_Ygroup  = 22,
+
+  OT_VAbv    = 26,
+  OT_VBlw    = 27,
+  OT_VPre    = 28,
+  OT_VPst    = 29,
+};
+
+static inline void
+set_khmer_properties (hb_glyph_info_t &info)
+{
+  hb_codepoint_t u = info.codepoint;
+  unsigned int type = hb_indic_get_categories (u);
+  khmer_category_t cat = (khmer_category_t) (type & 0x7Fu);
+  indic_position_t pos = (indic_position_t) (type >> 8);
+
+
+  /*
+   * Re-assign category
+   *
+   * These categories are experimentally extracted from what Uniscribe allows.
+   */
+  switch (u)
+  {
+    case 0x179Au:
+      cat = (khmer_category_t) OT_Ra;
+      break;
+
+    case 0x17CCu:
+    case 0x17C9u:
+    case 0x17CAu:
+      cat = OT_Robatic;
+      break;
+
+    case 0x17C6u:
+    case 0x17CBu:
+    case 0x17CDu:
+    case 0x17CEu:
+    case 0x17CFu:
+    case 0x17D0u:
+    case 0x17D1u:
+      cat = OT_Xgroup;
+      break;
+
+    case 0x17C7u:
+    case 0x17C8u:
+    case 0x17DDu:
+    case 0x17D3u: /* Just guessing. Uniscribe doesn't categorize it. */
+      cat = OT_Ygroup;
+      break;
+  }
+
+  /*
+   * Re-assign position.
+   */
+  if (cat == (khmer_category_t) OT_M)
+    switch ((int) pos)
+    {
+      case POS_PRE_C:   cat = OT_VPre; break;
+      case POS_BELOW_C: cat = OT_VBlw; break;
+      case POS_ABOVE_C: cat = OT_VAbv; break;
+      case POS_POST_C:  cat = OT_VPst; break;
+      default: assert (0);
+    };
+
+  info.khmer_category() = cat;
+}
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_KHMER_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar-machine.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar-machine.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -29,7 +29,7 @@
 #ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-ot-shape-complex-myanmar-machine.hh"
@@ -283,10 +283,9 @@
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -294,11 +293,11 @@
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
 
-#line 302 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 301 "hb-ot-shape-complex-myanmar-machine.hh"
         {
         cs = myanmar_syllable_machine_start;
         ts = 0;
@@ -306,16 +305,15 @@
         act = 0;
         }
 
-#line 115 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 114 "hb-ot-shape-complex-myanmar-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
 
-#line 319 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 317 "hb-ot-shape-complex-myanmar-machine.hh"
         {
         int _slen;
         int _trans;
@@ -329,7 +327,7 @@
 #line 1 "NONE"
         {ts = p;}
         break;
-#line 333 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 331 "hb-ot-shape-complex-myanmar-machine.hh"
         }
 
         _keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@@ -379,7 +377,7 @@
 #line 90 "hb-ot-shape-complex-myanmar-machine.rl"
         {te = p;p--;{ found_syllable (non_myanmar_cluster); }}
         break;
-#line 383 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 381 "hb-ot-shape-complex-myanmar-machine.hh"
         }
 
 _again:
@@ -388,7 +386,7 @@
 #line 1 "NONE"
         {ts = 0;}
         break;
-#line 392 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 390 "hb-ot-shape-complex-myanmar-machine.hh"
         }
 
         if ( ++p != pe )
@@ -404,7 +402,7 @@
 
         }
 
-#line 124 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 122 "hb-ot-shape-complex-myanmar-machine.rl"
 
 }
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-complex-indic-private.hh"
-
-
-/* buffer var allocations */
-#define myanmar_category() indic_category() /* myanmar_category_t */
-#define myanmar_position() indic_position() /* myanmar_position_t */
-
-
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum myanmar_category_t {
-  OT_As  = 18,  /* Asat */
-  OT_D0  = 20, /* Digit zero */
-  OT_DB  = OT_N, /* Dot below */
-  OT_GB  = OT_PLACEHOLDER,
-  OT_MH  = 21, /* Various consonant medial types */
-  OT_MR  = 22, /* Various consonant medial types */
-  OT_MW  = 23, /* Various consonant medial types */
-  OT_MY  = 24, /* Various consonant medial types */
-  OT_PT  = 25, /* Pwo and other tones */
-  OT_VAbv = 26,
-  OT_VBlw = 27,
-  OT_VPre = 28,
-  OT_VPst = 29,
-  OT_VS   = 30, /* Variation selectors */
-  OT_P    = 31, /* Punctuation */
-  OT_D    = 32, /* Digits except zero */
-};
-
-
-static inline void
-set_myanmar_properties (hb_glyph_info_t &info)
-{
-  hb_codepoint_t u = info.codepoint;
-  unsigned int type = hb_indic_get_categories (u);
-  indic_category_t cat = (indic_category_t) (type & 0x7Fu);
-  indic_position_t pos = (indic_position_t) (type >> 8);
-
-  /* Myanmar
-   * https://docs.microsoft.com/en-us/typography/script-development/myanmar#analyze
-   */
-  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)))
-    cat = (indic_category_t) OT_VS;
-
-  switch (u)
-  {
-    case 0x104Eu:
-      cat = (indic_category_t) OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */
-      break;
-
-    case 0x002Du: case 0x00A0u: case 0x00D7u: case 0x2012u:
-    case 0x2013u: case 0x2014u: case 0x2015u: case 0x2022u:
-    case 0x25CCu: case 0x25FBu: case 0x25FCu: case 0x25FDu:
-    case 0x25FEu:
-      cat = (indic_category_t) OT_GB;
-      break;
-
-    case 0x1004u: case 0x101Bu: case 0x105Au:
-      cat = (indic_category_t) OT_Ra;
-      break;
-
-    case 0x1032u: case 0x1036u:
-      cat = (indic_category_t) OT_A;
-      break;
-
-    case 0x1039u:
-      cat = (indic_category_t) OT_H;
-      break;
-
-    case 0x103Au:
-      cat = (indic_category_t) OT_As;
-      break;
-
-    case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u:
-    case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u:
-    case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u:
-    case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u:
-    case 0x1097u: case 0x1098u: case 0x1099u:
-      cat = (indic_category_t) OT_D;
-      break;
-
-    case 0x1040u:
-      cat = (indic_category_t) OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
-      break;
-
-    case 0x103Eu: case 0x1060u:
-      cat = (indic_category_t) OT_MH;
-      break;
-
-    case 0x103Cu:
-      cat = (indic_category_t) OT_MR;
-      break;
-
-    case 0x103Du: case 0x1082u:
-      cat = (indic_category_t) OT_MW;
-      break;
-
-    case 0x103Bu: case 0x105Eu: case 0x105Fu:
-      cat = (indic_category_t) OT_MY;
-      break;
-
-    case 0x1063u: case 0x1064u: case 0x1069u: case 0x106Au:
-    case 0x106Bu: case 0x106Cu: case 0x106Du: case 0xAA7Bu:
-      cat = (indic_category_t) OT_PT;
-      break;
-
-    case 0x1038u: case 0x1087u: case 0x1088u: case 0x1089u:
-    case 0x108Au: case 0x108Bu: case 0x108Cu: case 0x108Du:
-    case 0x108Fu: case 0x109Au: case 0x109Bu: case 0x109Cu:
-      cat = (indic_category_t) OT_SM;
-      break;
-
-    case 0x104Au: case 0x104Bu:
-      cat = (indic_category_t) OT_P;
-      break;
-
-    case 0xAA74u: case 0xAA75u: case 0xAA76u:
-      /* https://github.com/roozbehp/unicode-data/issues/3 */
-      cat = (indic_category_t) OT_C;
-      break;
-  }
-
-  if (cat == OT_M)
-  {
-    switch ((int) pos)
-    {
-      case POS_PRE_C:   cat = (indic_category_t) OT_VPre;
-                        pos = POS_PRE_M;                  break;
-      case POS_ABOVE_C: cat = (indic_category_t) OT_VAbv; break;
-      case POS_BELOW_C: cat = (indic_category_t) OT_VBlw; break;
-      case POS_POST_C:  cat = (indic_category_t) OT_VPst; break;
-    }
-  }
-
-  info.myanmar_category() = (myanmar_category_t) cat;
-  info.myanmar_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-myanmar-private.hh"
+#include "hb-ot-shape-complex-myanmar.hh"
 
 
 /*
@@ -36,7 +36,7 @@
 {
   /*
    * Basic features.
-   * These features are applied in order, one at a time, after initial_reordering.
+   * These features are applied in order, one at a time, after reordering.
    */
   HB_TAG('r','p','h','f'),
   HB_TAG('p','r','e','f'),
@@ -48,13 +48,20 @@
 {
   /*
    * Other features.
-   * These features are applied all at once, after final_reordering.
+   * These features are applied all at once, after clearing syllables.
    */
   HB_TAG('p','r','e','s'),
   HB_TAG('a','b','v','s'),
   HB_TAG('b','l','w','s'),
   HB_TAG('p','s','t','s'),
-  /* Positioning features, though we don't care about the types. */
+};
+static const hb_tag_t
+positioning_features[] =
+{
+  /*
+   * Positioning features.
+   * We don't care about the types.
+   */
   HB_TAG('d','i','s','t'),
   /* Pre-release version of Windows 8 Myanmar font had abvm,blwm
    * features.  The released Windows 8 version of the font (as well
@@ -73,13 +80,13 @@
                  hb_font_t *font,
                  hb_buffer_t *buffer);
 static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-                    hb_font_t *font,
-                    hb_buffer_t *buffer);
+reorder (const hb_ot_shape_plan_t *plan,
+         hb_font_t *font,
+         hb_buffer_t *buffer);
 static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-                  hb_font_t *font,
-                  hb_buffer_t *buffer);
+clear_syllables (const hb_ot_shape_plan_t *plan,
+                 hb_font_t *font,
+                 hb_buffer_t *buffer);
 
 static void
 collect_features_myanmar (hb_ot_shape_planner_t *plan)
@@ -89,27 +96,33 @@
   /* Do this before any lookups have been applied. */
   map->add_gsub_pause (setup_syllables);
 
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('l','o','c','l'));
   /* The Indic specs do not require ccmp, but we apply it here since if
    * there is a use of it, it's typically at the beginning. */
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
 
 
-  map->add_gsub_pause (initial_reordering);
+  map->add_gsub_pause (reorder);
+
   for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
   {
-    map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
+    map->enable_feature (basic_features[i], F_MANUAL_ZWJ);
     map->add_gsub_pause (nullptr);
   }
-  map->add_gsub_pause (final_reordering);
+
+  map->add_gsub_pause (clear_syllables);
+
   for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
-    map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
+    map->enable_feature (other_features[i], F_MANUAL_ZWJ);
+
+  for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++)
+    map->enable_feature (positioning_features[i]);
 }
 
 static void
 override_features_myanmar (hb_ot_shape_planner_t *plan)
 {
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
+  plan->map.disable_feature (HB_TAG('l','i','g','a'));
 }
 
 
@@ -261,8 +274,8 @@
 }
 
 static void
-initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
-                             hb_face_t *face,
+initial_reordering_syllable (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                             hb_face_t *face HB_UNUSED,
                              hb_buffer_t *buffer,
                              unsigned int start, unsigned int end)
 {
@@ -330,57 +343,34 @@
     else
       buffer->next_glyph ();
   }
-
   buffer->swap_buffers ();
 }
 
 static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-                    hb_font_t *font,
-                    hb_buffer_t *buffer)
+reorder (const hb_ot_shape_plan_t *plan,
+         hb_font_t *font,
+         hb_buffer_t *buffer)
 {
   insert_dotted_circles (plan, font, buffer);
 
   foreach_syllable (buffer, start, end)
     initial_reordering_syllable (plan, font->face, buffer, start, end);
-}
-
-static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-                  hb_font_t *font HB_UNUSED,
-                  hb_buffer_t *buffer)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  /* Zero syllables now... */
-  for (unsigned int i = 0; i < count; i++)
-    info[i].syllable() = 0;
 
   HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category);
   HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position);
 }
 
-
-/* Uniscribe seems to have a shaper for 'mymr' that is like the
- * generic shaper, except that it zeros mark advances GDEF_LATE. */
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old =
+static void
+clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                 hb_font_t *font HB_UNUSED,
+                 hb_buffer_t *buffer)
 {
-  nullptr, /* collect_features */
-  nullptr, /* override_features */
-  nullptr, /* data_create */
-  nullptr, /* data_destroy */
-  nullptr, /* preprocess_text */
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
-  nullptr, /* decompose */
-  nullptr, /* compose */
-  nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
-  true, /* fallback_position */
-};
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+  for (unsigned int i = 0; i < count; i++)
+    info[i].syllable() = 0;
+}
+
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
 {
@@ -394,8 +384,30 @@
   nullptr, /* decompose */
   nullptr, /* compose */
   setup_masks_myanmar,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
   false, /* fallback_position */
 };
+
+
+/* Ugly Zawgyi encoding.
+ * Disable all auto processing.
+ * https://github.com/harfbuzz/harfbuzz/issues/1162 */
+const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_zawgyi =
+{
+  nullptr, /* collect_features */
+  nullptr, /* override_features */
+  nullptr, /* data_create */
+  nullptr, /* data_destroy */
+  nullptr, /* preprocess_text */
+  nullptr, /* postprocess_glyphs */
+  HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
+  nullptr, /* decompose */
+  nullptr, /* compose */
+  nullptr, /* setup_masks */
+  HB_TAG_NONE, /* gpos_tag */
+  nullptr, /* reorder_marks */
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
+  false, /* fallback_position */
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,171 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_HH
+#define HB_OT_SHAPE_COMPLEX_MYANMAR_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex-indic.hh"
+
+
+/* buffer var allocations */
+#define myanmar_category() indic_category() /* myanmar_category_t */
+#define myanmar_position() indic_position() /* myanmar_position_t */
+
+
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum myanmar_category_t {
+  OT_As  = 18,  /* Asat */
+  OT_D0  = 20, /* Digit zero */
+  OT_DB  = OT_N, /* Dot below */
+  OT_GB  = OT_PLACEHOLDER,
+  OT_MH  = 21, /* Various consonant medial types */
+  OT_MR  = 22, /* Various consonant medial types */
+  OT_MW  = 23, /* Various consonant medial types */
+  OT_MY  = 24, /* Various consonant medial types */
+  OT_PT  = 25, /* Pwo and other tones */
+  OT_VAbv = 26,
+  OT_VBlw = 27,
+  OT_VPre = 28,
+  OT_VPst = 29,
+  OT_VS   = 30, /* Variation selectors */
+  OT_P    = 31, /* Punctuation */
+  OT_D    = 32, /* Digits except zero */
+};
+
+
+static inline void
+set_myanmar_properties (hb_glyph_info_t &info)
+{
+  hb_codepoint_t u = info.codepoint;
+  unsigned int type = hb_indic_get_categories (u);
+  unsigned int cat = type & 0x7Fu;
+  indic_position_t pos = (indic_position_t) (type >> 8);
+
+  /* Myanmar
+   * https://docs.microsoft.com/en-us/typography/script-development/myanmar#analyze
+   */
+  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)))
+    cat = OT_VS;
+
+  switch (u)
+  {
+    case 0x104Eu:
+      cat = OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */
+      break;
+
+    case 0x002Du: case 0x00A0u: case 0x00D7u: case 0x2012u:
+    case 0x2013u: case 0x2014u: case 0x2015u: case 0x2022u:
+    case 0x25CCu: case 0x25FBu: case 0x25FCu: case 0x25FDu:
+    case 0x25FEu:
+      cat = OT_GB;
+      break;
+
+    case 0x1004u: case 0x101Bu: case 0x105Au:
+      cat = OT_Ra;
+      break;
+
+    case 0x1032u: case 0x1036u:
+      cat = OT_A;
+      break;
+
+    case 0x1039u:
+      cat = OT_H;
+      break;
+
+    case 0x103Au:
+      cat = OT_As;
+      break;
+
+    case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u:
+    case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u:
+    case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u:
+    case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u:
+    case 0x1097u: case 0x1098u: case 0x1099u:
+      cat = OT_D;
+      break;
+
+    case 0x1040u:
+      cat = OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
+      break;
+
+    case 0x103Eu: case 0x1060u:
+      cat = OT_MH;
+      break;
+
+    case 0x103Cu:
+      cat = OT_MR;
+      break;
+
+    case 0x103Du: case 0x1082u:
+      cat = OT_MW;
+      break;
+
+    case 0x103Bu: case 0x105Eu: case 0x105Fu:
+      cat = OT_MY;
+      break;
+
+    case 0x1063u: case 0x1064u: case 0x1069u: case 0x106Au:
+    case 0x106Bu: case 0x106Cu: case 0x106Du: case 0xAA7Bu:
+      cat = OT_PT;
+      break;
+
+    case 0x1038u: case 0x1087u: case 0x1088u: case 0x1089u:
+    case 0x108Au: case 0x108Bu: case 0x108Cu: case 0x108Du:
+    case 0x108Fu: case 0x109Au: case 0x109Bu: case 0x109Cu:
+      cat = OT_SM;
+      break;
+
+    case 0x104Au: case 0x104Bu:
+      cat = OT_P;
+      break;
+
+    case 0xAA74u: case 0xAA75u: case 0xAA76u:
+      /* https://github.com/roozbehp/unicode-data/issues/3 */
+      cat = OT_C;
+      break;
+  }
+
+  if (cat == OT_M)
+  {
+    switch ((int) pos)
+    {
+      case POS_PRE_C:   cat = OT_VPre;
+                        pos = POS_PRE_M; break;
+      case POS_ABOVE_C: cat = OT_VAbv;   break;
+      case POS_BELOW_C: cat = OT_VBlw;   break;
+      case POS_POST_C:  cat = OT_VPst;   break;
+    }
+  }
+
+  info.myanmar_category() = cat;
+  info.myanmar_position() = pos;
+}
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,406 +0,0 @@
-/*
- * Copyright © 2010,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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-private.hh"
-#include "hb-ot-shape-normalize-private.hh"
-
-
-
-/* buffer var allocations, used by complex shapers */
-#define complex_var_u8_0()      var2.u8[2]
-#define complex_var_u8_1()      var2.u8[3]
-
-
-#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32
-
-enum hb_ot_shape_zero_width_marks_type_t {
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
-};
-
-
-/* Master OT shaper list */
-#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
-  HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \
-  HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (khmer) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_old) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (tibetan) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (use) \
-  /* ^--- Add new shapers here */
-
-
-struct hb_ot_complex_shaper_t
-{
-  /* collect_features()
-   * Called during shape_plan().
-   * Shapers should use plan->map to add their features and callbacks.
-   * May be nullptr.
-   */
-  void (*collect_features) (hb_ot_shape_planner_t *plan);
-
-  /* override_features()
-   * Called during shape_plan().
-   * Shapers should use plan->map to override features and add callbacks after
-   * common features are added.
-   * May be nullptr.
-   */
-  void (*override_features) (hb_ot_shape_planner_t *plan);
-
-
-  /* data_create()
-   * Called at the end of shape_plan().
-   * Whatever shapers return will be accessible through plan->data later.
-   * If nullptr is returned, means a plan failure.
-   */
-  void *(*data_create) (const hb_ot_shape_plan_t *plan);
-
-  /* data_destroy()
-   * Called when the shape_plan is being destroyed.
-   * plan->data is passed here for destruction.
-   * If nullptr is returned, means a plan failure.
-   * May be nullptr.
-   */
-  void (*data_destroy) (void *data);
-
-
-  /* preprocess_text()
-   * Called during shape().
-   * Shapers can use to modify text before shaping starts.
-   * May be nullptr.
-   */
-  void (*preprocess_text) (const hb_ot_shape_plan_t *plan,
-                           hb_buffer_t              *buffer,
-                           hb_font_t                *font);
-
-  /* postprocess_glyphs()
-   * Called during shape().
-   * Shapers can use to modify glyphs after shaping ends.
-   * May be nullptr.
-   */
-  void (*postprocess_glyphs) (const hb_ot_shape_plan_t *plan,
-                              hb_buffer_t              *buffer,
-                              hb_font_t                *font);
-
-
-  hb_ot_shape_normalization_mode_t normalization_preference;
-
-  /* decompose()
-   * Called during shape()'s normalization.
-   * May be nullptr.
-   */
-  bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
-                     hb_codepoint_t  ab,
-                     hb_codepoint_t *a,
-                     hb_codepoint_t *b);
-
-  /* compose()
-   * Called during shape()'s normalization.
-   * May be nullptr.
-   */
-  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
-                   hb_codepoint_t  a,
-                   hb_codepoint_t  b,
-                   hb_codepoint_t *ab);
-
-  /* setup_masks()
-   * Called during shape().
-   * Shapers should use map to get feature masks and set on buffer.
-   * Shapers may NOT modify characters.
-   * May be nullptr.
-   */
-  void (*setup_masks) (const hb_ot_shape_plan_t *plan,
-                       hb_buffer_t              *buffer,
-                       hb_font_t                *font);
-
-  /* disable_otl()
-   * Called during shape().
-   * If set and returns true, GDEF/GSUB/GPOS of the font are ignored
-   * and fallback operations used.
-   * May be nullptr.
-   */
-  bool (*disable_otl) (const hb_ot_shape_plan_t *plan);
-
-  /* reorder_marks()
-   * Called during shape().
-   * Shapers can use to modify ordering of combining marks.
-   * May be nullptr.
-   */
-  void (*reorder_marks) (const hb_ot_shape_plan_t *plan,
-                         hb_buffer_t              *buffer,
-                         unsigned int              start,
-                         unsigned int              end);
-
-  hb_ot_shape_zero_width_marks_type_t zero_width_marks;
-
-  bool fallback_position;
-};
-
-#define HB_COMPLEX_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_complex_shaper_t _hb_ot_complex_shaper_##name;
-HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
-#undef HB_COMPLEX_SHAPER_IMPLEMENT
-
-
-static inline const hb_ot_complex_shaper_t *
-hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
-{
-  switch ((hb_tag_t) planner->props.script)
-  {
-    default:
-      return &_hb_ot_complex_shaper_default;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_ARABIC:
-
-    /* Unicode-3.0 additions */
-    case HB_SCRIPT_MONGOLIAN:
-    case HB_SCRIPT_SYRIAC:
-
-    /* Unicode-5.0 additions */
-    case HB_SCRIPT_NKO:
-    case HB_SCRIPT_PHAGS_PA:
-
-    /* Unicode-6.0 additions */
-    case HB_SCRIPT_MANDAIC:
-
-    /* Unicode-7.0 additions */
-    case HB_SCRIPT_MANICHAEAN:
-    case HB_SCRIPT_PSALTER_PAHLAVI:
-
-    /* Unicode-9.0 additions */
-    case HB_SCRIPT_ADLAM:
-
-    /* Unicode-11.0 additions */
-    case HB_SCRIPT_HANIFI_ROHINGYA:
-    case HB_SCRIPT_SOGDIAN:
-
-      /* For Arabic script, use the Arabic shaper even if no OT script tag was found.
-       * This is because we do fallback shaping for Arabic script (and not others).
-       * But note that Arabic shaping is applicable only to horizontal layout; for
-       * vertical text, just use the generic shaper instead. */
-      if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
-           planner->props.script == HB_SCRIPT_ARABIC) &&
-          HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
-        return &_hb_ot_complex_shaper_arabic;
-      else
-        return &_hb_ot_complex_shaper_default;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_THAI:
-    case HB_SCRIPT_LAO:
-
-      return &_hb_ot_complex_shaper_thai;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_HANGUL:
-
-      return &_hb_ot_complex_shaper_hangul;
-
-
-    /* Unicode-2.0 additions */
-    case HB_SCRIPT_TIBETAN:
-
-      return &_hb_ot_complex_shaper_tibetan;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_HEBREW:
-
-      return &_hb_ot_complex_shaper_hebrew;
-
-
-    /* ^--- Add new shapers here */
-
-#if 0
-    /* Unicode-4.1 additions */
-    case HB_SCRIPT_NEW_TAI_LUE:
-#endif
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_BENGALI:
-    case HB_SCRIPT_DEVANAGARI:
-    case HB_SCRIPT_GUJARATI:
-    case HB_SCRIPT_GURMUKHI:
-    case HB_SCRIPT_KANNADA:
-    case HB_SCRIPT_MALAYALAM:
-    case HB_SCRIPT_ORIYA:
-    case HB_SCRIPT_TAMIL:
-    case HB_SCRIPT_TELUGU:
-
-    /* Unicode-3.0 additions */
-    case HB_SCRIPT_SINHALA:
-
-      /* If the designer designed the font for the 'DFLT' script,
-       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
-       * Otherwise, use the specific shaper.
-       * Note that for some simple scripts, there may not be *any*
-       * GSUB/GPOS needed, so there may be no scripts found! */
-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
-          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
-        return &_hb_ot_complex_shaper_default;
-      else
-        return &_hb_ot_complex_shaper_indic;
-
-    case HB_SCRIPT_KHMER:
-      /* A number of Khmer fonts in the wild don't have a 'pref' feature,
-       * and as such won't shape properly via the Indic shaper;
-       * however, they typically have 'liga' / 'clig' features that implement
-       * the necessary "reordering" by means of ligature substitutions.
-       * So we send such pref-less fonts through the generic shaper instead. */
-      if (planner->map.found_script[0] &&
-          hb_ot_layout_language_find_feature (planner->face, HB_OT_TAG_GSUB,
-                                              planner->map.script_index[0],
-                                              planner->map.language_index[0],
-                                              HB_TAG ('p','r','e','f'),
-                                              nullptr))
-        return &_hb_ot_complex_shaper_khmer;
-      else
-        return &_hb_ot_complex_shaper_default;
-
-    case HB_SCRIPT_MYANMAR:
-      if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','2'))
-        return &_hb_ot_complex_shaper_myanmar;
-      else if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
-        return &_hb_ot_complex_shaper_myanmar_old;
-      else
-        return &_hb_ot_complex_shaper_default;
-
-
-    /* Unicode-2.0 additions */
-    //case HB_SCRIPT_TIBETAN:
-
-    /* Unicode-3.0 additions */
-    //case HB_SCRIPT_MONGOLIAN:
-    //case HB_SCRIPT_SINHALA:
-
-    /* Unicode-3.2 additions */
-    case HB_SCRIPT_BUHID:
-    case HB_SCRIPT_HANUNOO:
-    case HB_SCRIPT_TAGALOG:
-    case HB_SCRIPT_TAGBANWA:
-
-    /* Unicode-4.0 additions */
-    case HB_SCRIPT_LIMBU:
-    case HB_SCRIPT_TAI_LE:
-
-    /* Unicode-4.1 additions */
-    case HB_SCRIPT_BUGINESE:
-    case HB_SCRIPT_KHAROSHTHI:
-    case HB_SCRIPT_SYLOTI_NAGRI:
-    case HB_SCRIPT_TIFINAGH:
-
-    /* Unicode-5.0 additions */
-    case HB_SCRIPT_BALINESE:
-    //case HB_SCRIPT_NKO:
-    //case HB_SCRIPT_PHAGS_PA:
-
-    /* Unicode-5.1 additions */
-    case HB_SCRIPT_CHAM:
-    case HB_SCRIPT_KAYAH_LI:
-    case HB_SCRIPT_LEPCHA:
-    case HB_SCRIPT_REJANG:
-    case HB_SCRIPT_SAURASHTRA:
-    case HB_SCRIPT_SUNDANESE:
-
-    /* Unicode-5.2 additions */
-    case HB_SCRIPT_EGYPTIAN_HIEROGLYPHS:
-    case HB_SCRIPT_JAVANESE:
-    case HB_SCRIPT_KAITHI:
-    case HB_SCRIPT_MEETEI_MAYEK:
-    case HB_SCRIPT_TAI_THAM:
-    case HB_SCRIPT_TAI_VIET:
-
-    /* Unicode-6.0 additions */
-    case HB_SCRIPT_BATAK:
-    case HB_SCRIPT_BRAHMI:
-    //case HB_SCRIPT_MANDAIC:
-
-    /* Unicode-6.1 additions */
-    case HB_SCRIPT_CHAKMA:
-    case HB_SCRIPT_SHARADA:
-    case HB_SCRIPT_TAKRI:
-
-    /* Unicode-7.0 additions */
-    case HB_SCRIPT_DUPLOYAN:
-    case HB_SCRIPT_GRANTHA:
-    case HB_SCRIPT_KHOJKI:
-    case HB_SCRIPT_KHUDAWADI:
-    case HB_SCRIPT_MAHAJANI:
-    //case HB_SCRIPT_MANICHAEAN:
-    case HB_SCRIPT_MODI:
-    case HB_SCRIPT_PAHAWH_HMONG:
-    //case HB_SCRIPT_PSALTER_PAHLAVI:
-    case HB_SCRIPT_SIDDHAM:
-    case HB_SCRIPT_TIRHUTA:
-
-    /* Unicode-8.0 additions */
-    case HB_SCRIPT_AHOM:
-    //case HB_SCRIPT_MULTANI:
-
-    /* Unicode-9.0 additions */
-    case HB_SCRIPT_BHAIKSUKI:
-    case HB_SCRIPT_MARCHEN:
-    case HB_SCRIPT_NEWA:
-
-    /* Unicode-10.0 additions */
-    case HB_SCRIPT_MASARAM_GONDI:
-    case HB_SCRIPT_SOYOMBO:
-    case HB_SCRIPT_ZANABAZAR_SQUARE:
-
-    /* Unicode-11.0 additions */
-    case HB_SCRIPT_DOGRA:
-    case HB_SCRIPT_GUNJALA_GONDI:
-    case HB_SCRIPT_MAKASAR:
-
-      /* If the designer designed the font for the 'DFLT' script,
-       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
-       * Otherwise, use the specific shaper.
-       * Note that for some simple scripts, there may not be *any*
-       * GSUB/GPOS needed, so there may be no scripts found! */
-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
-          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
-        return &_hb_ot_complex_shaper_default;
-      else
-        return &_hb_ot_complex_shaper_use;
-  }
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-thai.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-thai.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-complex.hh"
 
 
 /* Thai / Lao shaper */
@@ -324,9 +324,9 @@
     }
 
     /* Is SARA AM. Decompose and reorder. */
-    hb_codepoint_t decomposed[2] = {hb_codepoint_t (NIKHAHIT_FROM_SARA_AM (u)),
-                                    hb_codepoint_t (SARA_AA_FROM_SARA_AM (u))};
-    buffer->replace_glyphs (1, 2, decomposed);
+    hb_glyph_info_t &nikhahit = buffer->output_glyph (NIKHAHIT_FROM_SARA_AM (u));
+    _hb_glyph_info_set_continuation (&nikhahit);
+    buffer->replace_glyph (SARA_AA_FROM_SARA_AM (u));
     if (unlikely (!buffer->successful))
       return;
 
@@ -376,7 +376,7 @@
   nullptr, /* decompose */
   nullptr, /* compose */
   nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   false,/* fallback_position */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-tibetan.cc	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright © 2010,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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-static const hb_tag_t tibetan_features[] =
-{
-  HB_TAG('a','b','v','s'),
-  HB_TAG('b','l','w','s'),
-  HB_TAG('a','b','v','m'),
-  HB_TAG('b','l','w','m'),
-  HB_TAG_NONE
-};
-
-static void
-collect_features_tibetan (hb_ot_shape_planner_t *plan)
-{
-  for (const hb_tag_t *script_features = tibetan_features; script_features && *script_features; script_features++)
-    plan->map.add_global_bool_feature (*script_features);
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan =
-{
-  collect_features_tibetan,
-  nullptr, /* override_features */
-  nullptr, /* data_create */
-  nullptr, /* data_destroy */
-  nullptr, /* preprocess_text */
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
-  nullptr, /* decompose */
-  nullptr, /* compose */
-  nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
-  true, /* fallback_position */
-};
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-machine.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-machine.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -31,232 +31,271 @@
 #ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 38 "hb-ot-shape-complex-use-machine.hh"
 static const unsigned char _use_syllable_machine_trans_keys[] = {
-        12u, 12u, 1u, 15u, 1u, 1u, 12u, 12u, 0u, 43u, 21u, 21u, 8u, 39u, 8u, 39u,
-        1u, 15u, 1u, 1u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u,
-        8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
-        8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 13u, 21u, 4u, 4u, 13u, 13u, 8u, 39u,
-        8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u,
-        8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
-        8u, 39u, 1u, 15u, 12u, 12u, 1u, 39u, 8u, 39u, 21u, 42u, 41u, 42u, 42u, 42u,
-        1u, 5u, 0
+        12u, 44u, 1u, 15u, 1u, 1u, 12u, 44u, 0u, 44u, 21u, 21u, 8u, 44u, 8u, 44u,
+        1u, 15u, 1u, 1u, 8u, 44u, 8u, 44u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u,
+        8u, 39u, 8u, 39u, 8u, 39u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u,
+        8u, 44u, 8u, 44u, 8u, 44u, 1u, 39u, 8u, 44u, 13u, 21u, 4u, 4u, 13u, 13u,
+        8u, 44u, 8u, 44u, 8u, 44u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u,
+        8u, 39u, 8u, 39u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u,
+        8u, 44u, 8u, 44u, 1u, 39u, 1u, 15u, 12u, 44u, 1u, 44u, 8u, 44u, 21u, 42u,
+        41u, 42u, 42u, 42u, 1u, 5u, 0
 };
 
 static const char _use_syllable_machine_key_spans[] = {
-        1, 15, 1, 1, 44, 1, 32, 32,
-        15, 1, 32, 32, 32, 19, 19, 19,
-        32, 32, 32, 32, 32, 32, 32, 32,
-        32, 32, 32, 32, 9, 1, 1, 32,
-        32, 32, 32, 19, 19, 19, 32, 32,
-        32, 32, 32, 32, 32, 32, 32, 32,
-        32, 15, 1, 39, 32, 22, 2, 1,
-        5
+        33, 15, 1, 33, 45, 1, 37, 37,
+        15, 1, 37, 37, 32, 19, 19, 19,
+        32, 32, 32, 37, 37, 37, 37, 37,
+        37, 37, 37, 39, 37, 9, 1, 1,
+        37, 37, 37, 32, 19, 19, 19, 32,
+        32, 32, 37, 37, 37, 37, 37, 37,
+        37, 37, 39, 15, 33, 44, 37, 22,
+        2, 1, 5
 };
 
 static const short _use_syllable_machine_index_offsets[] = {
-        0, 2, 18, 20, 22, 67, 69, 102,
-        135, 151, 153, 186, 219, 252, 272, 292,
-        312, 345, 378, 411, 444, 477, 510, 543,
-        576, 609, 642, 675, 708, 718, 720, 722,
-        755, 788, 821, 854, 874, 894, 914, 947,
-        980, 1013, 1046, 1079, 1112, 1145, 1178, 1211,
-        1244, 1277, 1293, 1295, 1335, 1368, 1391, 1394,
-        1396
+        0, 34, 50, 52, 86, 132, 134, 172,
+        210, 226, 228, 266, 304, 337, 357, 377,
+        397, 430, 463, 496, 534, 572, 610, 648,
+        686, 724, 762, 800, 840, 878, 888, 890,
+        892, 930, 968, 1006, 1039, 1059, 1079, 1099,
+        1132, 1165, 1198, 1236, 1274, 1312, 1350, 1388,
+        1426, 1464, 1502, 1542, 1558, 1592, 1637, 1675,
+        1698, 1701, 1703
 };
 
 static const char _use_syllable_machine_indicies[] = {
+        1, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
         1, 0, 3, 2, 2, 2, 2, 2,
         2, 2, 2, 2, 2, 2, 2, 2,
-        4, 2, 3, 2, 6, 5, 7, 8,
+        4, 2, 3, 2, 6, 5, 5, 5,
+        5, 5, 5, 5, 5, 5, 5, 5,
+        5, 5, 5, 5, 5, 5, 5, 5,
+        5, 5, 5, 5, 5, 5, 5, 5,
+        5, 5, 5, 5, 6, 5, 7, 8,
         9, 7, 10, 8, 9, 9, 11, 9,
         9, 3, 12, 9, 9, 13, 7, 7,
         14, 15, 9, 9, 16, 17, 18, 19,
         20, 21, 22, 16, 23, 24, 25, 26,
         27, 28, 9, 29, 30, 31, 9, 9,
-        9, 32, 9, 34, 33, 36, 35, 35,
-        37, 1, 35, 35, 38, 35, 35, 35,
-        35, 35, 39, 40, 41, 42, 43, 44,
-        45, 46, 40, 47, 39, 48, 49, 50,
-        51, 35, 52, 53, 54, 35, 36, 35,
-        35, 37, 1, 35, 35, 38, 35, 35,
-        35, 35, 35, 55, 40, 41, 42, 43,
-        44, 45, 46, 40, 47, 48, 48, 49,
-        50, 51, 35, 52, 53, 54, 35, 37,
-        56, 56, 56, 56, 56, 56, 56, 56,
-        56, 56, 56, 56, 56, 57, 56, 37,
-        56, 36, 35, 35, 37, 1, 35, 35,
-        38, 35, 35, 35, 35, 35, 35, 40,
-        41, 42, 43, 44, 45, 46, 40, 47,
-        48, 48, 49, 50, 51, 35, 52, 53,
-        54, 35, 36, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        40, 41, 42, 43, 44, 35, 35, 35,
-        35, 35, 35, 49, 50, 51, 35, 52,
-        53, 54, 35, 36, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 41, 42, 43, 44, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        52, 53, 54, 35, 36, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 42, 43, 44, 35,
-        36, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 43, 44, 35, 36, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 44, 35,
-        36, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        42, 43, 44, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 52, 53, 54,
-        35, 36, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 42, 43, 44, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 53,
-        54, 35, 36, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 42, 43, 44, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 54, 35, 36, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 41, 42, 43, 44, 35, 35,
-        35, 35, 35, 35, 49, 50, 51, 35,
-        52, 53, 54, 35, 36, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 41, 42, 43, 44, 35,
-        35, 35, 35, 35, 35, 35, 50, 51,
-        35, 52, 53, 54, 35, 36, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 41, 42, 43, 44,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        51, 35, 52, 53, 54, 35, 36, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 40, 41, 42, 43,
-        44, 35, 46, 40, 35, 35, 35, 49,
-        50, 51, 35, 52, 53, 54, 35, 36,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 40, 41, 42,
-        43, 44, 35, 58, 40, 35, 35, 35,
-        49, 50, 51, 35, 52, 53, 54, 35,
-        36, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 40, 41,
-        42, 43, 44, 35, 35, 40, 35, 35,
-        35, 49, 50, 51, 35, 52, 53, 54,
-        35, 36, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 40,
-        41, 42, 43, 44, 45, 46, 40, 35,
-        35, 35, 49, 50, 51, 35, 52, 53,
-        54, 35, 36, 35, 35, 37, 1, 35,
-        35, 38, 35, 35, 35, 35, 35, 35,
-        40, 41, 42, 43, 44, 45, 46, 40,
-        47, 35, 48, 49, 50, 51, 35, 52,
-        53, 54, 35, 36, 35, 35, 37, 1,
-        35, 35, 38, 35, 35, 35, 35, 35,
-        35, 40, 41, 42, 43, 44, 45, 46,
-        40, 47, 39, 48, 49, 50, 51, 35,
-        52, 53, 54, 35, 60, 59, 59, 59,
-        59, 59, 59, 59, 61, 59, 10, 62,
-        60, 59, 11, 63, 63, 3, 6, 63,
-        63, 64, 63, 63, 63, 63, 63, 65,
+        9, 32, 33, 9, 35, 34, 37, 36,
+        36, 38, 1, 36, 36, 39, 36, 36,
+        36, 36, 36, 40, 41, 42, 43, 44,
+        45, 46, 47, 41, 48, 40, 49, 50,
+        51, 52, 36, 53, 54, 55, 36, 36,
+        36, 36, 56, 36, 37, 36, 36, 38,
+        1, 36, 36, 39, 36, 36, 36, 36,
+        36, 57, 41, 42, 43, 44, 45, 46,
+        47, 41, 48, 49, 49, 50, 51, 52,
+        36, 53, 54, 55, 36, 36, 36, 36,
+        56, 36, 38, 58, 58, 58, 58, 58,
+        58, 58, 58, 58, 58, 58, 58, 58,
+        59, 58, 38, 58, 37, 36, 36, 38,
+        1, 36, 36, 39, 36, 36, 36, 36,
+        36, 36, 41, 42, 43, 44, 45, 46,
+        47, 41, 48, 49, 49, 50, 51, 52,
+        36, 53, 54, 55, 36, 36, 36, 36,
+        56, 36, 37, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        41, 42, 43, 44, 45, 36, 36, 36,
+        36, 36, 36, 50, 51, 52, 36, 53,
+        54, 55, 36, 36, 36, 36, 42, 36,
+        37, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 42,
+        43, 44, 45, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 53, 54, 55,
+        36, 37, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 43, 44, 45, 36, 37, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 44, 45,
+        36, 37, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 45, 36, 37, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 43, 44, 45,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 53, 54, 55, 36, 37, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 43, 44,
+        45, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 54, 55, 36, 37,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 43,
+        44, 45, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 55, 36,
+        37, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 42,
+        43, 44, 45, 36, 36, 36, 36, 36,
+        36, 50, 51, 52, 36, 53, 54, 55,
+        36, 36, 36, 36, 42, 36, 37, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 42, 43, 44,
+        45, 36, 36, 36, 36, 36, 36, 36,
+        51, 52, 36, 53, 54, 55, 36, 36,
+        36, 36, 42, 36, 37, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 42, 43, 44, 45, 36,
+        36, 36, 36, 36, 36, 36, 36, 52,
+        36, 53, 54, 55, 36, 36, 36, 36,
+        42, 36, 37, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        41, 42, 43, 44, 45, 36, 47, 41,
+        36, 36, 36, 50, 51, 52, 36, 53,
+        54, 55, 36, 36, 36, 36, 42, 36,
+        37, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 41, 42,
+        43, 44, 45, 36, 60, 41, 36, 36,
+        36, 50, 51, 52, 36, 53, 54, 55,
+        36, 36, 36, 36, 42, 36, 37, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 41, 42, 43, 44,
+        45, 36, 36, 41, 36, 36, 36, 50,
+        51, 52, 36, 53, 54, 55, 36, 36,
+        36, 36, 42, 36, 37, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 41, 42, 43, 44, 45, 46,
+        47, 41, 36, 36, 36, 50, 51, 52,
+        36, 53, 54, 55, 36, 36, 36, 36,
+        42, 36, 37, 36, 36, 38, 1, 36,
+        36, 39, 36, 36, 36, 36, 36, 36,
+        41, 42, 43, 44, 45, 46, 47, 41,
+        48, 36, 49, 50, 51, 52, 36, 53,
+        54, 55, 36, 36, 36, 36, 56, 36,
+        38, 58, 58, 58, 58, 58, 58, 37,
+        58, 58, 58, 58, 58, 58, 59, 58,
+        58, 58, 58, 58, 58, 58, 42, 43,
+        44, 45, 58, 58, 58, 58, 58, 58,
+        58, 58, 58, 58, 53, 54, 55, 58,
+        37, 36, 36, 38, 1, 36, 36, 39,
+        36, 36, 36, 36, 36, 36, 41, 42,
+        43, 44, 45, 46, 47, 41, 48, 40,
+        49, 50, 51, 52, 36, 53, 54, 55,
+        36, 36, 36, 36, 56, 36, 62, 61,
+        61, 61, 61, 61, 61, 61, 63, 61,
+        10, 64, 62, 61, 11, 65, 65, 3,
+        6, 65, 65, 66, 65, 65, 65, 65,
+        65, 67, 16, 17, 18, 19, 20, 21,
+        22, 16, 23, 25, 25, 26, 27, 28,
+        65, 29, 30, 31, 65, 65, 65, 65,
+        33, 65, 11, 65, 65, 3, 6, 65,
+        65, 66, 65, 65, 65, 65, 65, 65,
         16, 17, 18, 19, 20, 21, 22, 16,
-        23, 25, 25, 26, 27, 28, 63, 29,
-        30, 31, 63, 11, 63, 63, 3, 6,
-        63, 63, 64, 63, 63, 63, 63, 63,
-        63, 16, 17, 18, 19, 20, 21, 22,
-        16, 23, 25, 25, 26, 27, 28, 63,
-        29, 30, 31, 63, 11, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 16, 17, 18, 19, 20, 63,
-        63, 63, 63, 63, 63, 26, 27, 28,
-        63, 29, 30, 31, 63, 11, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 17, 18, 19, 20,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 29, 30, 31, 63, 11, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 18, 19,
-        20, 63, 11, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 19, 20, 63, 11, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        20, 63, 11, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 18, 19, 20, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 29,
-        30, 31, 63, 11, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 18, 19, 20, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 30, 31, 63, 11, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 18, 19, 20, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 31, 63, 11, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 17, 18, 19, 20,
-        63, 63, 63, 63, 63, 63, 26, 27,
-        28, 63, 29, 30, 31, 63, 11, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 17, 18, 19,
-        20, 63, 63, 63, 63, 63, 63, 63,
-        27, 28, 63, 29, 30, 31, 63, 11,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 17, 18,
-        19, 20, 63, 63, 63, 63, 63, 63,
-        63, 63, 28, 63, 29, 30, 31, 63,
-        11, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 16, 17,
-        18, 19, 20, 63, 22, 16, 63, 63,
-        63, 26, 27, 28, 63, 29, 30, 31,
-        63, 11, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 16,
-        17, 18, 19, 20, 63, 66, 16, 63,
-        63, 63, 26, 27, 28, 63, 29, 30,
-        31, 63, 11, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        16, 17, 18, 19, 20, 63, 63, 16,
-        63, 63, 63, 26, 27, 28, 63, 29,
-        30, 31, 63, 11, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 16, 17, 18, 19, 20, 21, 22,
-        16, 63, 63, 63, 26, 27, 28, 63,
-        29, 30, 31, 63, 11, 63, 63, 3,
-        6, 63, 63, 64, 63, 63, 63, 63,
-        63, 63, 16, 17, 18, 19, 20, 21,
-        22, 16, 23, 63, 25, 26, 27, 28,
-        63, 29, 30, 31, 63, 3, 67, 67,
-        67, 67, 67, 67, 67, 67, 67, 67,
-        67, 67, 67, 4, 67, 6, 67, 8,
-        63, 63, 63, 8, 63, 63, 11, 63,
-        63, 3, 6, 63, 63, 64, 63, 63,
-        63, 63, 63, 63, 16, 17, 18, 19,
-        20, 21, 22, 16, 23, 24, 25, 26,
-        27, 28, 63, 29, 30, 31, 63, 11,
-        63, 63, 3, 6, 63, 63, 64, 63,
-        63, 63, 63, 63, 63, 16, 17, 18,
+        23, 25, 25, 26, 27, 28, 65, 29,
+        30, 31, 65, 65, 65, 65, 33, 65,
+        11, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 16, 17,
+        18, 19, 20, 65, 65, 65, 65, 65,
+        65, 26, 27, 28, 65, 29, 30, 31,
+        65, 65, 65, 65, 17, 65, 11, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 17, 18, 19,
+        20, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 29, 30, 31, 65, 11,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 18,
+        19, 20, 65, 11, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 19, 20, 65, 11,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 20, 65, 11, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 18, 19, 20, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        29, 30, 31, 65, 11, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 18, 19, 20, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 30, 31, 65, 11, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 18, 19, 20,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 31, 65, 11, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 17, 18, 19,
+        20, 65, 65, 65, 65, 65, 65, 26,
+        27, 28, 65, 29, 30, 31, 65, 65,
+        65, 65, 17, 65, 11, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 17, 18, 19, 20, 65,
+        65, 65, 65, 65, 65, 65, 27, 28,
+        65, 29, 30, 31, 65, 65, 65, 65,
+        17, 65, 11, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 17, 18, 19, 20, 65, 65, 65,
+        65, 65, 65, 65, 65, 28, 65, 29,
+        30, 31, 65, 65, 65, 65, 17, 65,
+        11, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 16, 17,
+        18, 19, 20, 65, 22, 16, 65, 65,
+        65, 26, 27, 28, 65, 29, 30, 31,
+        65, 65, 65, 65, 17, 65, 11, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 16, 17, 18, 19,
+        20, 65, 68, 16, 65, 65, 65, 26,
+        27, 28, 65, 29, 30, 31, 65, 65,
+        65, 65, 17, 65, 11, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 16, 17, 18, 19, 20, 65,
+        65, 16, 65, 65, 65, 26, 27, 28,
+        65, 29, 30, 31, 65, 65, 65, 65,
+        17, 65, 11, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        16, 17, 18, 19, 20, 21, 22, 16,
+        65, 65, 65, 26, 27, 28, 65, 29,
+        30, 31, 65, 65, 65, 65, 17, 65,
+        11, 65, 65, 3, 6, 65, 65, 66,
+        65, 65, 65, 65, 65, 65, 16, 17,
+        18, 19, 20, 21, 22, 16, 23, 65,
+        25, 26, 27, 28, 65, 29, 30, 31,
+        65, 65, 65, 65, 33, 65, 3, 65,
+        65, 65, 65, 65, 65, 11, 65, 65,
+        65, 65, 65, 65, 4, 65, 65, 65,
+        65, 65, 65, 65, 17, 18, 19, 20,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 29, 30, 31, 65, 3, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 4, 69, 6, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 6, 69,
+        8, 65, 65, 65, 8, 65, 65, 11,
+        65, 65, 3, 6, 65, 65, 66, 65,
+        65, 65, 65, 65, 65, 16, 17, 18,
         19, 20, 21, 22, 16, 23, 24, 25,
-        26, 27, 28, 63, 29, 30, 31, 63,
-        69, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 69, 70, 68, 69,
-        70, 68, 70, 68, 8, 67, 67, 67,
-        8, 67, 0
+        26, 27, 28, 65, 29, 30, 31, 65,
+        65, 65, 65, 33, 65, 11, 65, 65,
+        3, 6, 65, 65, 66, 65, 65, 65,
+        65, 65, 65, 16, 17, 18, 19, 20,
+        21, 22, 16, 23, 24, 25, 26, 27,
+        28, 65, 29, 30, 31, 65, 65, 65,
+        65, 33, 65, 71, 70, 70, 70, 70,
+        70, 70, 70, 70, 70, 70, 70, 70,
+        70, 70, 70, 70, 70, 70, 70, 71,
+        72, 70, 71, 72, 70, 72, 70, 8,
+        69, 69, 69, 8, 69, 0
 };
 
 static const char _use_syllable_machine_trans_targs[] = {
-        4, 8, 4, 31, 2, 4, 1, 5,
-        6, 4, 28, 4, 49, 50, 51, 53,
-        33, 34, 35, 36, 37, 44, 45, 47,
-        52, 48, 41, 42, 43, 38, 39, 40,
-        56, 4, 4, 4, 4, 7, 0, 27,
-        11, 12, 13, 14, 15, 22, 23, 25,
-        26, 19, 20, 21, 16, 17, 18, 10,
-        4, 9, 24, 4, 29, 30, 4, 4,
-        3, 32, 46, 4, 4, 54, 55
+        4, 8, 4, 32, 2, 4, 1, 5,
+        6, 4, 29, 4, 51, 52, 53, 55,
+        34, 35, 36, 37, 38, 45, 46, 48,
+        54, 49, 42, 43, 44, 39, 40, 41,
+        58, 50, 4, 4, 4, 4, 7, 0,
+        28, 11, 12, 13, 14, 15, 22, 23,
+        25, 26, 19, 20, 21, 16, 17, 18,
+        27, 10, 4, 9, 24, 4, 30, 31,
+        4, 4, 3, 33, 47, 4, 4, 56,
+        57
 };
 
 static const char _use_syllable_machine_trans_actions[] = {
@@ -264,11 +303,12 @@
         7, 8, 0, 9, 10, 10, 3, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         3, 3, 0, 0, 0, 0, 0, 0,
-        0, 11, 12, 13, 14, 7, 0, 7,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        7, 0, 0, 0, 0, 0, 0, 7,
-        15, 0, 0, 16, 0, 0, 17, 18,
-        0, 3, 0, 19, 20, 0, 0
+        0, 3, 11, 12, 13, 14, 7, 0,
+        7, 0, 0, 0, 0, 0, 0, 0,
+        0, 7, 0, 0, 0, 0, 0, 0,
+        0, 7, 15, 0, 0, 16, 0, 0,
+        17, 18, 0, 3, 0, 19, 20, 0,
+        0
 };
 
 static const char _use_syllable_machine_to_state_actions[] = {
@@ -279,7 +319,7 @@
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0
+        0, 0, 0
 };
 
 static const char _use_syllable_machine_from_state_actions[] = {
@@ -290,18 +330,18 @@
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0
+        0, 0, 0
 };
 
 static const short _use_syllable_machine_eof_trans[] = {
-        1, 3, 3, 6, 0, 34, 36, 36,
-        57, 57, 36, 36, 36, 36, 36, 36,
-        36, 36, 36, 36, 36, 36, 36, 36,
-        36, 36, 36, 36, 60, 63, 60, 64,
-        64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64, 64,
-        64, 68, 68, 64, 64, 69, 69, 69,
-        68
+        1, 3, 3, 6, 0, 35, 37, 37,
+        59, 59, 37, 37, 37, 37, 37, 37,
+        37, 37, 37, 37, 37, 37, 37, 37,
+        37, 37, 37, 59, 37, 62, 65, 62,
+        66, 66, 66, 66, 66, 66, 66, 66,
+        66, 66, 66, 66, 66, 66, 66, 66,
+        66, 66, 66, 70, 70, 66, 66, 71,
+        71, 71, 70
 };
 
 static const int use_syllable_machine_start = 4;
@@ -315,15 +355,14 @@
 
 
 
-#line 141 "hb-ot-shape-complex-use-machine.rl"
+#line 143 "hb-ot-shape-complex-use-machine.rl"
 
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -331,11 +370,11 @@
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
 
-#line 339 "hb-ot-shape-complex-use-machine.hh"
+#line 378 "hb-ot-shape-complex-use-machine.hh"
         {
         cs = use_syllable_machine_start;
         ts = 0;
@@ -343,16 +382,15 @@
         act = 0;
         }
 
-#line 162 "hb-ot-shape-complex-use-machine.rl"
+#line 163 "hb-ot-shape-complex-use-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
 
-#line 356 "hb-ot-shape-complex-use-machine.hh"
+#line 394 "hb-ot-shape-complex-use-machine.hh"
         {
         int _slen;
         int _trans;
@@ -366,7 +404,7 @@
 #line 1 "NONE"
         {ts = p;}
         break;
-#line 370 "hb-ot-shape-complex-use-machine.hh"
+#line 408 "hb-ot-shape-complex-use-machine.hh"
         }
 
         _keys = _use_syllable_machine_trans_keys + (cs<<1);
@@ -389,59 +427,59 @@
         {te = p+1;}
         break;
         case 12:
-#line 130 "hb-ot-shape-complex-use-machine.rl"
+#line 132 "hb-ot-shape-complex-use-machine.rl"
         {te = p+1;{ found_syllable (independent_cluster); }}
         break;
         case 14:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 134 "hb-ot-shape-complex-use-machine.rl"
         {te = p+1;{ found_syllable (standard_cluster); }}
         break;
         case 9:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 138 "hb-ot-shape-complex-use-machine.rl"
         {te = p+1;{ found_syllable (broken_cluster); }}
         break;
         case 8:
-#line 137 "hb-ot-shape-complex-use-machine.rl"
+#line 139 "hb-ot-shape-complex-use-machine.rl"
         {te = p+1;{ found_syllable (non_cluster); }}
         break;
         case 11:
-#line 130 "hb-ot-shape-complex-use-machine.rl"
+#line 132 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (independent_cluster); }}
         break;
         case 15:
-#line 131 "hb-ot-shape-complex-use-machine.rl"
+#line 133 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (virama_terminated_cluster); }}
         break;
         case 13:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 134 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (standard_cluster); }}
         break;
         case 17:
-#line 133 "hb-ot-shape-complex-use-machine.rl"
+#line 135 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }}
         break;
         case 16:
-#line 134 "hb-ot-shape-complex-use-machine.rl"
+#line 136 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (numeral_cluster); }}
         break;
         case 20:
-#line 135 "hb-ot-shape-complex-use-machine.rl"
+#line 137 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (symbol_cluster); }}
         break;
         case 18:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 138 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (broken_cluster); }}
         break;
         case 19:
-#line 137 "hb-ot-shape-complex-use-machine.rl"
+#line 139 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (non_cluster); }}
         break;
         case 1:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 134 "hb-ot-shape-complex-use-machine.rl"
         {{p = ((te))-1;}{ found_syllable (standard_cluster); }}
         break;
         case 4:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 138 "hb-ot-shape-complex-use-machine.rl"
         {{p = ((te))-1;}{ found_syllable (broken_cluster); }}
         break;
         case 2:
@@ -459,16 +497,16 @@
         case 3:
 #line 1 "NONE"
         {te = p+1;}
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 138 "hb-ot-shape-complex-use-machine.rl"
         {act = 7;}
         break;
         case 10:
 #line 1 "NONE"
         {te = p+1;}
-#line 137 "hb-ot-shape-complex-use-machine.rl"
+#line 139 "hb-ot-shape-complex-use-machine.rl"
         {act = 8;}
         break;
-#line 472 "hb-ot-shape-complex-use-machine.hh"
+#line 510 "hb-ot-shape-complex-use-machine.hh"
         }
 
 _again:
@@ -477,7 +515,7 @@
 #line 1 "NONE"
         {ts = 0;}
         break;
-#line 481 "hb-ot-shape-complex-use-machine.hh"
+#line 519 "hb-ot-shape-complex-use-machine.hh"
         }
 
         if ( ++p != pe )
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright © 2015  Mozilla Foundation.
- * Copyright © 2015  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.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-#define USE_TABLE_ELEMENT_TYPE uint8_t
-
-/* Cateories used in the Universal Shaping Engine spec:
- * https://docs.microsoft.com/en-us/typography/script-development/use
- */
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum use_category_t {
-  USE_O         = 0,    /* OTHER */
-
-  USE_B         = 1,    /* BASE */
-  USE_IND       = 3,    /* BASE_IND */
-  USE_N         = 4,    /* BASE_NUM */
-  USE_GB        = 5,    /* BASE_OTHER */
-  USE_CGJ       = 6,    /* CGJ */
-//  USE_F               = 7,    /* CONS_FINAL */
-  USE_FM        = 8,    /* CONS_FINAL_MOD */
-//  USE_M               = 9,    /* CONS_MED */
-//  USE_CM      = 10,   /* CONS_MOD */
-  USE_SUB       = 11,   /* CONS_SUB */
-  USE_H         = 12,   /* HALANT */
-
-  USE_HN        = 13,   /* HALANT_NUM */
-  USE_ZWNJ      = 14,   /* Zero width non-joiner */
-  USE_ZWJ       = 15,   /* Zero width joiner */
-  USE_WJ        = 16,   /* Word joiner */
-  USE_Rsv       = 17,   /* Reserved characters */
-  USE_R         = 18,   /* REPHA */
-  USE_S         = 19,   /* SYM */
-//  USE_SM      = 20,   /* SYM_MOD */
-  USE_VS        = 21,   /* VARIATION_SELECTOR */
-//  USE_V       = 36,   /* VOWEL */
-//  USE_VM      = 40,   /* VOWEL_MOD */
-
-  USE_FAbv      = 24,   /* CONS_FINAL_ABOVE */
-  USE_FBlw      = 25,   /* CONS_FINAL_BELOW */
-  USE_FPst      = 26,   /* CONS_FINAL_POST */
-  USE_MAbv      = 27,   /* CONS_MED_ABOVE */
-  USE_MBlw      = 28,   /* CONS_MED_BELOW */
-  USE_MPst      = 29,   /* CONS_MED_POST */
-  USE_MPre      = 30,   /* CONS_MED_PRE */
-  USE_CMAbv     = 31,   /* CONS_MOD_ABOVE */
-  USE_CMBlw     = 32,   /* CONS_MOD_BELOW */
-  USE_VAbv      = 33,   /* VOWEL_ABOVE / VOWEL_ABOVE_BELOW / VOWEL_ABOVE_BELOW_POST / VOWEL_ABOVE_POST */
-  USE_VBlw      = 34,   /* VOWEL_BELOW / VOWEL_BELOW_POST */
-  USE_VPst      = 35,   /* VOWEL_POST   UIPC = Right */
-  USE_VPre      = 22,   /* VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST */
-  USE_VMAbv     = 37,   /* VOWEL_MOD_ABOVE */
-  USE_VMBlw     = 38,   /* VOWEL_MOD_BELOW */
-  USE_VMPst     = 39,   /* VOWEL_MOD_POST */
-  USE_VMPre     = 23,   /* VOWEL_MOD_PRE */
-  USE_SMAbv     = 41,   /* SYM_MOD_ABOVE */
-  USE_SMBlw     = 42,   /* SYM_MOD_BELOW */
-  USE_CS        = 43    /* CONS_WITH_STACKER */
-};
-
-HB_INTERNAL USE_TABLE_ELEMENT_TYPE
-hb_use_get_category (hb_codepoint_t u);
-
-#endif /* HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-table.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-table.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -15,8 +15,10 @@
  * UnicodeData.txt does not have a header.
  */
 
-#include "hb-ot-shape-complex-use-private.hh"
+#include "hb-ot-shape-complex-use.hh"
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
 #define B       USE_B   /* BASE */
 #define CGJ     USE_CGJ /* CGJ */
 #define CS      USE_CS  /* CONS_WITH_STACKER */
@@ -24,6 +26,7 @@
 #define GB      USE_GB  /* BASE_OTHER */
 #define H       USE_H   /* HALANT */
 #define HN      USE_HN  /* HALANT_NUM */
+#define HVM     USE_HVM /* HALANT_OR_VOWEL_MODIFIER */
 #define IND     USE_IND /* BASE_IND */
 #define N       USE_N   /* BASE_NUM */
 #define O       USE_O   /* OTHER */
@@ -54,6 +57,7 @@
 #define VMBlw   USE_VMBlw
 #define VMPst   USE_VMPst
 #define VMAbv   USE_VMAbv
+#pragma GCC diagnostic pop
 
 static const USE_TABLE_ELEMENT_TYPE use_table[] = {
 
@@ -101,7 +105,7 @@
   /* 0990 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 09A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 09B0 */     B,     O,     B,     O,     O,     O,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VPre,
-  /* 09C0 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,   IND,     O,
+  /* 09C0 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPst,  VPst,     H,   IND,     O,
   /* 09D0 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     B,     B,     O,     B,
   /* 09E0 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 09F0 */     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     B,     O,    FM,     O,
@@ -134,7 +138,7 @@
   /* 0B10 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0B20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 0B30 */     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VAbv,
-  /* 0B40 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,     O,     O,
+  /* 0B40 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPst,     O,     O,  VPst,  VPst,     H,     O,     O,
   /* 0B50 */     O,     O,     O,     O,     O,     O,  VAbv,  VAbv,     O,     O,     O,     O,     B,     B,     O,     B,
   /* 0B60 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0B70 */     O,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
@@ -145,7 +149,7 @@
   /* 0B90 */     B,     O,     B,     B,     B,     B,     O,     O,     O,     B,     B,     O,     B,     O,     B,     B,
   /* 0BA0 */     O,     O,     O,     B,     B,     O,     O,     O,     B,     B,     B,     O,     O,     O,     B,     B,
   /* 0BB0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,  VPst,  VPst,
-  /* 0BC0 */  VAbv,  VPst,  VPst,     O,     O,     O,  VPre,  VPre,  VPre,     O,  VPre,  VPre,  VPre,     H,     O,     O,
+  /* 0BC0 */  VAbv,  VPst,  VPst,     O,     O,     O,  VPre,  VPre,  VPre,     O,  VPst,  VPst,  VPst,     H,     O,     O,
   /* 0BD0 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 0BE0 */     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0BF0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
@@ -178,7 +182,7 @@
   /* 0D10 */     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0D20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0D30 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,     B,  VPst,  VPst,
-  /* 0D40 */  VPst,  VPst,  VPst,  VBlw,  VBlw,     O,  VPre,  VPre,  VPre,     O,  VPre,  VPre,  VPre,     H,     R,     O,
+  /* 0D40 */  VPst,  VPst,  VPst,  VBlw,  VBlw,     O,  VPre,  VPre,  VPre,     O,  VPst,  VPst,  VPst,     H,     R,     O,
   /* 0D50 */     O,     O,     O,     O,   IND,   IND,   IND,  VPst,     O,     O,     O,     O,     O,     O,     O,     B,
   /* 0D60 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0D70 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,   IND,   IND,   IND,   IND,   IND,   IND,
@@ -190,11 +194,28 @@
   /* 0DA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0DB0 */     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     O,     O,
   /* 0DC0 */     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     H,     O,     O,     O,     O,  VPst,
-  /* 0DD0 */  VPst,  VPst,  VAbv,  VAbv,  VBlw,     O,  VBlw,     O,  VPst,  VPre,  VPre,  VPre,  VPre,  VPre,  VPre,  VPst,
+  /* 0DD0 */  VPst,  VPst,  VAbv,  VAbv,  VBlw,     O,  VBlw,     O,  VPst,  VPre,  VPst,  VPre,  VPst,  VPst,  VPst,  VPst,
   /* 0DE0 */     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0DF0 */     O,     O,  VPst,  VPst,     O,     O,     O,     O,
 
-#define use_offset_0x1000u 1360
+#define use_offset_0x0f18u 1360
+
+
+  /* Tibetan */
+                                                                      VBlw,  VBlw,     O,     O,     O,     O,     O,     O,
+  /* 0F20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 0F30 */     B,     B,     B,     B,     O,    FM,     O,    FM,     O, CMAbv,     O,     O,     O,     O,  VPst,  VPre,
+  /* 0F40 */     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,
+  /* 0F50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 0F60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,
+  /* 0F70 */     O,  VBlw,  VBlw,  VAbv,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw, VMAbv, VMPst,
+  /* 0F80 */  VBlw,  VAbv, VMAbv, VMAbv,  VBlw,   IND, VMAbv, VMAbv,     B,     B,     B,     B,     B,   SUB,   SUB,   SUB,
+  /* 0F90 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
+  /* 0FA0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
+  /* 0FB0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,     O,     O,
+  /* 0FC0 */     O,     O,     O,     O,     O,     O,    FM,     O,
+
+#define use_offset_0x1000u 1536
 
 
   /* Myanmar */
@@ -210,7 +231,7 @@
   /* 1080 */     B,     B,  MBlw,  VPst,  VPre,  VAbv,  VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw,     B, VMPst,
   /* 1090 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B, VMPst, VMPst,  VPst,  VAbv,     O,     O,
 
-#define use_offset_0x1700u 1520
+#define use_offset_0x1700u 1696
 
 
   /* Tagalog */
@@ -238,12 +259,12 @@
   /* 1780 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1790 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 17A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 17B0 */     B,     B,     B,     B,     O,     O,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VPre,  VPre,
-  /* 17C0 */  VPre,  VPre,  VPre,  VPre,  VPre,  VPre, VMAbv, VMPst,  VPst, VMAbv, VMAbv,    FM,  FAbv, CMAbv,    FM,    FM,
+  /* 17B0 */     B,     B,     B,     B,     O,     O,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VPst,  VPst,
+  /* 17C0 */  VPst,  VPre,  VPre,  VPre,  VPst,  VPst, VMAbv, VMPst,  VPst, VMAbv, VMAbv,    FM,  FAbv, CMAbv,    FM,    FM,
   /* 17D0 */    FM,  VAbv,     H,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     B,  VAbv,     O,     O,
   /* 17E0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1900u 1760
+#define use_offset_0x1900u 1936
 
 
   /* Limbu */
@@ -287,7 +308,7 @@
   /* 1A80 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
   /* 1A90 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1b00u 2176
+#define use_offset_0x1b00u 2352
 
 
   /* Balinese */
@@ -296,7 +317,7 @@
   /* 1B10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1B20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1B30 */     B,     B,     B,     B, CMAbv,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VPre,  VPre,
-  /* 1B40 */  VPre,  VPre,  VAbv,  VAbv,     H,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
+  /* 1B40 */  VPst,  VPst,  VAbv,  VAbv,     H,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
   /* 1B50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
   /* 1B60 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
   /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
@@ -319,11 +340,11 @@
 
   /* 1C00 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1C10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1C20 */     B,     B,     B,     B,   SUB,   SUB,  VPst,  VPre,  VPre,  VPre,  VPst,  VPst,  VBlw,  FAbv,  FAbv,  FAbv,
+  /* 1C20 */     B,     B,     B,     B,   SUB,   SUB,  VPst,  VPre,  VPre,  VPst,  VPst,  VPst,  VBlw,  FAbv,  FAbv,  FAbv,
   /* 1C30 */  FAbv,  FAbv,  FAbv,  FAbv, VMPre, VMPre,    FM, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 1C40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     B,     B,     B,
 
-#define use_offset_0x1cd0u 2512
+#define use_offset_0x1cd0u 2688
 
 
   /* Vedic Extensions */
@@ -332,20 +353,20 @@
   /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw,     O,     O,     O,     O, VMBlw,     O,     O,
   /* 1CF0 */     O,     O, VMPst, VMPst, VMAbv,    CS,    CS, VMPst, VMAbv, VMAbv,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1df8u 2560
+#define use_offset_0x1df8u 2736
 
 
   /* Combining Diacritical Marks Supplement */
                                                                          O,     O,     O,    FM,     O,     O,     O,     O,
 
-#define use_offset_0x2008u 2568
+#define use_offset_0x2008u 2744
 
 
   /* General Punctuation */
                                                                          O,     O,     O,     O,  ZWNJ,   ZWJ,     O,     O,
   /* 2010 */    GB,    GB,    GB,    GB,    GB,     O,     O,     O,
 
-#define use_offset_0x2060u 2584
+#define use_offset_0x2060u 2760
 
   /* 2060 */    WJ,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
@@ -354,20 +375,20 @@
   /* 2070 */     O,     O,     O,     O,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 2080 */     O,     O,    FM,    FM,    FM,     O,     O,     O,
 
-#define use_offset_0x20f0u 2624
+#define use_offset_0x20f0u 2800
 
 
   /* Combining Diacritical Marks for Symbols */
 
   /* 20F0 */ VMAbv,     O,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x25c8u 2632
+#define use_offset_0x25c8u 2808
 
 
   /* Geometric Shapes */
                                                                          O,     O,     O,     O,    GB,     O,     O,     O,
 
-#define use_offset_0xa800u 2640
+#define use_offset_0xa800u 2816
 
 
   /* Syloti Nagri */
@@ -454,7 +475,7 @@
   /* AAE0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPre,  VBlw,  VAbv,  VPre,  VPst,
   /* AAF0 */     O,     O,     O,     O,     O, VMPst,     H,     O,
 
-#define use_offset_0xabc0u 3400
+#define use_offset_0xabc0u 3576
 
 
   /* Meetei Mayek */
@@ -464,14 +485,14 @@
   /* ABE0 */     B,     B,     B,  VPst,  VPst,  VAbv,  VPst,  VPst,  VBlw,  VPst,  VPst,     O, VMPst,  VBlw,     O,     O,
   /* ABF0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0xfe00u 3464
+#define use_offset_0xfe00u 3640
 
 
   /* Variation Selectors */
 
   /* FE00 */    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,
 
-#define use_offset_0x10a00u 3480
+#define use_offset_0x10a00u 3656
 
 
   /* Kharoshthi */
@@ -482,7 +503,7 @@
   /* 10A30 */     B,     B,     B,     B,     B,     B,     O,     O, CMAbv, CMBlw, CMBlw,     O,     O,     O,     O,     H,
   /* 10A40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11000u 3560
+#define use_offset_0x11000u 3736
 
 
   /* Brahmi */
@@ -491,7 +512,7 @@
   /* 11010 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11020 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11030 */     B,     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,
-  /* 11040 */  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,     H,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 11040 */  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,   HVM,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11050 */     O,     O,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,
   /* 11060 */     N,     N,     N,     N,     N,     N,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11070 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,    HN,
@@ -503,15 +524,15 @@
   /* 110A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 110B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VAbv,  VAbv,  VPst,  VPst,     H, CMBlw,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11100u 3752
+#define use_offset_0x11100u 3928
 
 
   /* Chakma */
 
   /* 11100 */ VMAbv, VMAbv, VMAbv,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11110 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11120 */     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VAbv,  VAbv,  VAbv,
-  /* 11130 */  VAbv,  VBlw,  VBlw,     H,  VAbv,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 11120 */     B,     B,     B,     B,     B,     B,     B,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VPre,  VBlw,  VAbv,  VAbv,
+  /* 11130 */  VBlw,  VAbv,  VAbv,     H, CMBlw,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11140 */     O,     O,     O,     O,     B,  VPst,  VPst,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
   /* Mahajani */
@@ -526,7 +547,7 @@
   /* 11190 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 111A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 111B0 */     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,
-  /* 111C0 */     H,     B,     R,     R,     O,     O,     O,     O,     O,    FM, CMBlw,  VAbv,  VBlw,     O,     O,     O,
+  /* 111C0 */     H,     B,     R,     R,     O,     O,     O,     O,    GB,  FBlw, CMBlw,  VAbv,  VBlw,     O,     O,     O,
   /* 111D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
   /* Sinhala Archaic Numbers */
@@ -541,7 +562,7 @@
   /* 11220 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,  VPst,  VPst,  VBlw,
   /* 11230 */  VAbv,  VAbv,  VAbv,  VAbv, VMAbv,     H, CMAbv, CMAbv,     O,     O,     O,     O,     O,     O, VMAbv,     O,
 
-#define use_offset_0x11280u 4072
+#define use_offset_0x11280u 4248
 
 
   /* Multani */
@@ -560,16 +581,16 @@
 
   /* Grantha */
 
-  /* 11300 */ VMAbv, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     B,
+  /* 11300 */ VMAbv, VMAbv, VMAbv, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     B,
   /* 11310 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11320 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 11330 */     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,     O, CMBlw, CMBlw,     B,  VPst,  VPst,
-  /* 11340 */  VAbv,  VPst,  VPst,  VPst,  VPst,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,     O,     O,
+  /* 11340 */  VAbv,  VPst,  VPst,  VPst,  VPst,     O,     O,  VPre,  VPre,     O,     O,  VPst,  VPst,   HVM,     O,     O,
   /* 11350 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     O,     O,     B,     B,
   /* 11360 */     B,     B,  VPst,  VPst,     O,     O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
   /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
 
-#define use_offset_0x11400u 4320
+#define use_offset_0x11400u 4496
 
 
   /* Newa */
@@ -588,11 +609,11 @@
   /* 11480 */     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11490 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 114A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 114B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VPre,  VAbv,  VPre,  VPre,  VPst,  VPre, VMAbv,
+  /* 114B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VPre,  VAbv,  VPst,  VPst,  VPst,  VPst, VMAbv,
   /* 114C0 */ VMAbv, VMPst,     H, CMBlw,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 114D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11580u 4544
+#define use_offset_0x11580u 4720
 
 
   /* Siddham */
@@ -600,7 +621,7 @@
   /* 11580 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11590 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 115A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,
-  /* 115B0 */  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,  VPre,  VPre, VMAbv, VMAbv, VMPst,     H,
+  /* 115B0 */  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPst,  VPst,  VPst, VMAbv, VMAbv, VMPst,     H,
   /* 115C0 */ CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 115D0 */     O,     O,     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,  VBlw,  VBlw,     O,     O,
   /* 115E0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
@@ -635,7 +656,7 @@
   /* 11720 */  VPst,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VAbv,  VBlw,  VAbv,  VAbv,  VAbv,     O,     O,     O,     O,
   /* 11730 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
 
-#define use_offset_0x11800u 4992
+#define use_offset_0x11800u 5168
 
 
   /* Dogra */
@@ -645,7 +666,7 @@
   /* 11820 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,
   /* 11830 */  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv, VMAbv, VMPst,     H, CMBlw,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11a00u 5056
+#define use_offset_0x11a00u 5232
 
 
   /* Zanabazar Square */
@@ -664,7 +685,7 @@
   /* 11A80 */     B,     B,     B,     B,     O,     O,     R,     R,     R,     R,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,
   /* 11A90 */  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw, VMAbv, VMPst, CMAbv,     H,     O,     O,     O,     B,     O,     O,
 
-#define use_offset_0x11c00u 5216
+#define use_offset_0x11c00u 5392
 
 
   /* Bhaiksuki */
@@ -673,7 +694,7 @@
   /* 11C10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11C20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,
   /* 11C30 */  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,     O,  VAbv,  VAbv,  VAbv,  VAbv, VMAbv, VMAbv, VMPst,     H,
-  /* 11C40 */     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 11C40 */     B,     O,     O,     O,    GB,    GB,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11C50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11C60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,
 
@@ -685,7 +706,7 @@
   /* 11CA0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
   /* 11CB0 */  VBlw,  VPre,  VBlw,  VAbv,  VPst, VMAbv, VMAbv,     O,
 
-#define use_offset_0x11d00u 5400
+#define use_offset_0x11d00u 5576
 
 
   /* Masaram Gondi */
@@ -705,7 +726,7 @@
   /* 11D90 */  VAbv,  VAbv,     O,  VPst,  VPst, VMAbv, VMPst,     H,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11DA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11ee0u 5576
+#define use_offset_0x11ee0u 5752
 
 
   /* Makasar */
@@ -713,7 +734,7 @@
   /* 11EE0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11EF0 */     B,     B,    GB,  VAbv,  VBlw,  VPre,  VPst,     O,
 
-}; /* Table items: 5600; occupancy: 73% */
+}; /* Table items: 5776; occupancy: 74% */
 
 USE_TABLE_ELEMENT_TYPE
 hb_use_get_category (hb_codepoint_t u)
@@ -725,6 +746,7 @@
       if (hb_in_range<hb_codepoint_t> (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u];
       if (hb_in_range<hb_codepoint_t> (u, 0x0348u, 0x034Fu)) return use_table[u - 0x0348u + use_offset_0x0348u];
       if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x0F18u, 0x0FC7u)) return use_table[u - 0x0F18u + use_offset_0x0f18u];
       break;
 
     case 0x1u:
@@ -782,6 +804,7 @@
 #undef GB
 #undef H
 #undef HN
+#undef HVM
 #undef IND
 #undef N
 #undef O
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -26,8 +26,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-use-private.hh"
-#include "hb-ot-shape-complex-arabic-private.hh"
+#include "hb-ot-shape-complex-use.hh"
+#include "hb-ot-shape-complex-arabic.hh"
+#include "hb-ot-shape-complex-vowel-constraints.hh"
 
 /* buffer var allocations */
 #define use_category() complex_var_u8_0()
@@ -79,14 +80,22 @@
 {
   /*
    * Other features.
-   * These features are applied all at once, after reordering.
+   * These features are applied all at once, after reordering and
+   * clearing syllables.
    */
   HB_TAG('a','b','v','s'),
   HB_TAG('b','l','w','s'),
   HB_TAG('h','a','l','n'),
   HB_TAG('p','r','e','s'),
   HB_TAG('p','s','t','s'),
-  /* Positioning features, though we don't care about the types. */
+};
+static const hb_tag_t
+positioning_features[] =
+{
+  /*
+   * Positioning features.
+   * We don't care about the types.
+   */
   HB_TAG('d','i','s','t'),
   HB_TAG('a','b','v','m'),
   HB_TAG('b','l','w','m'),
@@ -112,6 +121,10 @@
 reorder (const hb_ot_shape_plan_t *plan,
          hb_font_t *font,
          hb_buffer_t *buffer);
+static void
+clear_syllables (const hb_ot_shape_plan_t *plan,
+                 hb_font_t *font,
+                 hb_buffer_t *buffer);
 
 static void
 collect_features_use (hb_ot_shape_planner_t *plan)
@@ -122,39 +135,42 @@
   map->add_gsub_pause (setup_syllables);
 
   /* "Default glyph pre-processing group" */
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-  map->add_global_bool_feature (HB_TAG('n','u','k','t'));
-  map->add_global_bool_feature (HB_TAG('a','k','h','n'));
+  map->enable_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
+  map->enable_feature (HB_TAG('n','u','k','t'));
+  map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ);
 
   /* "Reordering group" */
   map->add_gsub_pause (clear_substitution_flags);
-  map->add_feature (HB_TAG('r','p','h','f'), 1, F_MANUAL_ZWJ);
+  map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ);
   map->add_gsub_pause (record_rphf);
   map->add_gsub_pause (clear_substitution_flags);
-  map->add_feature (HB_TAG('p','r','e','f'), 1, F_GLOBAL | F_MANUAL_ZWJ);
+  map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ);
   map->add_gsub_pause (record_pref);
 
   /* "Orthographic unit shaping group" */
   for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
-    map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
+    map->enable_feature (basic_features[i], F_MANUAL_ZWJ);
 
   map->add_gsub_pause (reorder);
+  map->add_gsub_pause (clear_syllables);
 
   /* "Topographical features" */
   for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++)
-    map->add_feature (arabic_features[i], 1, F_NONE);
+    map->add_feature (arabic_features[i]);
   map->add_gsub_pause (nullptr);
 
-  /* "Standard typographic presentation" and "Positional feature application" */
+  /* "Standard typographic presentation" */
   for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
-    map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
+    map->enable_feature (other_features[i], F_MANUAL_ZWJ);
+
+  /* "Positional feature application" */
+  for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++)
+    map->enable_feature (positioning_features[i]);
 }
 
 struct use_shape_plan_t
 {
-  ASSERT_POD ();
-
   hb_mask_t rphf_mask;
 
   arabic_shape_plan_t *arabic_plan;
@@ -361,7 +377,7 @@
 }
 
 static void
-clear_substitution_flags (const hb_ot_shape_plan_t *plan,
+clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED,
                           hb_font_t *font HB_UNUSED,
                           hb_buffer_t *buffer)
 {
@@ -373,7 +389,7 @@
 
 static void
 record_rphf (const hb_ot_shape_plan_t *plan,
-             hb_font_t *font,
+             hb_font_t *font HB_UNUSED,
              hb_buffer_t *buffer)
 {
   const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
@@ -395,8 +411,8 @@
 }
 
 static void
-record_pref (const hb_ot_shape_plan_t *plan,
-             hb_font_t *font,
+record_pref (const hb_ot_shape_plan_t *plan HB_UNUSED,
+             hb_font_t *font HB_UNUSED,
              hb_buffer_t *buffer)
 {
   hb_glyph_info_t *info = buffer->info;
@@ -416,7 +432,8 @@
 static inline bool
 is_halant (const hb_glyph_info_t &info)
 {
-  return info.use_category() == USE_H && !_hb_glyph_info_ligated (&info);
+  return (info.use_category() == USE_H || info.use_category() == USE_HVM) &&
+         !_hb_glyph_info_ligated (&info);
 }
 
 static void
@@ -433,19 +450,38 @@
 
   hb_glyph_info_t *info = buffer->info;
 
-#define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB))
+#define POST_BASE_FLAGS64 (FLAG64 (USE_FM) | \
+                           FLAG64 (USE_FAbv) | \
+                           FLAG64 (USE_FBlw) | \
+                           FLAG64 (USE_FPst) | \
+                           FLAG64 (USE_MAbv) | \
+                           FLAG64 (USE_MBlw) | \
+                           FLAG64 (USE_MPst) | \
+                           FLAG64 (USE_MPre) | \
+                           FLAG64 (USE_VAbv) | \
+                           FLAG64 (USE_VBlw) | \
+                           FLAG64 (USE_VPst) | \
+                           FLAG64 (USE_VPre) | \
+                           FLAG64 (USE_VMAbv) | \
+                           FLAG64 (USE_VMBlw) | \
+                           FLAG64 (USE_VMPst) | \
+                           FLAG64 (USE_VMPre))
 
   /* Move things forward. */
   if (info[start].use_category() == USE_R && end - start > 1)
   {
-    /* Got a repha.  Reorder it to after first base, before first halant. */
+    /* Got a repha.  Reorder it towards the end, but before the first post-base
+     * glyph. */
     for (unsigned int i = start + 1; i < end; i++)
-      if ((FLAG_UNSAFE (info[i].use_category()) & (BASE_FLAGS)) || is_halant (info[i]))
+    {
+      bool is_post_base_glyph = (FLAG64_UNSAFE (info[i].use_category()) & POST_BASE_FLAGS64) ||
+                                is_halant (info[i]);
+      if (is_post_base_glyph || i == end - 1)
       {
-        /* If we hit a halant, move before it; otherwise it's a base: move to it's
-         * place, and shift things in between backward. */
+        /* If we hit a post-base glyph, move before it; otherwise move to the
+         * end. Shift things in between backward. */
 
-        if (is_halant (info[i]))
+        if (is_post_base_glyph)
           i--;
 
         buffer->merge_clusters (start, i + 1);
@@ -455,21 +491,19 @@
 
         break;
       }
+    }
   }
 
   /* Move things back. */
-  unsigned int j = end;
+  unsigned int j = start;
   for (unsigned int i = start; i < end; i++)
   {
     uint32_t flag = FLAG_UNSAFE (info[i].use_category());
-    if ((flag & (BASE_FLAGS)) || is_halant (info[i]))
+    if (is_halant (info[i]))
     {
-      /* If we hit a halant, move after it; otherwise it's a base: move to it's
-       * place, and shift things in between backward. */
-      if (is_halant (info[i]))
-        j = i + 1;
-      else
-        j = i;
+      /* If we hit a halant, move after it; otherwise move to the beginning, and
+       * shift things in between forward. */
+      j = i + 1;
     }
     else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) &&
              /* Only move the first component of a MultipleSubst. */
@@ -536,7 +570,6 @@
     else
       buffer->next_glyph ();
   }
-
   buffer->swap_buffers ();
 }
 
@@ -547,36 +580,30 @@
 {
   insert_dotted_circles (plan, font, buffer);
 
-  hb_glyph_info_t *info = buffer->info;
-
   foreach_syllable (buffer, start, end)
     reorder_syllable (buffer, start, end);
 
-  /* Zero syllables now... */
-  unsigned int count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-    info[i].syllable() = 0;
-
   HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
 }
 
-static bool
-decompose_use (const hb_ot_shape_normalize_context_t *c,
-                hb_codepoint_t  ab,
-                hb_codepoint_t *a,
-                hb_codepoint_t *b)
+static void
+clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                 hb_font_t *font HB_UNUSED,
+                 hb_buffer_t *buffer)
 {
-  switch (ab)
-  {
-    /* Chakma:
-     * Special case where the Unicode decomp gives matras in the wrong order
-     * for cluster validation.
-     */
-    case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true;
-    case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true;
-  }
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+  for (unsigned int i = 0; i < count; i++)
+    info[i].syllable() = 0;
+}
+
 
-  return (bool) c->unicode->decompose (ab, a, b);
+static void
+preprocess_text_use (const hb_ot_shape_plan_t *plan,
+                     hb_buffer_t              *buffer,
+                     hb_font_t                *font)
+{
+  _hb_preprocess_text_vowel_constraints (plan, buffer, font);
 }
 
 static bool
@@ -599,13 +626,13 @@
   nullptr, /* override_features */
   data_create_use,
   data_destroy_use,
-  nullptr, /* preprocess_text */
+  preprocess_text_use,
   nullptr, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
-  decompose_use,
+  nullptr, /* decompose */
   compose_use,
   setup_masks_use,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
   false, /* fallback_position */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,100 @@
+/*
+ * Copyright © 2015  Mozilla Foundation.
+ * Copyright © 2015  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.
+ *
+ * Mozilla Author(s): Jonathan Kew
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_USE_HH
+#define HB_OT_SHAPE_COMPLEX_USE_HH
+
+#include "hb.hh"
+
+
+#include "hb-ot-shape-complex.hh"
+
+
+#define USE_TABLE_ELEMENT_TYPE uint8_t
+
+/* Cateories used in the Universal Shaping Engine spec:
+ * https://docs.microsoft.com/en-us/typography/script-development/use
+ */
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum use_category_t {
+  USE_O         = 0,    /* OTHER */
+
+  USE_B         = 1,    /* BASE */
+  USE_IND       = 3,    /* BASE_IND */
+  USE_N         = 4,    /* BASE_NUM */
+  USE_GB        = 5,    /* BASE_OTHER */
+  USE_CGJ       = 6,    /* CGJ */
+//  USE_F               = 7,    /* CONS_FINAL */
+  USE_FM        = 8,    /* CONS_FINAL_MOD */
+//  USE_M               = 9,    /* CONS_MED */
+//  USE_CM      = 10,   /* CONS_MOD */
+  USE_SUB       = 11,   /* CONS_SUB */
+  USE_H         = 12,   /* HALANT */
+
+  USE_HN        = 13,   /* HALANT_NUM */
+  USE_ZWNJ      = 14,   /* Zero width non-joiner */
+  USE_ZWJ       = 15,   /* Zero width joiner */
+  USE_WJ        = 16,   /* Word joiner */
+  USE_Rsv       = 17,   /* Reserved characters */
+  USE_R         = 18,   /* REPHA */
+  USE_S         = 19,   /* SYM */
+//  USE_SM      = 20,   /* SYM_MOD */
+  USE_VS        = 21,   /* VARIATION_SELECTOR */
+//  USE_V       = 36,   /* VOWEL */
+//  USE_VM      = 40,   /* VOWEL_MOD */
+
+  USE_FAbv      = 24,   /* CONS_FINAL_ABOVE */
+  USE_FBlw      = 25,   /* CONS_FINAL_BELOW */
+  USE_FPst      = 26,   /* CONS_FINAL_POST */
+  USE_MAbv      = 27,   /* CONS_MED_ABOVE */
+  USE_MBlw      = 28,   /* CONS_MED_BELOW */
+  USE_MPst      = 29,   /* CONS_MED_POST */
+  USE_MPre      = 30,   /* CONS_MED_PRE */
+  USE_CMAbv     = 31,   /* CONS_MOD_ABOVE */
+  USE_CMBlw     = 32,   /* CONS_MOD_BELOW */
+  USE_VAbv      = 33,   /* VOWEL_ABOVE / VOWEL_ABOVE_BELOW / VOWEL_ABOVE_BELOW_POST / VOWEL_ABOVE_POST */
+  USE_VBlw      = 34,   /* VOWEL_BELOW / VOWEL_BELOW_POST */
+  USE_VPst      = 35,   /* VOWEL_POST   UIPC = Right */
+  USE_VPre      = 22,   /* VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST */
+  USE_VMAbv     = 37,   /* VOWEL_MOD_ABOVE */
+  USE_VMBlw     = 38,   /* VOWEL_MOD_BELOW */
+  USE_VMPst     = 39,   /* VOWEL_MOD_POST */
+  USE_VMPre     = 23,   /* VOWEL_MOD_PRE */
+  USE_SMAbv     = 41,   /* SYM_MOD_ABOVE */
+  USE_SMBlw     = 42,   /* SYM_MOD_BELOW */
+  USE_CS        = 43,   /* CONS_WITH_STACKER */
+
+  /* https://github.com/harfbuzz/harfbuzz/issues/1102 */
+  USE_HVM       = 44,   /* HALANT_OR_VOWEL_MODIFIER */
+};
+
+HB_INTERNAL USE_TABLE_ELEMENT_TYPE
+hb_use_get_category (hb_codepoint_t u);
+
+#endif /* HB_OT_SHAPE_COMPLEX_USE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-vowel-constraints.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,437 @@
+/* == Start of generated functions == */
+/*
+ * The following functions are generated by running:
+ *
+ *   ./gen-vowel-constraints.py use Scripts.txt
+ *
+ * on files with these headers:
+ *
+ * # Copied from https://docs.microsoft.com/en-us/typography/script-development/use
+ * # On October 23, 2018; with documentd dated 02/07/2018.
+ *
+ * # Scripts-11.0.0.txt
+ * # Date: 2018-02-21, 05:34:31 GMT
+ */
+
+#include "hb-ot-shape-complex-vowel-constraints.hh"
+
+static void
+_output_dotted_circle (hb_buffer_t *buffer)
+{
+  hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu);
+  _hb_glyph_info_reset_continuation (&dottedcircle);
+}
+
+static void
+_output_with_dotted_circle (hb_buffer_t *buffer)
+{
+  _output_dotted_circle (buffer);
+  buffer->next_glyph ();
+}
+
+void
+_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                                       hb_buffer_t              *buffer,
+                                       hb_font_t                *font HB_UNUSED)
+{
+  /* UGLY UGLY UGLY business of adding dotted-circle in the middle of
+   * vowel-sequences that look like another vowel.  Data for each script
+   * collected from the USE script development spec.
+   *
+   * https://github.com/harfbuzz/harfbuzz/issues/1019
+   */
+  bool processed = false;
+  buffer->clear_output ();
+  unsigned int count = buffer->len;
+  switch ((unsigned) buffer->props.script)
+  {
+    case HB_SCRIPT_DEVANAGARI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0905u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x093Au: case 0x093Bu: case 0x093Eu: case 0x0945u:
+              case 0x0946u: case 0x0949u: case 0x094Au: case 0x094Bu:
+              case 0x094Cu: case 0x094Fu: case 0x0956u: case 0x0957u:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0906u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x093Au: case 0x0945u: case 0x0946u: case 0x0947u:
+              case 0x0948u:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0909u:
+            matched = 0x0941u == buffer->cur (1).codepoint;
+            break;
+          case 0x090Fu:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0945u: case 0x0946u: case 0x0947u:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0930u:
+            if (0x094Du == buffer->cur (1).codepoint &&
+                buffer->idx + 2 < count &&
+                0x0907u == buffer->cur (2).codepoint)
+            {
+              buffer->next_glyph ();
+              buffer->next_glyph ();
+              _output_dotted_circle (buffer);
+            }
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_BENGALI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0985u:
+            matched = 0x09BEu == buffer->cur (1).codepoint;
+            break;
+          case 0x098Bu:
+            matched = 0x09C3u == buffer->cur (1).codepoint;
+            break;
+          case 0x098Cu:
+            matched = 0x09E2u == buffer->cur (1).codepoint;
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_GURMUKHI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0A05u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0A3Eu: case 0x0A48u: case 0x0A4Cu:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0A72u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0A3Fu: case 0x0A40u: case 0x0A47u:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0A73u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0A41u: case 0x0A42u: case 0x0A4Bu:
+                matched = true;
+                break;
+            }
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_GUJARATI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0A85u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0ABEu: case 0x0AC5u: case 0x0AC7u: case 0x0AC8u:
+              case 0x0AC9u: case 0x0ACBu: case 0x0ACCu:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0AC5u:
+            matched = 0x0ABEu == buffer->cur (1).codepoint;
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_ORIYA:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0B05u:
+            matched = 0x0B3Eu == buffer->cur (1).codepoint;
+            break;
+          case 0x0B0Fu: case 0x0B13u:
+            matched = 0x0B57u == buffer->cur (1).codepoint;
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_TELUGU:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0C12u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0C4Cu: case 0x0C55u:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0C3Fu: case 0x0C46u: case 0x0C4Au:
+            matched = 0x0C55u == buffer->cur (1).codepoint;
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_KANNADA:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0C89u: case 0x0C8Bu:
+            matched = 0x0CBEu == buffer->cur (1).codepoint;
+            break;
+          case 0x0C92u:
+            matched = 0x0CCCu == buffer->cur (1).codepoint;
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_MALAYALAM:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0D07u: case 0x0D09u:
+            matched = 0x0D57u == buffer->cur (1).codepoint;
+            break;
+          case 0x0D0Eu:
+            matched = 0x0D46u == buffer->cur (1).codepoint;
+            break;
+          case 0x0D12u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0D3Eu: case 0x0D57u:
+                matched = true;
+                break;
+            }
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_SINHALA:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0D85u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0DCFu: case 0x0DD0u: case 0x0DD1u:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0D8Bu: case 0x0D8Fu: case 0x0D94u:
+            matched = 0x0DDFu == buffer->cur (1).codepoint;
+            break;
+          case 0x0D8Du:
+            matched = 0x0DD8u == buffer->cur (1).codepoint;
+            break;
+          case 0x0D91u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0DCAu: case 0x0DD9u: case 0x0DDAu: case 0x0DDCu:
+              case 0x0DDDu:
+                matched = true;
+                break;
+            }
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_BRAHMI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x11005u:
+            matched = 0x11038u == buffer->cur (1).codepoint;
+            break;
+          case 0x1100Bu:
+            matched = 0x1103Eu == buffer->cur (1).codepoint;
+            break;
+          case 0x1100Fu:
+            matched = 0x11042u == buffer->cur (1).codepoint;
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_KHUDAWADI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x112B0u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x112E0u: case 0x112E5u: case 0x112E6u: case 0x112E7u:
+              case 0x112E8u:
+                matched = true;
+                break;
+            }
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_TIRHUTA:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x11481u:
+            matched = 0x114B0u == buffer->cur (1).codepoint;
+            break;
+          case 0x1148Bu: case 0x1148Du:
+            matched = 0x114BAu == buffer->cur (1).codepoint;
+            break;
+          case 0x114AAu:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x114B5u: case 0x114B6u:
+                matched = true;
+                break;
+            }
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_MODI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x11600u: case 0x11601u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x11639u: case 0x1163Au:
+                matched = true;
+                break;
+            }
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_TAKRI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x11680u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x116ADu: case 0x116B4u: case 0x116B5u:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x11686u:
+            matched = 0x116B2u == buffer->cur (1).codepoint;
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    default:
+      break;
+  }
+  if (processed)
+  {
+    if (buffer->idx < count)
+      buffer->next_glyph ();
+    buffer->swap_buffers ();
+  }
+}
+
+/* == End of generated functions == */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-vowel-constraints.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH
+#define HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex.hh"
+
+HB_INTERNAL void
+_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan,
+                                       hb_buffer_t              *buffer,
+                                       hb_font_t                *font);
+
+#endif /* HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,394 @@
+/*
+ * Copyright © 2010,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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_HH
+#define HB_OT_SHAPE_COMPLEX_HH
+
+#include "hb.hh"
+
+#include "hb-ot-layout.hh"
+#include "hb-ot-shape.hh"
+#include "hb-ot-shape-normalize.hh"
+
+
+/* buffer var allocations, used by complex shapers */
+#define complex_var_u8_0()      var2.u8[2]
+#define complex_var_u8_1()      var2.u8[3]
+
+
+#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32
+
+enum hb_ot_shape_zero_width_marks_type_t {
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
+};
+
+
+/* Master OT shaper list */
+#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
+  HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \
+  HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (khmer) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_zawgyi) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (use) \
+  /* ^--- Add new shapers here */
+
+
+struct hb_ot_complex_shaper_t
+{
+  /* collect_features()
+   * Called during shape_plan().
+   * Shapers should use plan->map to add their features and callbacks.
+   * May be NULL.
+   */
+  void (*collect_features) (hb_ot_shape_planner_t *plan);
+
+  /* override_features()
+   * Called during shape_plan().
+   * Shapers should use plan->map to override features and add callbacks after
+   * common features are added.
+   * May be NULL.
+   */
+  void (*override_features) (hb_ot_shape_planner_t *plan);
+
+
+  /* data_create()
+   * Called at the end of shape_plan().
+   * Whatever shapers return will be accessible through plan->data later.
+   * If nullptr is returned, means a plan failure.
+   */
+  void *(*data_create) (const hb_ot_shape_plan_t *plan);
+
+  /* data_destroy()
+   * Called when the shape_plan is being destroyed.
+   * plan->data is passed here for destruction.
+   * If nullptr is returned, means a plan failure.
+   * May be NULL.
+   */
+  void (*data_destroy) (void *data);
+
+
+  /* preprocess_text()
+   * Called during shape().
+   * Shapers can use to modify text before shaping starts.
+   * May be NULL.
+   */
+  void (*preprocess_text) (const hb_ot_shape_plan_t *plan,
+                           hb_buffer_t              *buffer,
+                           hb_font_t                *font);
+
+  /* postprocess_glyphs()
+   * Called during shape().
+   * Shapers can use to modify glyphs after shaping ends.
+   * May be NULL.
+   */
+  void (*postprocess_glyphs) (const hb_ot_shape_plan_t *plan,
+                              hb_buffer_t              *buffer,
+                              hb_font_t                *font);
+
+
+  hb_ot_shape_normalization_mode_t normalization_preference;
+
+  /* decompose()
+   * Called during shape()'s normalization.
+   * May be NULL.
+   */
+  bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
+                     hb_codepoint_t  ab,
+                     hb_codepoint_t *a,
+                     hb_codepoint_t *b);
+
+  /* compose()
+   * Called during shape()'s normalization.
+   * May be NULL.
+   */
+  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
+                   hb_codepoint_t  a,
+                   hb_codepoint_t  b,
+                   hb_codepoint_t *ab);
+
+  /* setup_masks()
+   * Called during shape().
+   * Shapers should use map to get feature masks and set on buffer.
+   * Shapers may NOT modify characters.
+   * May be NULL.
+   */
+  void (*setup_masks) (const hb_ot_shape_plan_t *plan,
+                       hb_buffer_t              *buffer,
+                       hb_font_t                *font);
+
+  /* gpos_tag()
+   * If not HB_TAG_NONE, then must match found GPOS script tag for
+   * GPOS to be applied.  Otherwise, fallback positioning will be used.
+   */
+  hb_tag_t gpos_tag;
+
+  /* reorder_marks()
+   * Called during shape().
+   * Shapers can use to modify ordering of combining marks.
+   * May be NULL.
+   */
+  void (*reorder_marks) (const hb_ot_shape_plan_t *plan,
+                         hb_buffer_t              *buffer,
+                         unsigned int              start,
+                         unsigned int              end);
+
+  hb_ot_shape_zero_width_marks_type_t zero_width_marks;
+
+  bool fallback_position;
+};
+
+#define HB_COMPLEX_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_complex_shaper_t _hb_ot_complex_shaper_##name;
+HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
+#undef HB_COMPLEX_SHAPER_IMPLEMENT
+
+
+static inline const hb_ot_complex_shaper_t *
+hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
+{
+  switch ((hb_tag_t) planner->props.script)
+  {
+    default:
+      return &_hb_ot_complex_shaper_default;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_ARABIC:
+
+    /* Unicode-3.0 additions */
+    case HB_SCRIPT_MONGOLIAN:
+    case HB_SCRIPT_SYRIAC:
+
+    /* Unicode-5.0 additions */
+    case HB_SCRIPT_NKO:
+    case HB_SCRIPT_PHAGS_PA:
+
+    /* Unicode-6.0 additions */
+    case HB_SCRIPT_MANDAIC:
+
+    /* Unicode-7.0 additions */
+    case HB_SCRIPT_MANICHAEAN:
+    case HB_SCRIPT_PSALTER_PAHLAVI:
+
+    /* Unicode-9.0 additions */
+    case HB_SCRIPT_ADLAM:
+
+    /* Unicode-11.0 additions */
+    case HB_SCRIPT_HANIFI_ROHINGYA:
+    case HB_SCRIPT_SOGDIAN:
+
+      /* For Arabic script, use the Arabic shaper even if no OT script tag was found.
+       * This is because we do fallback shaping for Arabic script (and not others).
+       * But note that Arabic shaping is applicable only to horizontal layout; for
+       * vertical text, just use the generic shaper instead. */
+      if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
+           planner->props.script == HB_SCRIPT_ARABIC) &&
+          HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
+        return &_hb_ot_complex_shaper_arabic;
+      else
+        return &_hb_ot_complex_shaper_default;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_THAI:
+    case HB_SCRIPT_LAO:
+
+      return &_hb_ot_complex_shaper_thai;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_HANGUL:
+
+      return &_hb_ot_complex_shaper_hangul;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_HEBREW:
+
+      return &_hb_ot_complex_shaper_hebrew;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_BENGALI:
+    case HB_SCRIPT_DEVANAGARI:
+    case HB_SCRIPT_GUJARATI:
+    case HB_SCRIPT_GURMUKHI:
+    case HB_SCRIPT_KANNADA:
+    case HB_SCRIPT_MALAYALAM:
+    case HB_SCRIPT_ORIYA:
+    case HB_SCRIPT_TAMIL:
+    case HB_SCRIPT_TELUGU:
+
+    /* Unicode-3.0 additions */
+    case HB_SCRIPT_SINHALA:
+
+      /* If the designer designed the font for the 'DFLT' script,
+       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+       * Otherwise, use the specific shaper.
+       *
+       * If it's indy3 tag, send to USE. */
+      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
+        return &_hb_ot_complex_shaper_default;
+      else if ((planner->map.chosen_script[0] & 0x000000FF) == '3')
+        return &_hb_ot_complex_shaper_use;
+      else
+        return &_hb_ot_complex_shaper_indic;
+
+    case HB_SCRIPT_KHMER:
+        return &_hb_ot_complex_shaper_khmer;
+
+    case HB_SCRIPT_MYANMAR:
+      /* If the designer designed the font for the 'DFLT' script,
+       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+       * Otherwise, use the specific shaper.
+       *
+       * If designer designed for 'mymr' tag, also send to default
+       * shaper.  That's tag used from before Myanmar shaping spec
+       * was developed.  The shaping spec uses 'mym2' tag. */
+      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n') ||
+          planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
+        return &_hb_ot_complex_shaper_default;
+      else
+        return &_hb_ot_complex_shaper_myanmar;
+
+
+    /* https://github.com/harfbuzz/harfbuzz/issues/1162 */
+    case HB_SCRIPT_MYANMAR_ZAWGYI:
+
+      return &_hb_ot_complex_shaper_myanmar_zawgyi;
+
+
+    /* Unicode-2.0 additions */
+    case HB_SCRIPT_TIBETAN:
+
+    /* Unicode-3.0 additions */
+    //case HB_SCRIPT_MONGOLIAN:
+    //case HB_SCRIPT_SINHALA:
+
+    /* Unicode-3.2 additions */
+    case HB_SCRIPT_BUHID:
+    case HB_SCRIPT_HANUNOO:
+    case HB_SCRIPT_TAGALOG:
+    case HB_SCRIPT_TAGBANWA:
+
+    /* Unicode-4.0 additions */
+    case HB_SCRIPT_LIMBU:
+    case HB_SCRIPT_TAI_LE:
+
+    /* Unicode-4.1 additions */
+    case HB_SCRIPT_BUGINESE:
+    case HB_SCRIPT_KHAROSHTHI:
+    case HB_SCRIPT_SYLOTI_NAGRI:
+    case HB_SCRIPT_TIFINAGH:
+
+    /* Unicode-5.0 additions */
+    case HB_SCRIPT_BALINESE:
+    //case HB_SCRIPT_NKO:
+    //case HB_SCRIPT_PHAGS_PA:
+
+    /* Unicode-5.1 additions */
+    case HB_SCRIPT_CHAM:
+    case HB_SCRIPT_KAYAH_LI:
+    case HB_SCRIPT_LEPCHA:
+    case HB_SCRIPT_REJANG:
+    case HB_SCRIPT_SAURASHTRA:
+    case HB_SCRIPT_SUNDANESE:
+
+    /* Unicode-5.2 additions */
+    case HB_SCRIPT_EGYPTIAN_HIEROGLYPHS:
+    case HB_SCRIPT_JAVANESE:
+    case HB_SCRIPT_KAITHI:
+    case HB_SCRIPT_MEETEI_MAYEK:
+    case HB_SCRIPT_TAI_THAM:
+    case HB_SCRIPT_TAI_VIET:
+
+    /* Unicode-6.0 additions */
+    case HB_SCRIPT_BATAK:
+    case HB_SCRIPT_BRAHMI:
+    //case HB_SCRIPT_MANDAIC:
+
+    /* Unicode-6.1 additions */
+    case HB_SCRIPT_CHAKMA:
+    case HB_SCRIPT_SHARADA:
+    case HB_SCRIPT_TAKRI:
+
+    /* Unicode-7.0 additions */
+    case HB_SCRIPT_DUPLOYAN:
+    case HB_SCRIPT_GRANTHA:
+    case HB_SCRIPT_KHOJKI:
+    case HB_SCRIPT_KHUDAWADI:
+    case HB_SCRIPT_MAHAJANI:
+    //case HB_SCRIPT_MANICHAEAN:
+    case HB_SCRIPT_MODI:
+    case HB_SCRIPT_PAHAWH_HMONG:
+    //case HB_SCRIPT_PSALTER_PAHLAVI:
+    case HB_SCRIPT_SIDDHAM:
+    case HB_SCRIPT_TIRHUTA:
+
+    /* Unicode-8.0 additions */
+    case HB_SCRIPT_AHOM:
+
+    /* Unicode-9.0 additions */
+    //case HB_SCRIPT_ADLAM:
+    case HB_SCRIPT_BHAIKSUKI:
+    case HB_SCRIPT_MARCHEN:
+    case HB_SCRIPT_NEWA:
+
+    /* Unicode-10.0 additions */
+    case HB_SCRIPT_MASARAM_GONDI:
+    case HB_SCRIPT_SOYOMBO:
+    case HB_SCRIPT_ZANABAZAR_SQUARE:
+
+    /* Unicode-11.0 additions */
+    case HB_SCRIPT_DOGRA:
+    case HB_SCRIPT_GUNJALA_GONDI:
+    //case HB_SCRIPT_HANIFI_ROHINGYA:
+    case HB_SCRIPT_MAKASAR:
+    //case HB_SCRIPT_SOGDIAN:
+
+      /* If the designer designed the font for the 'DFLT' script,
+       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+       * Otherwise, use the specific shaper.
+       * Note that for some simple scripts, there may not be *any*
+       * GSUB/GPOS needed, so there may be no scripts found! */
+      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
+        return &_hb_ot_complex_shaper_default;
+      else
+        return &_hb_ot_complex_shaper_use;
+  }
+}
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright © 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_FALLBACK_PRIVATE_HH
-#define HB_OT_SHAPE_FALLBACK_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-private.hh"
-
-
-HB_INTERNAL void _hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
-                                                 hb_font_t *font,
-                                                 hb_buffer_t  *buffer);
-
-HB_INTERNAL void _hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan,
-                                                                    hb_font_t *font,
-                                                                    hb_buffer_t  *buffer);
-
-
-HB_INTERNAL void _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
-                                             hb_font_t *font,
-                                             hb_buffer_t  *buffer);
-
-HB_INTERNAL void _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
-                                               hb_font_t *font,
-                                               hb_buffer_t  *buffer);
-
-
-#endif /* HB_OT_SHAPE_FALLBACK_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,8 +24,8 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-fallback-private.hh"
-#include "hb-ot-layout-gsubgpos-private.hh"
+#include "hb-ot-shape-fallback.hh"
+#include "hb-kern.hh"
 
 static unsigned int
 recategorize_combining_class (hb_codepoint_t u,
@@ -162,9 +162,9 @@
 }
 
 void
-_hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
-                                                   hb_font_t *font HB_UNUSED,
-                                                   hb_buffer_t  *buffer)
+_hb_ot_shape_fallback_mark_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                                                        hb_font_t *font HB_UNUSED,
+                                                        hb_buffer_t  *buffer)
 {
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
@@ -180,19 +180,25 @@
 static void
 zero_mark_advances (hb_buffer_t *buffer,
                     unsigned int start,
-                    unsigned int end)
+                    unsigned int end,
+                    bool adjust_offsets_when_zeroing)
 {
   hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = start; i < end; i++)
     if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
     {
+      if (adjust_offsets_when_zeroing)
+      {
+        buffer->pos[i].x_offset -= buffer->pos[i].x_advance;
+        buffer->pos[i].y_offset -= buffer->pos[i].y_advance;
+      }
       buffer->pos[i].x_advance = 0;
       buffer->pos[i].y_advance = 0;
     }
 }
 
 static inline void
-position_mark (const hb_ot_shape_plan_t *plan,
+position_mark (const hb_ot_shape_plan_t *plan HB_UNUSED,
                hb_font_t *font,
                hb_buffer_t  *buffer,
                hb_glyph_extents_t &base_extents,
@@ -303,7 +309,8 @@
                       hb_font_t *font,
                       hb_buffer_t  *buffer,
                       unsigned int base,
-                      unsigned int end)
+                      unsigned int end,
+                      bool adjust_offsets_when_zeroing)
 {
   hb_direction_t horiz_dir = HB_DIRECTION_INVALID;
 
@@ -314,11 +321,15 @@
                                 &base_extents))
   {
     /* If extents don't work, zero marks and go home. */
-    zero_mark_advances (buffer, base + 1, end);
+    zero_mark_advances (buffer, base + 1, end, adjust_offsets_when_zeroing);
     return;
   }
-  base_extents.x_bearing += buffer->pos[base].x_offset;
   base_extents.y_bearing += buffer->pos[base].y_offset;
+  /* Use horizontal advance for horizontal positioning.
+   * Generally a better idea.  Also works for zero-ink glyphs.  See:
+   * https://github.com/harfbuzz/harfbuzz/issues/1532 */
+  base_extents.x_bearing = 0;
+  base_extents.width = font->get_glyph_h_advance (buffer->info[base].codepoint);
 
   unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[base]);
   /* Use integer for num_lig_components such that it doesn't convert to unsigned
@@ -394,7 +405,8 @@
                   hb_font_t *font,
                   hb_buffer_t  *buffer,
                   unsigned int start,
-                  unsigned int end)
+                  unsigned int end,
+                  bool adjust_offsets_when_zeroing)
 {
   if (end - start < 2)
     return;
@@ -410,16 +422,17 @@
         if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[j])))
           break;
 
-      position_around_base (plan, font, buffer, i, j);
+      position_around_base (plan, font, buffer, i, j, adjust_offsets_when_zeroing);
 
       i = j - 1;
     }
 }
 
 void
-_hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
-                                hb_font_t *font,
-                                hb_buffer_t  *buffer)
+_hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
+                                     hb_font_t *font,
+                                     hb_buffer_t  *buffer,
+                                     bool adjust_offsets_when_zeroing)
 {
   _hb_buffer_assert_gsubgpos_vars (buffer);
 
@@ -428,81 +441,66 @@
   hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 1; i < count; i++)
     if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) {
-      position_cluster (plan, font, buffer, start, i);
+      position_cluster (plan, font, buffer, start, i, adjust_offsets_when_zeroing);
       start = i;
     }
-  position_cluster (plan, font, buffer, start, count);
+  position_cluster (plan, font, buffer, start, count, adjust_offsets_when_zeroing);
 }
 
 
-/* Performs old-style TrueType kerning. */
+struct hb_ot_shape_fallback_kern_driver_t
+{
+  hb_ot_shape_fallback_kern_driver_t (hb_font_t   *font_,
+                                      hb_buffer_t *buffer) :
+    font (font_), direction (buffer->props.direction) {}
+
+  hb_position_t get_kerning (hb_codepoint_t first, hb_codepoint_t second) const
+  {
+    hb_position_t kern = 0;
+    font->get_glyph_kerning_for_direction (first, second,
+                                           direction,
+                                           &kern, &kern);
+    return kern;
+  }
+
+  hb_font_t *font;
+  hb_direction_t direction;
+};
+
+/* Performs font-assisted kerning. */
 void
 _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
                             hb_font_t *font,
-                            hb_buffer_t  *buffer)
+                            hb_buffer_t *buffer)
 {
-  if (!plan->has_kern) return;
-
-  OT::hb_ot_apply_context_t c (1, font, buffer);
-  c.set_lookup_mask (plan->kern_mask);
-  c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
-  OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
-  skippy_iter.init (&c);
+  if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
+      !font->has_glyph_h_kerning_func () :
+      !font->has_glyph_v_kerning_func ())
+    return;
 
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  hb_glyph_position_t *pos = buffer->pos;
-  for (unsigned int idx = 0; idx < count;)
-  {
-    skippy_iter.reset (idx, 1);
-    if (!skippy_iter.next ())
-    {
-      idx++;
-      continue;
-    }
+  bool reverse = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
 
-    hb_position_t x_kern, y_kern;
-    font->get_glyph_kerning_for_direction (info[idx].codepoint,
-                                           info[skippy_iter.idx].codepoint,
-                                           buffer->props.direction,
-                                           &x_kern, &y_kern);
+  if (reverse)
+    buffer->reverse ();
 
-    if (x_kern)
-    {
-      hb_position_t kern1 = x_kern >> 1;
-      hb_position_t kern2 = x_kern - kern1;
-      pos[idx].x_advance += kern1;
-      pos[skippy_iter.idx].x_advance += kern2;
-      pos[skippy_iter.idx].x_offset += kern2;
-      buffer->unsafe_to_break (idx, skippy_iter.idx + 1);
-    }
+  hb_ot_shape_fallback_kern_driver_t driver (font, buffer);
+  OT::hb_kern_machine_t<hb_ot_shape_fallback_kern_driver_t> machine (driver);
+  machine.kern (font, buffer, plan->kern_mask, false);
 
-    if (y_kern)
-    {
-      hb_position_t kern1 = y_kern >> 1;
-      hb_position_t kern2 = y_kern - kern1;
-      pos[idx].y_advance += kern1;
-      pos[skippy_iter.idx].y_advance += kern2;
-      pos[skippy_iter.idx].y_offset += kern2;
-      buffer->unsafe_to_break (idx, skippy_iter.idx + 1);
-    }
-
-    idx = skippy_iter.idx;
-  }
+  if (reverse)
+    buffer->reverse ();
 }
 
 
 /* Adjusts width of various spaces. */
 void
-_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
+_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan HB_UNUSED,
                               hb_font_t *font,
                               hb_buffer_t  *buffer)
 {
-  if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
-    return;
-
   hb_glyph_info_t *info = buffer->info;
   hb_glyph_position_t *pos = buffer->pos;
+  bool horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction);
   unsigned int count = buffer->len;
   for (unsigned int i = 0; i < count; i++)
     if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i]))
@@ -523,27 +521,40 @@
         case t::SPACE_EM_5:
         case t::SPACE_EM_6:
         case t::SPACE_EM_16:
-          pos[i].x_advance = (font->x_scale + ((int) space_type)/2) / (int) space_type;
+          if (horizontal)
+            pos[i].x_advance = +(font->x_scale + ((int) space_type)/2) / (int) space_type;
+          else
+            pos[i].y_advance = -(font->y_scale + ((int) space_type)/2) / (int) space_type;
           break;
 
         case t::SPACE_4_EM_18:
-          pos[i].x_advance = (int64_t) font->x_scale * 4 / 18;
+          if (horizontal)
+            pos[i].x_advance = (int64_t) +font->x_scale * 4 / 18;
+          else
+            pos[i].y_advance = (int64_t) -font->y_scale * 4 / 18;
           break;
 
         case t::SPACE_FIGURE:
           for (char u = '0'; u <= '9'; u++)
             if (font->get_nominal_glyph (u, &glyph))
             {
-              pos[i].x_advance = font->get_glyph_h_advance (glyph);
+              if (horizontal)
+                pos[i].x_advance = font->get_glyph_h_advance (glyph);
+              else
+                pos[i].y_advance = font->get_glyph_v_advance (glyph);
               break;
             }
           break;
 
         case t::SPACE_PUNCTUATION:
-          if (font->get_nominal_glyph ('.', &glyph))
-            pos[i].x_advance = font->get_glyph_h_advance (glyph);
-          else if (font->get_nominal_glyph (',', &glyph))
-            pos[i].x_advance = font->get_glyph_h_advance (glyph);
+          if (font->get_nominal_glyph ('.', &glyph) ||
+              font->get_nominal_glyph (',', &glyph))
+          {
+            if (horizontal)
+              pos[i].x_advance = font->get_glyph_h_advance (glyph);
+            else
+              pos[i].y_advance = font->get_glyph_v_advance (glyph);
+          }
           break;
 
         case t::SPACE_NARROW:
@@ -552,7 +563,10 @@
            * However, in my testing, many fonts have their regular space being about that
            * size.  To me, a percentage of the space width makes more sense.  Half is as
            * good as any. */
-          pos[i].x_advance /= 2;
+          if (horizontal)
+            pos[i].x_advance /= 2;
+          else
+            pos[i].y_advance /= 2;
           break;
       }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_FALLBACK_HH
+#define HB_OT_SHAPE_FALLBACK_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape.hh"
+
+
+HB_INTERNAL void _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
+                                                      hb_font_t *font,
+                                                      hb_buffer_t  *buffer,
+                                                      bool adjust_offsets_when_zeroing);
+
+HB_INTERNAL void _hb_ot_shape_fallback_mark_position_recategorize_marks (const hb_ot_shape_plan_t *plan,
+                                                                         hb_font_t *font,
+                                                                         hb_buffer_t  *buffer);
+
+
+HB_INTERNAL void _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
+                                             hb_font_t *font,
+                                             hb_buffer_t  *buffer);
+
+HB_INTERNAL void _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
+                                               hb_font_t *font,
+                                               hb_buffer_t  *buffer);
+
+
+#endif /* HB_OT_SHAPE_FALLBACK_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-normalize-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright © 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_NORMALIZE_PRIVATE_HH
-#define HB_OT_SHAPE_NORMALIZE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-/* buffer var allocations, used during the normalization process */
-#define glyph_index()   var1.u32
-
-struct hb_ot_shape_plan_t;
-
-enum hb_ot_shape_normalization_mode_t {
-  HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
-  HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED,
-  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* never composes base-to-base */
-  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* always fully decomposes and then recompose back */
-
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS
-};
-
-HB_INTERNAL void _hb_ot_shape_normalize (const hb_ot_shape_plan_t *shaper,
-                                         hb_buffer_t *buffer,
-                                         hb_font_t *font);
-
-
-struct hb_ot_shape_normalize_context_t
-{
-  const hb_ot_shape_plan_t *plan;
-  hb_buffer_t *buffer;
-  hb_font_t *font;
-  hb_unicode_funcs_t *unicode;
-  bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
-                     hb_codepoint_t  ab,
-                     hb_codepoint_t *a,
-                     hb_codepoint_t *b);
-  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
-                   hb_codepoint_t  a,
-                   hb_codepoint_t  b,
-                   hb_codepoint_t *ab);
-};
-
-
-#endif /* HB_OT_SHAPE_NORMALIZE_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-normalize.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-normalize.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,9 +24,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-normalize-private.hh"
-#include "hb-ot-shape-complex-private.hh"
-#include "hb-ot-shape-private.hh"
+#include "hb-ot-shape-normalize.hh"
+#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shape.hh"
 
 
 /*
@@ -213,17 +213,19 @@
 }
 
 static inline void
-handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit)
+handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c,
+                                   unsigned int end,
+                                   bool short_circuit HB_UNUSED)
 {
   /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
   hb_buffer_t * const buffer = c->buffer;
   hb_font_t * const font = c->font;
   for (; buffer->idx < end - 1 && buffer->successful;) {
     if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) {
-      /* The next two lines are some ugly lines... But work. */
       if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()))
       {
-        buffer->replace_glyphs (2, 1, &buffer->cur().codepoint);
+        hb_codepoint_t unicode = buffer->cur().codepoint;
+        buffer->replace_glyphs (2, 1, &unicode);
       }
       else
       {
@@ -264,15 +266,6 @@
     decompose_current_character (c, short_circuit);
 }
 
-static inline void
-decompose_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool might_short_circuit, bool always_short_circuit)
-{
-  if (likely (c->buffer->idx + 1 == end))
-    decompose_current_character (c, might_short_circuit);
-  else
-    decompose_multi_char_cluster (c, end, always_short_circuit);
-}
-
 
 static int
 compare_combining_class (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
@@ -294,6 +287,16 @@
   _hb_buffer_assert_unicode_vars (buffer);
 
   hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference;
+  if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_AUTO)
+  {
+    if (plan->has_gpos_mark)
+      // https://github.com/harfbuzz/harfbuzz/issues/653#issuecomment-423905920
+      //mode = HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED;
+      mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS;
+    else
+      mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS;
+  }
+
   const hb_ot_shape_normalize_context_t c = {
     plan,
     buffer,
@@ -318,105 +321,81 @@
 
   /* First round, decompose */
 
-  buffer->clear_output ();
-  count = buffer->len;
-  for (buffer->idx = 0; buffer->idx < count && buffer->successful;)
+  bool all_simple = true;
   {
-    unsigned int end;
-    for (end = buffer->idx + 1; end < count; end++)
-      if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))))
+    buffer->clear_output ();
+    count = buffer->len;
+    buffer->idx = 0;
+    do
+    {
+      unsigned int end;
+      for (end = buffer->idx + 1; end < count; end++)
+        if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))))
+          break;
+
+      if (end < count)
+        end--; /* Leave one base for the marks to cluster with. */
+
+      /* From idx to end are simple clusters. */
+      if (might_short_circuit)
+      {
+        unsigned int done = font->get_nominal_glyphs (end - buffer->idx,
+                                                      &buffer->cur().codepoint,
+                                                      sizeof (buffer->info[0]),
+                                                      &buffer->cur().glyph_index(),
+                                                      sizeof (buffer->info[0]));
+        buffer->next_glyphs (done);
+      }
+      while (buffer->idx < end && buffer->successful)
+        decompose_current_character (&c, might_short_circuit);
+
+      if (buffer->idx == count || !buffer->successful)
         break;
 
-    decompose_cluster (&c, end, might_short_circuit, always_short_circuit);
+      all_simple = false;
+
+      /* Find all the marks now. */
+      for (end = buffer->idx + 1; end < count; end++)
+        if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))
+          break;
+
+      /* idx to end is one non-simple cluster. */
+      decompose_multi_char_cluster (&c, end, always_short_circuit);
+    }
+    while (buffer->idx < count && buffer->successful);
+    buffer->swap_buffers ();
   }
-  buffer->swap_buffers ();
 
 
   /* Second round, reorder (inplace) */
 
-  count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
+  if (!all_simple)
   {
-    if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0)
-      continue;
-
-    unsigned int end;
-    for (end = i + 1; end < count; end++)
-      if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0)
-        break;
-
-    /* We are going to do a O(n^2).  Only do this if the sequence is short. */
-    if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) {
-      i = end;
-      continue;
-    }
-
-    buffer->sort (i, end, compare_combining_class);
-
-    if (plan->shaper->reorder_marks)
-      plan->shaper->reorder_marks (plan, buffer, i, end);
-
-    i = end;
-  }
-
-
-  if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE ||
-      mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED)
-    return;
-
-  /* Third round, recompose */
-
-  /* As noted in the comment earlier, we don't try to combine
-   * ccc=0 chars with their previous Starter. */
+    count = buffer->len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0)
+        continue;
 
-  buffer->clear_output ();
-  count = buffer->len;
-  unsigned int starter = 0;
-  buffer->next_glyph ();
-  while (buffer->idx < count && buffer->successful)
-  {
-    hb_codepoint_t composed, glyph;
-    if (/* We don't try to compose a non-mark character with it's preceding starter.
-         * This is both an optimization to avoid trying to compose every two neighboring
-         * glyphs in most scripts AND a desired feature for Hangul.  Apparently Hangul
-         * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */
-        HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur())))
-    {
-      if (/* If there's anything between the starter and this char, they should have CCC
-           * smaller than this character's. */
-          (starter == buffer->out_len - 1 ||
-           info_cc (buffer->prev()) < info_cc (buffer->cur())) &&
-          /* And compose. */
-          c.compose (&c,
-                     buffer->out_info[starter].codepoint,
-                     buffer->cur().codepoint,
-                     &composed) &&
-          /* And the font has glyph for the composite. */
-          font->get_nominal_glyph (composed, &glyph))
-      {
-        /* Composes. */
-        buffer->next_glyph (); /* Copy to out-buffer. */
-        if (unlikely (!buffer->successful))
-          return;
-        buffer->merge_out_clusters (starter, buffer->out_len);
-        buffer->out_len--; /* Remove the second composable. */
-        /* Modify starter and carry on. */
-        buffer->out_info[starter].codepoint = composed;
-        buffer->out_info[starter].glyph_index() = glyph;
-        _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer);
+      unsigned int end;
+      for (end = i + 1; end < count; end++)
+        if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0)
+          break;
 
+      /* We are going to do a O(n^2).  Only do this if the sequence is short. */
+      if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) {
+        i = end;
         continue;
       }
-    }
 
-    /* Blocked, or doesn't compose. */
-    buffer->next_glyph ();
+      buffer->sort (i, end, compare_combining_class);
 
-    if (info_cc (buffer->prev()) == 0)
-      starter = buffer->out_len - 1;
+      if (plan->shaper->reorder_marks)
+        plan->shaper->reorder_marks (plan, buffer, i, end);
+
+      i = end;
+    }
   }
-  buffer->swap_buffers ();
-
   if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_CGJ)
   {
     /* For all CGJ, check if it prevented any reordering at all.
@@ -430,4 +409,63 @@
         _hb_glyph_info_unhide (&buffer->info[i]);
       }
   }
+
+
+  /* Third round, recompose */
+
+  if (!all_simple &&
+      (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS ||
+       mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT))
+  {
+    /* As noted in the comment earlier, we don't try to combine
+     * ccc=0 chars with their previous Starter. */
+
+    buffer->clear_output ();
+    count = buffer->len;
+    unsigned int starter = 0;
+    buffer->next_glyph ();
+    while (buffer->idx < count && buffer->successful)
+    {
+      hb_codepoint_t composed, glyph;
+      if (/* We don't try to compose a non-mark character with it's preceding starter.
+           * This is both an optimization to avoid trying to compose every two neighboring
+           * glyphs in most scripts AND a desired feature for Hangul.  Apparently Hangul
+           * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */
+          HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur())))
+      {
+        if (/* If there's anything between the starter and this char, they should have CCC
+             * smaller than this character's. */
+            (starter == buffer->out_len - 1 ||
+             info_cc (buffer->prev()) < info_cc (buffer->cur())) &&
+            /* And compose. */
+            c.compose (&c,
+                       buffer->out_info[starter].codepoint,
+                       buffer->cur().codepoint,
+                       &composed) &&
+            /* And the font has glyph for the composite. */
+            font->get_nominal_glyph (composed, &glyph))
+        {
+          /* Composes. */
+          buffer->next_glyph (); /* Copy to out-buffer. */
+          if (unlikely (!buffer->successful))
+            return;
+          buffer->merge_out_clusters (starter, buffer->out_len);
+          buffer->out_len--; /* Remove the second composable. */
+          /* Modify starter and carry on. */
+          buffer->out_info[starter].codepoint = composed;
+          buffer->out_info[starter].glyph_index() = glyph;
+          _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer);
+
+          continue;
+        }
+      }
+
+      /* Blocked, or doesn't compose. */
+      buffer->next_glyph ();
+
+      if (info_cc (buffer->prev()) == 0)
+        starter = buffer->out_len - 1;
+    }
+    buffer->swap_buffers ();
+  }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-normalize.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_NORMALIZE_HH
+#define HB_OT_SHAPE_NORMALIZE_HH
+
+#include "hb.hh"
+
+
+/* buffer var allocations, used during the normalization process */
+#define glyph_index()   var1.u32
+
+struct hb_ot_shape_plan_t;
+
+enum hb_ot_shape_normalization_mode_t {
+  HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
+  HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED,
+  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* Never composes base-to-base */
+  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* Always fully decomposes and then recompose back */
+
+  HB_OT_SHAPE_NORMALIZATION_MODE_AUTO, /* See hb-ot-shape-normalize.cc for logic. */
+  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT = HB_OT_SHAPE_NORMALIZATION_MODE_AUTO
+};
+
+HB_INTERNAL void _hb_ot_shape_normalize (const hb_ot_shape_plan_t *shaper,
+                                         hb_buffer_t *buffer,
+                                         hb_font_t *font);
+
+
+struct hb_ot_shape_normalize_context_t
+{
+  const hb_ot_shape_plan_t *plan;
+  hb_buffer_t *buffer;
+  hb_font_t *font;
+  hb_unicode_funcs_t *unicode;
+  bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
+                     hb_codepoint_t  ab,
+                     hb_codepoint_t *a,
+                     hb_codepoint_t *b);
+  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
+                   hb_codepoint_t  a,
+                   hb_codepoint_t  b,
+                   hb_codepoint_t *ab);
+};
+
+
+#endif /* HB_OT_SHAPE_NORMALIZE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright © 2010  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_PRIVATE_HH
-#define HB_OT_SHAPE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-map-private.hh"
-#include "hb-ot-layout-private.hh"
-
-
-
-struct hb_ot_shape_plan_t
-{
-  hb_segment_properties_t props;
-  const struct hb_ot_complex_shaper_t *shaper;
-  hb_ot_map_t map;
-  const void *data;
-  hb_mask_t rtlm_mask, frac_mask, numr_mask, dnom_mask;
-  hb_mask_t kern_mask;
-  unsigned int has_frac : 1;
-  unsigned int has_kern : 1;
-  unsigned int has_mark : 1;
-
-  inline void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
-  {
-    unsigned int table_index;
-    switch (table_tag) {
-      case HB_OT_TAG_GSUB: table_index = 0; break;
-      case HB_OT_TAG_GPOS: table_index = 1; break;
-      default: return;
-    }
-    map.collect_lookups (table_index, lookups);
-  }
-  inline void substitute (hb_font_t *font, hb_buffer_t *buffer) const { map.substitute (this, font, buffer); }
-  inline void position (hb_font_t *font, hb_buffer_t *buffer) const { map.position (this, font, buffer); }
-
-  void init (void)
-  {
-    memset (this, 0, sizeof (*this));
-    map.init ();
-  }
-  void fini (void) {
-    map.fini ();
-  }
-};
-
-struct hb_ot_shape_planner_t
-{
-  /* In the order that they are filled in. */
-  hb_face_t *face;
-  hb_segment_properties_t props;
-  const struct hb_ot_complex_shaper_t *shaper;
-  hb_ot_map_builder_t map;
-
-  hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan) :
-                         face (master_plan->face_unsafe),
-                         props (master_plan->props),
-                         shaper (nullptr),
-                         map (face, &props) {}
-
-  inline void compile (hb_ot_shape_plan_t &plan,
-                       const int          *coords,
-                       unsigned int        num_coords)
-  {
-    plan.props = props;
-    plan.shaper = shaper;
-    map.compile (plan.map, coords, num_coords);
-
-    plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
-    plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
-    plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r'));
-    plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m'));
-
-    plan.kern_mask = plan.map.get_mask (HB_DIRECTION_IS_HORIZONTAL (plan.props.direction) ?
-                                        HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'));
-
-    plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
-    plan.has_kern = !!plan.kern_mask;
-    plan.has_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
-  }
-
-  private:
-  HB_DISALLOW_COPY_AND_ASSIGN (hb_ot_shape_planner_t);
-};
-
-
-#endif /* HB_OT_SHAPE_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -26,62 +26,246 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#define HB_SHAPER ot
-#define hb_ot_shaper_face_data_t hb_ot_layout_t
-#define hb_ot_shaper_shape_plan_data_t hb_ot_shape_plan_t
-#include "hb-shaper-impl-private.hh"
-
-#include "hb-ot-shape-private.hh"
-#include "hb-ot-shape-complex-private.hh"
-#include "hb-ot-shape-fallback-private.hh"
-#include "hb-ot-shape-normalize-private.hh"
+#include "hb-shaper-impl.hh"
 
-#include "hb-ot-layout-private.hh"
-#include "hb-unicode-private.hh"
-#include "hb-set-private.hh"
-
-#include "hb-ot-layout-gsubgpos-private.hh"
-//#include "hb-aat-layout-private.hh"
+#include "hb-ot-shape.hh"
+#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shape-fallback.hh"
+#include "hb-ot-shape-normalize.hh"
 
-static hb_tag_t common_features[] = {
-  HB_TAG('c','c','m','p'),
-  HB_TAG('l','o','c','l'),
-  HB_TAG('m','a','r','k'),
-  HB_TAG('m','k','m','k'),
-  HB_TAG('r','l','i','g'),
-};
+#include "hb-ot-face.hh"
+
+#include "hb-set.hh"
+
+#include "hb-aat-layout.hh"
 
 
-static hb_tag_t horizontal_features[] = {
-  HB_TAG('c','a','l','t'),
-  HB_TAG('c','l','i','g'),
-  HB_TAG('c','u','r','s'),
-  HB_TAG('k','e','r','n'),
-  HB_TAG('l','i','g','a'),
-  HB_TAG('r','c','l','t'),
-};
-
+/**
+ * SECTION:hb-ot-shape
+ * @title: hb-ot-shape
+ * @short_description: OpenType shaping support
+ * @include: hb-ot.h
+ *
+ * Support functions for OpenType shaping related queries.
+ **/
 
 
 static void
 hb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
-                              const hb_segment_properties_t  *props,
+                              const hb_feature_t             *user_features,
+                              unsigned int                    num_user_features);
+
+static bool
+_hb_apply_morx (hb_face_t *face)
+{
+  if (hb_options ().aat &&
+      hb_aat_layout_has_substitution (face))
+    return true;
+
+  /* Ignore empty GSUB tables. */
+  return (!hb_ot_layout_has_substitution (face) ||
+          !hb_ot_layout_table_get_script_tags (face,
+                                               HB_OT_TAG_GSUB,
+                                               0, nullptr, nullptr)) &&
+         hb_aat_layout_has_substitution (face);
+}
+
+hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t                     *face,
+                                              const hb_segment_properties_t *props) :
+                                                face (face),
+                                                props (*props),
+                                                map (face, props),
+                                                aat_map (face, props),
+                                                apply_morx (_hb_apply_morx (face))
+{
+  shaper = hb_ot_shape_complex_categorize (this);
+
+  script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
+  script_fallback_mark_positioning = shaper->fallback_position;
+
+  if (apply_morx)
+    shaper = &_hb_ot_complex_shaper_default;
+}
+
+void
+hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t           &plan,
+                                const hb_ot_shape_plan_key_t &key)
+{
+  plan.props = props;
+  plan.shaper = shaper;
+  map.compile (plan.map, key);
+  if (apply_morx)
+    aat_map.compile (plan.aat_map);
+
+  plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
+  plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r'));
+  plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m'));
+  plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
+  plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
+  hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (props.direction) ?
+                      HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n');
+  plan.kern_mask = plan.map.get_mask (kern_tag);
+  plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k'));
+
+  plan.requested_kerning = !!plan.kern_mask;
+  plan.requested_tracking = !!plan.trak_mask;
+  bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX;
+  bool disable_gpos = plan.shaper->gpos_tag &&
+                      plan.shaper->gpos_tag != plan.map.chosen_script[1];
+
+  /*
+   * Decide who provides glyph classes. GDEF or Unicode.
+   */
+
+  if (!hb_ot_layout_has_glyph_classes (face))
+    plan.fallback_glyph_classes = true;
+
+  /*
+   * Decide who does substitutions. GSUB, morx, or fallback.
+   */
+
+  plan.apply_morx = apply_morx;
+
+  /*
+   * Decide who does positioning. GPOS, kerx, kern, or fallback.
+   */
+
+  if (hb_options ().aat && hb_aat_layout_has_positioning (face))
+    plan.apply_kerx = true;
+  else if (!apply_morx && !disable_gpos && hb_ot_layout_has_positioning (face))
+    plan.apply_gpos = true;
+  else if (hb_aat_layout_has_positioning (face))
+    plan.apply_kerx = true;
+
+  if (!plan.apply_kerx && !has_gpos_kern)
+  {
+    /* Apparently Apple applies kerx if GPOS kern was not applied. */
+    if (hb_aat_layout_has_positioning (face))
+      plan.apply_kerx = true;
+    else if (hb_ot_layout_has_kerning (face))
+      plan.apply_kern = true;
+  }
+
+  plan.zero_marks = script_zero_marks &&
+                    !plan.apply_kerx &&
+                    (!plan.apply_kern || !hb_ot_layout_has_machine_kerning (face));
+  plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
+
+  plan.adjust_mark_positioning_when_zeroing = !plan.apply_gpos &&
+                                              !plan.apply_kerx &&
+                                              (!plan.apply_kern || !hb_ot_layout_has_cross_kerning (face));
+
+  plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing &&
+                                   script_fallback_mark_positioning;
+
+  /* Currently we always apply trak. */
+  plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
+}
+
+bool
+hb_ot_shape_plan_t::init0 (hb_face_t                     *face,
+                           const hb_shape_plan_key_t     *key)
+{
+  map.init ();
+  aat_map.init ();
+
+  hb_ot_shape_planner_t planner (face,
+                                 &key->props);
+
+  hb_ot_shape_collect_features (&planner,
+                                key->user_features,
+                                key->num_user_features);
+
+  planner.compile (*this, key->ot);
+
+  if (shaper->data_create)
+  {
+    data = shaper->data_create (this);
+    if (unlikely (!data))
+      return false;
+  }
+
+  return true;
+}
+
+void
+hb_ot_shape_plan_t::fini ()
+{
+  if (shaper->data_destroy)
+    shaper->data_destroy (const_cast<void *> (data));
+
+  map.fini ();
+  aat_map.fini ();
+}
+
+void
+hb_ot_shape_plan_t::substitute (hb_font_t   *font,
+                                hb_buffer_t *buffer) const
+{
+  if (unlikely (apply_morx))
+    hb_aat_layout_substitute (this, font, buffer);
+  else
+    map.substitute (this, font, buffer);
+}
+
+void
+hb_ot_shape_plan_t::position (hb_font_t   *font,
+                              hb_buffer_t *buffer) const
+{
+  if (this->apply_gpos)
+    map.position (this, font, buffer);
+  else if (this->apply_kerx)
+    hb_aat_layout_position (this, font, buffer);
+  else if (this->apply_kern)
+    hb_ot_layout_kern (this, font, buffer);
+  else
+    _hb_ot_shape_fallback_kern (this, font, buffer);
+
+  if (this->apply_trak)
+    hb_aat_layout_track (this, font, buffer);
+}
+
+
+static const hb_ot_map_feature_t
+common_features[] =
+{
+  {HB_TAG('c','c','m','p'), F_GLOBAL},
+  {HB_TAG('l','o','c','l'), F_GLOBAL},
+  {HB_TAG('m','a','r','k'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('m','k','m','k'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('r','l','i','g'), F_GLOBAL},
+};
+
+
+static const hb_ot_map_feature_t
+horizontal_features[] =
+{
+  {HB_TAG('c','a','l','t'), F_GLOBAL},
+  {HB_TAG('c','l','i','g'), F_GLOBAL},
+  {HB_TAG('c','u','r','s'), F_GLOBAL},
+  {HB_TAG('k','e','r','n'), F_GLOBAL_HAS_FALLBACK},
+  {HB_TAG('l','i','g','a'), F_GLOBAL},
+  {HB_TAG('r','c','l','t'), F_GLOBAL},
+};
+
+static void
+hb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
                               const hb_feature_t             *user_features,
                               unsigned int                    num_user_features)
 {
   hb_ot_map_builder_t *map = &planner->map;
 
-  map->add_global_bool_feature (HB_TAG('r','v','r','n'));
+  map->enable_feature (HB_TAG('r','v','r','n'));
   map->add_gsub_pause (nullptr);
 
-  switch (props->direction) {
+  switch (planner->props.direction) {
     case HB_DIRECTION_LTR:
-      map->add_global_bool_feature (HB_TAG ('l','t','r','a'));
-      map->add_global_bool_feature (HB_TAG ('l','t','r','m'));
+      map->enable_feature (HB_TAG ('l','t','r','a'));
+      map->enable_feature (HB_TAG ('l','t','r','m'));
       break;
     case HB_DIRECTION_RTL:
-      map->add_global_bool_feature (HB_TAG ('r','t','l','a'));
-      map->add_feature (HB_TAG ('r','t','l','m'), 1, F_NONE);
+      map->enable_feature (HB_TAG ('r','t','l','a'));
+      map->add_feature (HB_TAG ('r','t','l','m'));
       break;
     case HB_DIRECTION_TTB:
     case HB_DIRECTION_BTT:
@@ -90,39 +274,62 @@
       break;
   }
 
-  map->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE);
-  map->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE);
-  map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE);
+  /* Automatic fractions. */
+  map->add_feature (HB_TAG ('f','r','a','c'));
+  map->add_feature (HB_TAG ('n','u','m','r'));
+  map->add_feature (HB_TAG ('d','n','o','m'));
+
+  /* Random! */
+  map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE);
+
+  /* Tracking.  We enable dummy feature here just to allow disabling
+   * AAT 'trak' table using features.
+   * https://github.com/harfbuzz/harfbuzz/issues/1303 */
+  map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK);
+
+  map->enable_feature (HB_TAG ('H','A','R','F'));
 
   if (planner->shaper->collect_features)
     planner->shaper->collect_features (planner);
 
-  for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++)
-    map->add_global_bool_feature (common_features[i]);
+  map->enable_feature (HB_TAG ('B','U','Z','Z'));
 
-  if (HB_DIRECTION_IS_HORIZONTAL (props->direction))
+  for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++)
+    map->add_feature (common_features[i]);
+
+  if (HB_DIRECTION_IS_HORIZONTAL (planner->props.direction))
     for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++)
-      map->add_feature (horizontal_features[i], 1, F_GLOBAL |
-                        (horizontal_features[i] == HB_TAG('k','e','r','n') ?
-                         F_HAS_FALLBACK : F_NONE));
+      map->add_feature (horizontal_features[i]);
   else
   {
     /* We really want to find a 'vert' feature if there's any in the font, no
      * matter which script/langsys it is listed (or not) under.
      * See various bugs referenced from:
      * https://github.com/harfbuzz/harfbuzz/issues/63 */
-    map->add_feature (HB_TAG ('v','e','r','t'), 1, F_GLOBAL | F_GLOBAL_SEARCH);
+    map->enable_feature (HB_TAG ('v','e','r','t'), F_GLOBAL_SEARCH);
+  }
+
+  for (unsigned int i = 0; i < num_user_features; i++)
+  {
+    const hb_feature_t *feature = &user_features[i];
+    map->add_feature (feature->tag,
+                      (feature->start == HB_FEATURE_GLOBAL_START &&
+                       feature->end == HB_FEATURE_GLOBAL_END) ?  F_GLOBAL : F_NONE,
+                      feature->value);
+  }
+
+  if (planner->apply_morx)
+  {
+    hb_aat_map_builder_t *aat_map = &planner->aat_map;
+    for (unsigned int i = 0; i < num_user_features; i++)
+    {
+      const hb_feature_t *feature = &user_features[i];
+      aat_map->add_feature (feature->tag, feature->value);
+    }
   }
 
   if (planner->shaper->override_features)
     planner->shaper->override_features (planner);
-
-  for (unsigned int i = 0; i < num_user_features; i++) {
-    const hb_feature_t *feature = &user_features[i];
-    map->add_feature (feature->tag, feature->value,
-                      (feature->start == 0 && feature->end == (unsigned int) -1) ?
-                       F_GLOBAL : F_NONE);
-  }
 }
 
 
@@ -130,18 +337,17 @@
  * shaper face data
  */
 
-HB_SHAPER_DATA_ENSURE_DEFINE(ot, face)
+struct hb_ot_face_data_t {};
 
-hb_ot_shaper_face_data_t *
+hb_ot_face_data_t *
 _hb_ot_shaper_face_data_create (hb_face_t *face)
 {
-  return _hb_ot_layout_create (face);
+  return (hb_ot_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
-_hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
+_hb_ot_shaper_face_data_destroy (hb_ot_face_data_t *data)
 {
-  _hb_ot_layout_destroy (data);
 }
 
 
@@ -149,68 +355,17 @@
  * shaper font data
  */
 
-HB_SHAPER_DATA_ENSURE_DEFINE(ot, font)
+struct hb_ot_font_data_t {};
 
-struct hb_ot_shaper_font_data_t {};
-
-hb_ot_shaper_font_data_t *
+hb_ot_font_data_t *
 _hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED)
 {
-  return (hb_ot_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+  return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
-_hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data)
-{
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-hb_ot_shaper_shape_plan_data_t *
-_hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan,
-                                      const hb_feature_t *user_features,
-                                      unsigned int        num_user_features,
-                                      const int          *coords,
-                                      unsigned int        num_coords)
+_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data HB_UNUSED)
 {
-  hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t));
-  if (unlikely (!plan))
-    return nullptr;
-
-  plan->init ();
-
-  hb_ot_shape_planner_t planner (shape_plan);
-
-  planner.shaper = hb_ot_shape_complex_categorize (&planner);
-
-  hb_ot_shape_collect_features (&planner, &shape_plan->props,
-                                user_features, num_user_features);
-
-  planner.compile (*plan, coords, num_coords);
-
-  if (plan->shaper->data_create) {
-    plan->data = plan->shaper->data_create (plan);
-    if (unlikely (!plan->data)) {
-      free(plan);
-      return nullptr;
-    }
-  }
-
-  return plan;
-}
-
-void
-_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *plan)
-{
-  if (plan->shaper->data_destroy)
-    plan->shaper->data_destroy (const_cast<void *> (plan->data));
-
-  plan->fini ();
-
-  free (plan);
 }
 
 
@@ -228,8 +383,6 @@
   unsigned int        num_user_features;
 
   /* Transient stuff */
-  bool fallback_positioning;
-  bool fallback_glyph_classes;
   hb_direction_t target_direction;
 };
 
@@ -243,10 +396,53 @@
 static void
 hb_set_unicode_props (hb_buffer_t *buffer)
 {
+  /* Implement enough of Unicode Graphemes here that shaping
+   * in reverse-direction wouldn't break graphemes.  Namely,
+   * we mark all marks and ZWJ and ZWJ,Extended_Pictographic
+   * sequences as continuations.  The foreach_grapheme()
+   * macro uses this bit.
+   *
+   * https://www.unicode.org/reports/tr29/#Regex_Definitions
+   */
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 0; i < count; i++)
+  {
     _hb_glyph_info_set_unicode_props (&info[i], buffer);
+
+    /* Marks are already set as continuation by the above line.
+     * Handle Emoji_Modifier and ZWJ-continuation. */
+    if (unlikely (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL &&
+                  hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x1F3FBu, 0x1F3FFu)))
+    {
+        _hb_glyph_info_set_continuation (&info[i]);
+    }
+    else if (unlikely (_hb_glyph_info_is_zwj (&info[i])))
+    {
+      _hb_glyph_info_set_continuation (&info[i]);
+      if (i + 1 < count &&
+          _hb_unicode_is_emoji_Extended_Pictographic (info[i + 1].codepoint))
+      {
+        i++;
+        _hb_glyph_info_set_unicode_props (&info[i], buffer);
+        _hb_glyph_info_set_continuation (&info[i]);
+      }
+    }
+    /* Or part of the Other_Grapheme_Extend that is not marks.
+     * As of Unicode 11 that is just:
+     *
+     * 200C          ; Other_Grapheme_Extend # Cf       ZERO WIDTH NON-JOINER
+     * FF9E..FF9F    ; Other_Grapheme_Extend # Lm   [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
+     * E0020..E007F  ; Other_Grapheme_Extend # Cf  [96] TAG SPACE..CANCEL TAG
+     *
+     * ZWNJ is special, we don't want to merge it as there's no need, and keeping
+     * it separate results in more granular clusters.  Ignore Katakana for now.
+     * Tags are used for Emoji sub-region flag sequences:
+     * https://github.com/harfbuzz/harfbuzz/issues/1556
+     */
+    else if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0xE0020u, 0xE007Fu)))
+      _hb_glyph_info_set_continuation (&info[i]);
+  }
 }
 
 static void
@@ -254,8 +450,7 @@
 {
   if (!(buffer->flags & HB_BUFFER_FLAG_BOT) ||
       buffer->context_len[0] ||
-      _hb_glyph_info_get_general_category (&buffer->info[0]) !=
-      HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
+      !_hb_glyph_info_is_unicode_mark (&buffer->info[0]))
     return;
 
   if (!font->has_glyph (0x25CCu))
@@ -274,7 +469,6 @@
   buffer->output_info (info);
   while (buffer->idx < buffer->len && buffer->successful)
     buffer->next_glyph ();
-
   buffer->swap_buffers ();
 }
 
@@ -284,26 +478,12 @@
   if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII))
     return;
 
-  /* Loop duplicated in hb_ensure_native_direction(), and in _hb-coretext.cc */
-  unsigned int base = 0;
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 1; i < count; i++)
-  {
-    if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])) &&
-                !_hb_glyph_info_is_joiner (&info[i])))
-    {
-      if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
-        buffer->merge_clusters (base, i);
-      else
-        buffer->unsafe_to_break (base, i);
-      base = i;
-    }
-  }
   if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
-    buffer->merge_clusters (base, count);
+    foreach_grapheme (buffer, start, end)
+      buffer->merge_clusters (start, end);
   else
-    buffer->unsafe_to_break (base, count);
+    foreach_grapheme (buffer, start, end)
+      buffer->unsafe_to_break (start, end);
 }
 
 static void
@@ -321,25 +501,17 @@
       (HB_DIRECTION_IS_VERTICAL   (direction) &&
        direction != HB_DIRECTION_TTB))
   {
-    /* Same loop as hb_form_clusters().
-     * Since form_clusters() merged clusters already, we don't merge. */
-    unsigned int base = 0;
-    unsigned int count = buffer->len;
-    hb_glyph_info_t *info = buffer->info;
-    for (unsigned int i = 1; i < count; i++)
-    {
-      if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))))
+
+    if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+      foreach_grapheme (buffer, start, end)
       {
-        if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
-          buffer->merge_clusters (base, i);
-        buffer->reverse_range (base, i);
-
-        base = i;
+        buffer->merge_clusters (start, end);
+        buffer->reverse_range (start, end);
       }
-    }
-    if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
-      buffer->merge_clusters (base, count);
-    buffer->reverse_range (base, count);
+    else
+      foreach_grapheme (buffer, start, end)
+        /* form_clusters() merged clusters already, we don't merge. */
+        buffer->reverse_range (start, end);
 
     buffer->reverse ();
 
@@ -348,10 +520,12 @@
 }
 
 
-/* Substitute */
+/*
+ * Substitute
+ */
 
 static inline void
-hb_ot_mirror_chars (hb_ot_shape_context_t *c)
+hb_ot_mirror_chars (const hb_ot_shape_context_t *c)
 {
   if (HB_DIRECTION_IS_FORWARD (c->target_direction))
     return;
@@ -372,7 +546,7 @@
 }
 
 static inline void
-hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
+hb_ot_shape_setup_masks_fraction (const hb_ot_shape_context_t *c)
 {
   if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
       !c->plan->has_frac)
@@ -422,7 +596,7 @@
 }
 
 static inline void
-hb_ot_shape_initialize_masks (hb_ot_shape_context_t *c)
+hb_ot_shape_initialize_masks (const hb_ot_shape_context_t *c)
 {
   hb_ot_map_t *map = &c->plan->map;
   hb_buffer_t *buffer = c->buffer;
@@ -432,7 +606,7 @@
 }
 
 static inline void
-hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
+hb_ot_shape_setup_masks (const hb_ot_shape_context_t *c)
 {
   hb_ot_map_t *map = &c->plan->map;
   hb_buffer_t *buffer = c->buffer;
@@ -454,10 +628,8 @@
 }
 
 static void
-hb_ot_zero_width_default_ignorables (hb_ot_shape_context_t *c)
+hb_ot_zero_width_default_ignorables (const hb_buffer_t *buffer)
 {
-  hb_buffer_t *buffer = c->buffer;
-
   if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
       (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) ||
       (buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES))
@@ -473,83 +645,29 @@
 }
 
 static void
-hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
+hb_ot_hide_default_ignorables (hb_buffer_t *buffer,
+                               hb_font_t   *font)
 {
-  hb_buffer_t *buffer = c->buffer;
-
   if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
       (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES))
     return;
 
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
-  hb_glyph_position_t *pos = buffer->pos;
-  unsigned int i = 0;
-  for (i = 0; i < count; i++)
+
+  hb_codepoint_t invisible = buffer->invisible;
+  if (!(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) &&
+      (invisible || font->get_nominal_glyph (' ', &invisible)))
   {
-    if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
-      break;
-  }
-
-  /* No default-ignorables found; return. */
-  if (i == count)
-    return;
-
-  hb_codepoint_t space;
-  if (!(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) &&
-      c->font->get_nominal_glyph (' ', &space))
-  {
-    /* Replace default-ignorables with a zero-advance space glyph. */
-    for (/*continue*/; i < count; i++)
+    /* Replace default-ignorables with a zero-advance invisible glyph. */
+    for (unsigned int i = 0; i < count; i++)
     {
       if (_hb_glyph_info_is_default_ignorable (&info[i]))
-        info[i].codepoint = space;
+        info[i].codepoint = invisible;
     }
   }
   else
-  {
-    /* Merge clusters and delete default-ignorables.
-     * NOTE! We can't use out-buffer as we have positioning data. */
-    unsigned int j = i;
-    for (; i < count; i++)
-    {
-      if (_hb_glyph_info_is_default_ignorable (&info[i]))
-      {
-        /* Merge clusters.
-         * Same logic as buffer->delete_glyph(), but for in-place removal. */
-
-        unsigned int cluster = info[i].cluster;
-        if (i + 1 < count && cluster == info[i + 1].cluster)
-          continue; /* Cluster survives; do nothing. */
-
-        if (j)
-        {
-          /* Merge cluster backward. */
-          if (cluster < info[j - 1].cluster)
-          {
-            unsigned int mask = info[i].mask;
-            unsigned int old_cluster = info[j - 1].cluster;
-            for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
-              buffer->set_cluster (info[k - 1], cluster, mask);
-          }
-          continue;
-        }
-
-        if (i + 1 < count)
-          buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
-
-        continue;
-      }
-
-      if (j != i)
-      {
-        info[j] = info[i];
-        pos[j] = pos[i];
-      }
-      j++;
-    }
-    buffer->len = j;
-  }
+    hb_ot_layout_delete_glyphs_inplace (buffer, _hb_glyph_info_is_default_ignorable);
 }
 
 
@@ -566,10 +684,10 @@
 }
 
 static inline void
-hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
+hb_synthesize_glyph_classes (hb_buffer_t *buffer)
 {
-  unsigned int count = c->buffer->len;
-  hb_glyph_info_t *info = c->buffer->info;
+  unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 0; i < count; i++)
   {
     hb_ot_layout_glyph_props_flags_t klass;
@@ -592,7 +710,7 @@
 }
 
 static inline void
-hb_ot_substitute_default (hb_ot_shape_context_t *c)
+hb_ot_substitute_default (const hb_ot_shape_context_t *c)
 {
   hb_buffer_t *buffer = c->buffer;
 
@@ -605,8 +723,8 @@
   hb_ot_shape_setup_masks (c);
 
   /* This is unfortunate to go here, but necessary... */
-  if (c->fallback_positioning)
-    _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer);
+  if (c->plan->fallback_mark_positioning)
+    _hb_ot_shape_fallback_mark_position_recategorize_marks (c->plan, c->font, buffer);
 
   hb_ot_map_glyphs_fast (buffer);
 
@@ -614,23 +732,20 @@
 }
 
 static inline void
-hb_ot_substitute_complex (hb_ot_shape_context_t *c)
+hb_ot_substitute_complex (const hb_ot_shape_context_t *c)
 {
   hb_buffer_t *buffer = c->buffer;
 
   hb_ot_layout_substitute_start (c->font, buffer);
 
-  if (!hb_ot_layout_has_glyph_classes (c->face))
-    hb_synthesize_glyph_classes (c);
+  if (c->plan->fallback_glyph_classes)
+    hb_synthesize_glyph_classes (c->buffer);
 
   c->plan->substitute (c->font, buffer);
-
-  /* XXX Call morx instead. */
-  //hb_aat_layout_substitute (c->font, c->buffer);
 }
 
 static inline void
-hb_ot_substitute (hb_ot_shape_context_t *c)
+hb_ot_substitute_pre (const hb_ot_shape_context_t *c)
 {
   hb_ot_substitute_default (c);
 
@@ -639,7 +754,21 @@
   hb_ot_substitute_complex (c);
 }
 
-/* Position */
+static inline void
+hb_ot_substitute_post (const hb_ot_shape_context_t *c)
+{
+  hb_ot_hide_default_ignorables (c->buffer, c->font);
+  if (c->plan->apply_morx)
+    hb_aat_layout_remove_deleted_glyphs (c->buffer);
+
+  if (c->plan->shaper->postprocess_glyphs)
+    c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
+}
+
+
+/*
+ * Position
+ */
 
 static inline void
 adjust_mark_offsets (hb_glyph_position_t *pos)
@@ -670,7 +799,7 @@
 }
 
 static inline void
-hb_ot_position_default (hb_ot_shape_context_t *c)
+hb_ot_position_default (const hb_ot_shape_context_t *c)
 {
   hb_direction_t direction = c->buffer->props.direction;
   unsigned int count = c->buffer->len;
@@ -679,8 +808,8 @@
 
   if (HB_DIRECTION_IS_HORIZONTAL (direction))
   {
-    for (unsigned int i = 0; i < count; i++)
-      pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint);
+    c->font->get_glyph_h_advances (count, &info[0].codepoint, sizeof(info[0]),
+                                   &pos[0].x_advance, sizeof(pos[0]));
     /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
     if (c->font->has_glyph_h_origin_func ())
       for (unsigned int i = 0; i < count; i++)
@@ -690,9 +819,10 @@
   }
   else
   {
+    c->font->get_glyph_v_advances (count, &info[0].codepoint, sizeof(info[0]),
+                                   &pos[0].y_advance, sizeof(pos[0]));
     for (unsigned int i = 0; i < count; i++)
     {
-      pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint);
       c->font->subtract_glyph_v_origin (info[i].codepoint,
                                         &pos[i].x_offset,
                                         &pos[i].y_offset);
@@ -703,23 +833,22 @@
 }
 
 static inline void
-hb_ot_position_complex (hb_ot_shape_context_t *c)
+hb_ot_position_complex (const hb_ot_shape_context_t *c)
 {
   unsigned int count = c->buffer->len;
   hb_glyph_info_t *info = c->buffer->info;
   hb_glyph_position_t *pos = c->buffer->pos;
 
-  /* If the font has no GPOS, AND, no fallback positioning will
-   * happen, AND, direction is forward, then when zeroing mark
-   * widths, we shift the mark with it, such that the mark
-   * is positioned hanging over the previous glyph.  When
+  /* If the font has no GPOS and direction is forward, then when
+   * zeroing mark widths, we shift the mark with it, such that the
+   * mark is positioned hanging over the previous glyph.  When
    * direction is backward we don't shift and it will end up
    * hanging over the next glyph after the final reordering.
-   * If fallback positinoing happens or GPOS is present, we don't
-   * care.
+   *
+   * Note: If fallback positinoing happens, we don't care about
+   * this as it will be overriden.
    */
-  bool adjust_offsets_when_zeroing = c->fallback_positioning &&
-                                     !c->plan->shaper->fallback_position &&
+  bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing &&
                                      HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
 
   /* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
@@ -733,36 +862,39 @@
 
   hb_ot_layout_position_start (c->font, c->buffer);
 
-  switch (c->plan->shaper->zero_width_marks)
-  {
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
-      zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
-      break;
+  if (c->plan->zero_marks)
+    switch (c->plan->shaper->zero_width_marks)
+    {
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
+        zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
+        break;
 
-    default:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
-      break;
-  }
+      default:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
+        break;
+    }
 
-  if (likely (!c->fallback_positioning))
-    c->plan->position (c->font, c->buffer);
+  c->plan->position (c->font, c->buffer);
 
-  switch (c->plan->shaper->zero_width_marks)
-  {
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
-      zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
-      break;
+  if (c->plan->zero_marks)
+    switch (c->plan->shaper->zero_width_marks)
+    {
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
+        zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
+        break;
 
-    default:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
-      break;
-  }
+      default:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
+        break;
+    }
 
-  /* Finishing off GPOS has to follow a certain order. */
+  /* Finish off.  Has to follow a certain order. */
   hb_ot_layout_position_finish_advances (c->font, c->buffer);
-  hb_ot_zero_width_default_ignorables (c);
+  hb_ot_zero_width_default_ignorables (c->buffer);
+  if (c->plan->apply_morx)
+    hb_aat_layout_zero_width_deleted_glyphs (c->buffer);
   hb_ot_layout_position_finish_offsets (c->font, c->buffer);
 
   /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
@@ -771,10 +903,14 @@
       c->font->subtract_glyph_h_origin (info[i].codepoint,
                                         &pos[i].x_offset,
                                         &pos[i].y_offset);
+
+  if (c->plan->fallback_mark_positioning)
+    _hb_ot_shape_fallback_mark_position (c->plan, c->font, c->buffer,
+                                         adjust_offsets_when_zeroing);
 }
 
 static inline void
-hb_ot_position (hb_ot_shape_context_t *c)
+hb_ot_position (const hb_ot_shape_context_t *c)
 {
   c->buffer->clear_positions ();
 
@@ -782,20 +918,10 @@
 
   hb_ot_position_complex (c);
 
-  if (c->fallback_positioning && c->plan->shaper->fallback_position)
-    _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer);
-
   if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
     hb_buffer_reverse (c->buffer);
 
-  /* Visual fallback goes here. */
-
-  if (c->fallback_positioning)
-    _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
-
   _hb_buffer_deallocate_gsubgpos_vars (c->buffer);
-
-  //hb_aat_layout_position (c->font, c->buffer);
 }
 
 static inline void
@@ -831,22 +957,17 @@
 {
   c->buffer->deallocate_var_all ();
   c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
-  if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR)))
+  if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR)))
   {
     c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR,
                               (unsigned) HB_BUFFER_MAX_LEN_MIN);
   }
-  if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR)))
+  if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR)))
   {
     c->buffer->max_ops = MAX (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR,
                               (unsigned) HB_BUFFER_MAX_OPS_MIN);
   }
 
-  bool disable_otl = c->plan->shaper->disable_otl && c->plan->shaper->disable_otl (c->plan);
-  //c->fallback_substitute     = disable_otl || !hb_ot_layout_has_substitution (c->face);
-  c->fallback_positioning    = disable_otl || !hb_ot_layout_has_positioning (c->face);
-  c->fallback_glyph_classes  = disable_otl || !hb_ot_layout_has_glyph_classes (c->face);
-
   /* Save the original direction, we use it later. */
   c->target_direction = c->buffer->props.direction;
 
@@ -865,13 +986,9 @@
   if (c->plan->shaper->preprocess_text)
     c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
 
-  hb_ot_substitute (c);
+  hb_ot_substitute_pre (c);
   hb_ot_position (c);
-
-  hb_ot_hide_default_ignorables (c);
-
-  if (c->plan->shaper->postprocess_glyphs)
-    c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
+  hb_ot_substitute_post (c);
 
   hb_propagate_flags (c->buffer);
 
@@ -892,7 +1009,7 @@
               const hb_feature_t *features,
               unsigned int        num_features)
 {
-  hb_ot_shape_context_t c = {HB_SHAPER_DATA_GET (shape_plan), font, font->face, buffer, features, num_features};
+  hb_ot_shape_context_t c = {&shape_plan->ot, font, font->face, buffer, features, num_features};
   hb_ot_shape_internal (&c);
 
   return true;
@@ -909,8 +1026,7 @@
                                   hb_tag_t         table_tag,
                                   hb_set_t        *lookup_indexes /* OUT */)
 {
-  /* XXX Does the first part always succeed? */
-  HB_SHAPER_DATA_GET (shape_plan)->collect_lookups (table_tag, lookup_indexes);
+  shape_plan->ot.collect_lookups (table_tag, lookup_indexes);
 }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,129 @@
+/*
+ * Copyright © 2010  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_HH
+#define HB_OT_SHAPE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-map.hh"
+#include "hb-aat-map.hh"
+
+
+struct hb_ot_shape_plan_key_t
+{
+  unsigned int variations_index[2];
+
+  void init (hb_face_t   *face,
+                    const int   *coords,
+                    unsigned int num_coords)
+  {
+    for (unsigned int table_index = 0; table_index < 2; table_index++)
+      hb_ot_layout_table_find_feature_variations (face,
+                                                  table_tags[table_index],
+                                                  coords,
+                                                  num_coords,
+                                                  &variations_index[table_index]);
+  }
+
+  bool equal (const hb_ot_shape_plan_key_t *other)
+  {
+    return 0 == memcmp (this, other, sizeof (*this));
+  }
+};
+
+
+struct hb_shape_plan_key_t;
+
+struct hb_ot_shape_plan_t
+{
+  hb_segment_properties_t props;
+  const struct hb_ot_complex_shaper_t *shaper;
+  hb_ot_map_t map;
+  hb_aat_map_t aat_map;
+  const void *data;
+  hb_mask_t frac_mask, numr_mask, dnom_mask;
+  hb_mask_t rtlm_mask;
+  hb_mask_t kern_mask;
+  hb_mask_t trak_mask;
+
+  bool requested_kerning : 1;
+  bool requested_tracking : 1;
+  bool has_frac : 1;
+  bool has_gpos_mark : 1;
+  bool zero_marks : 1;
+  bool fallback_glyph_classes : 1;
+  bool fallback_mark_positioning : 1;
+  bool adjust_mark_positioning_when_zeroing : 1;
+
+  bool apply_gpos : 1;
+  bool apply_kerx : 1;
+  bool apply_kern : 1;
+  bool apply_morx : 1;
+  bool apply_trak : 1;
+
+  void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
+  {
+    unsigned int table_index;
+    switch (table_tag) {
+      case HB_OT_TAG_GSUB: table_index = 0; break;
+      case HB_OT_TAG_GPOS: table_index = 1; break;
+      default: return;
+    }
+    map.collect_lookups (table_index, lookups);
+  }
+
+  HB_INTERNAL bool init0 (hb_face_t                     *face,
+                          const hb_shape_plan_key_t     *key);
+  HB_INTERNAL void fini ();
+
+  HB_INTERNAL void substitute (hb_font_t *font, hb_buffer_t *buffer) const;
+  HB_INTERNAL void position (hb_font_t *font, hb_buffer_t *buffer) const;
+};
+
+struct hb_shape_plan_t;
+
+struct hb_ot_shape_planner_t
+{
+  /* In the order that they are filled in. */
+  hb_face_t *face;
+  hb_segment_properties_t props;
+  hb_ot_map_builder_t map;
+  hb_aat_map_builder_t aat_map;
+  bool apply_morx : 1;
+  bool script_zero_marks : 1;
+  bool script_fallback_mark_positioning : 1;
+  const struct hb_ot_complex_shaper_t *shaper;
+
+  HB_INTERNAL hb_ot_shape_planner_t (hb_face_t                     *face,
+                                     const hb_segment_properties_t *props);
+
+  HB_INTERNAL void compile (hb_ot_shape_plan_t           &plan,
+                            const hb_ot_shape_plan_key_t &key);
+};
+
+
+#endif /* HB_OT_SHAPE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-stat-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,280 @@
+/*
+ * 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_OT_STAT_TABLE_HH
+#define HB_OT_STAT_TABLE_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
+
+/*
+ * STAT -- Style Attributes
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/stat
+ */
+#define HB_OT_TAG_STAT HB_TAG('S','T','A','T')
+
+
+namespace OT {
+
+enum
+{
+  OLDER_SIBLING_FONT_ATTRIBUTE = 0x0001,        /* If set, this axis value table
+                                                 * provides axis value information
+                                                 * that is applicable to other fonts
+                                                 * within the same font family. This
+                                                 * is used if the other fonts were
+                                                 * released earlier and did not include
+                                                 * information about values for some axis.
+                                                 * If newer versions of the other
+                                                 * fonts include the information
+                                                 * themselves and are present,
+                                                 * then this record is ignored. */
+  ELIDABLE_AXIS_VALUE_NAME = 0x0002             /* If set, it indicates that the axis
+                                                 * value represents the “normal” value
+                                                 * for the axis and may be omitted when
+                                                 * composing name strings. */
+  // Reserved = 0xFFFC                          /* Reserved for future use — set to zero. */
+};
+
+struct AxisValueFormat1
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier — set to 1. */
+  HBUINT16      axisIndex;      /* Zero-base index into the axis record array
+                                 * identifying the axis of design variation
+                                 * to which the axis value record applies.
+                                 * Must be less than designAxisCount. */
+  HBUINT16      flags;          /* Flags — see below for details. */
+  NameID        valueNameID;    /* The name ID for entries in the 'name' table
+                                 * that provide a display string for this
+                                 * attribute value. */
+  Fixed         value;          /* A numeric value for this attribute value. */
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+struct AxisValueFormat2
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier — set to 2. */
+  HBUINT16      axisIndex;      /* Zero-base index into the axis record array
+                                 * identifying the axis of design variation
+                                 * to which the axis value record applies.
+                                 * Must be less than designAxisCount. */
+  HBUINT16      flags;          /* Flags — see below for details. */
+  NameID        valueNameID;    /* The name ID for entries in the 'name' table
+                                 * that provide a display string for this
+                                 * attribute value. */
+  Fixed         nominalValue;   /* A numeric value for this attribute value. */
+  Fixed         rangeMinValue;  /* The minimum value for a range associated
+                                 * with the specified name ID. */
+  Fixed         rangeMaxValue;  /* The maximum value for a range associated
+                                 * with the specified name ID. */
+  public:
+  DEFINE_SIZE_STATIC (20);
+};
+
+struct AxisValueFormat3
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier — set to 3. */
+  HBUINT16      axisIndex;      /* Zero-base index into the axis record array
+                                 * identifying the axis of design variation
+                                 * to which the axis value record applies.
+                                 * Must be less than designAxisCount. */
+  HBUINT16      flags;          /* Flags — see below for details. */
+  NameID        valueNameID;    /* The name ID for entries in the 'name' table
+                                 * that provide a display string for this
+                                 * attribute value. */
+  Fixed         value;          /* A numeric value for this attribute value. */
+  Fixed         linkedValue;    /* The numeric value for a style-linked mapping
+                                 * from this value. */
+  public:
+  DEFINE_SIZE_STATIC (16);
+};
+
+struct AxisValueRecord
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16      axisIndex;      /* Zero-base index into the axis record array
+                                 * identifying the axis to which this value
+                                 * applies. Must be less than designAxisCount. */
+  Fixed         value;          /* A numeric value for this attribute value. */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct AxisValueFormat4
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier — set to 4. */
+  HBUINT16      axisCount;      /* The total number of axes contributing to
+                                 * this axis-values combination. */
+  HBUINT16      flags;          /* Flags — see below for details. */
+  NameID        valueNameID;    /* The name ID for entries in the 'name' table
+                                 * that provide a display string for this
+                                 * attribute value. */
+  UnsizedArrayOf<AxisValueRecord>
+                axisValues;     /* Array of AxisValue records that provide the
+                                 * combination of axis values, one for each
+                                 * contributing axis. */
+  public:
+  DEFINE_SIZE_ARRAY (8, axisValues);
+};
+
+struct AxisValue
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (c->check_struct (this)))
+      return_trace (false);
+
+    switch (u.format)
+    {
+    case 1:  return_trace (likely (u.format1.sanitize (c)));
+    case 2:  return_trace (likely (u.format2.sanitize (c)));
+    case 3:  return_trace (likely (u.format3.sanitize (c)));
+    case 4:  return_trace (likely (u.format4.sanitize (c)));
+    default: return_trace (true);
+    }
+  }
+
+  protected:
+  union
+  {
+  HBUINT16              format;
+  AxisValueFormat1      format1;
+  AxisValueFormat2      format2;
+  AxisValueFormat3      format3;
+  AxisValueFormat4      format4;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+
+struct StatAxisRecord
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  Tag           tag;            /* A tag identifying the axis of design variation. */
+  NameID        nameID;         /* The name ID for entries in the 'name' table that
+                                 * provide a display string for this axis. */
+  HBUINT16      ordering;       /* A value that applications can use to determine
+                                 * primary sorting of face names, or for ordering
+                                 * of descriptors when composing family or face names. */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct STAT
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_STAT;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          majorVersion == 1 &&
+                          minorVersion > 0 &&
+                          designAxesOffset.sanitize (c, this, designAxisCount) &&
+                          offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets))));
+  }
+
+  protected:
+  HBUINT16      majorVersion;   /* Major version number of the style attributes
+                                 * table — set to 1. */
+  HBUINT16      minorVersion;   /* Minor version number of the style attributes
+                                 * table — set to 2. */
+  HBUINT16      designAxisSize; /* The size in bytes of each axis record. */
+  HBUINT16      designAxisCount;/* The number of design axis records. In a
+                                 * font with an 'fvar' table, this value must be
+                                 * greater than or equal to the axisCount value
+                                 * in the 'fvar' table. In all fonts, must
+                                 * be greater than zero if axisValueCount
+                                 * is greater than zero. */
+  LNNOffsetTo<UnsizedArrayOf<StatAxisRecord> >
+                designAxesOffset;
+                                /* Offset in bytes from the beginning of
+                                 * the STAT table to the start of the design
+                                 * axes array. If designAxisCount is zero,
+                                 * set to zero; if designAxisCount is greater
+                                 * than zero, must be greater than zero. */
+  HBUINT16      axisValueCount; /* The number of axis value tables. */
+  LNNOffsetTo<UnsizedArrayOf<OffsetTo<AxisValue> > >
+                offsetToAxisValueOffsets;
+                                /* Offset in bytes from the beginning of
+                                 * the STAT table to the start of the design
+                                 * axes value offsets array. If axisValueCount
+                                 * is zero, set to zero; if axisValueCount is
+                                 * greater than zero, must be greater than zero. */
+  NameID        elidedFallbackNameID;
+                                /* Name ID used as fallback when projection of
+                                 * names into a particular font model produces
+                                 * a subfamily name containing only elidable
+                                 * elements. */
+  public:
+  DEFINE_SIZE_STATIC (20);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_STAT_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-tag-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,2064 @@
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ *   ./gen-tag-table.py languagetags language-subtag-registry
+ *
+ * on files with these headers:
+ *
+ * <meta name="updated_at" content="2018-09-07 07:45 PM" />
+ * File-Date: 2018-08-08
+ */
+
+#ifndef HB_OT_TAG_TABLE_HH
+#define HB_OT_TAG_TABLE_HH
+
+static const LangTag ot_languages[] = {
+  {"aa",        {HB_TAG('A','F','R',' ')}},     /* Afar */
+  {"aae",       {HB_TAG('S','Q','I',' ')}},     /* Arbëreshë Albanian -> Albanian */
+  {"aao",       {HB_TAG('A','R','A',' ')}},     /* Algerian Saharan Arabic -> Arabic */
+  {"aat",       {HB_TAG('S','Q','I',' ')}},     /* Arvanitika Albanian -> Albanian */
+  {"ab",        {HB_TAG('A','B','K',' ')}},     /* Abkhazian */
+  {"abh",       {HB_TAG('A','R','A',' ')}},     /* Tajiki Arabic -> Arabic */
+  {"abq",       {HB_TAG('A','B','A',' ')}},     /* Abaza */
+  {"abv",       {HB_TAG('A','R','A',' ')}},     /* Baharna Arabic -> Arabic */
+  {"acf",       {HB_TAG('F','A','N',' ')}},     /* Saint Lucian Creole French -> French Antillean */
+  {"ach",       {HB_TAG('A','C','H',' ')}},     /* Acoli -> Acholi */
+  {"acm",       {HB_TAG('A','R','A',' ')}},     /* Mesopotamian Arabic -> Arabic */
+  {"acq",       {HB_TAG('A','R','A',' ')}},     /* Ta'izzi-Adeni Arabic -> Arabic */
+  {"acr",       {HB_TAG('A','C','R',' ')}},     /* Achi */
+  {"acw",       {HB_TAG('A','R','A',' ')}},     /* Hijazi Arabic -> Arabic */
+  {"acx",       {HB_TAG('A','R','A',' ')}},     /* Omani Arabic -> Arabic */
+  {"acy",       {HB_TAG('A','R','A',' ')}},     /* Cypriot Arabic -> Arabic */
+  {"ada",       {HB_TAG('D','N','G',' ')}},     /* Adangme -> Dangme */
+  {"adf",       {HB_TAG('A','R','A',' ')}},     /* Dhofari Arabic -> Arabic */
+  {"adp",       {HB_TAG('D','Z','N',' ')}},     /* Adap (retired code) -> Dzongkha */
+  {"ady",       {HB_TAG('A','D','Y',' ')}},     /* Adyghe */
+  {"aeb",       {HB_TAG('A','R','A',' ')}},     /* Tunisian Arabic -> Arabic */
+  {"aec",       {HB_TAG('A','R','A',' ')}},     /* Saidi Arabic -> Arabic */
+  {"af",        {HB_TAG('A','F','K',' ')}},     /* Afrikaans */
+  {"afb",       {HB_TAG('A','R','A',' ')}},     /* Gulf Arabic -> Arabic */
+  {"ahg",       {HB_TAG('A','G','W',' ')}},     /* Qimant -> Agaw */
+  {"aht",       {HB_TAG('A','T','H',' ')}},     /* Ahtena -> Athapaskan */
+  {"aii",       {HB_TAG('S','W','A',' '),       /* Assyrian Neo-Aramaic -> Swadaya Aramaic */
+                 HB_TAG('S','Y','R',' ')}},     /* Assyrian Neo-Aramaic -> Syriac */
+  {"aio",       {HB_TAG('A','I','O',' ')}},     /* Aiton */
+  {"aiw",       {HB_TAG('A','R','I',' ')}},     /* Aari */
+  {"ajp",       {HB_TAG('A','R','A',' ')}},     /* South Levantine Arabic -> Arabic */
+  {"ak",        {HB_TAG('A','K','A',' '),       /* Akan [macrolanguage] */
+                 HB_TAG('T','W','I',' ')}},     /* Akan [macrolanguage] -> Twi */
+  {"aln",       {HB_TAG('S','Q','I',' ')}},     /* Gheg Albanian -> Albanian */
+  {"als",       {HB_TAG('S','Q','I',' ')}},     /* Tosk Albanian -> Albanian */
+  {"alt",       {HB_TAG('A','L','T',' ')}},     /* Southern Altai -> Altai */
+  {"am",        {HB_TAG('A','M','H',' ')}},     /* Amharic */
+  {"amf",       {HB_TAG('H','B','N',' ')}},     /* Hamer-Banna -> Hammer-Banna */
+  {"amw",       {HB_TAG('S','Y','R',' ')}},     /* Western Neo-Aramaic -> Syriac */
+  {"an",        {HB_TAG('A','R','G',' ')}},     /* Aragonese */
+  {"ang",       {HB_TAG('A','N','G',' ')}},     /* Old English (ca. 450-1100) -> Anglo-Saxon */
+  {"apc",       {HB_TAG('A','R','A',' ')}},     /* North Levantine Arabic -> Arabic */
+  {"apd",       {HB_TAG('A','R','A',' ')}},     /* Sudanese Arabic -> Arabic */
+  {"apj",       {HB_TAG('A','T','H',' ')}},     /* Jicarilla Apache -> Athapaskan */
+  {"apk",       {HB_TAG('A','T','H',' ')}},     /* Kiowa Apache -> Athapaskan */
+  {"apl",       {HB_TAG('A','T','H',' ')}},     /* Lipan Apache -> Athapaskan */
+  {"apm",       {HB_TAG('A','T','H',' ')}},     /* Mescalero-Chiricahua Apache -> Athapaskan */
+  {"apw",       {HB_TAG('A','T','H',' ')}},     /* Western Apache -> Athapaskan */
+  {"ar",        {HB_TAG('A','R','A',' ')}},     /* Arabic [macrolanguage] */
+  {"arb",       {HB_TAG('A','R','A',' ')}},     /* Standard Arabic -> Arabic */
+  {"arn",       {HB_TAG('M','A','P',' ')}},     /* Mapudungun */
+  {"arq",       {HB_TAG('A','R','A',' ')}},     /* Algerian Arabic -> Arabic */
+  {"ars",       {HB_TAG('A','R','A',' ')}},     /* Najdi Arabic -> Arabic */
+  {"ary",       {HB_TAG('M','O','R',' ')}},     /* Moroccan Arabic -> Moroccan */
+  {"arz",       {HB_TAG('A','R','A',' ')}},     /* Egyptian Arabic -> Arabic */
+  {"as",        {HB_TAG('A','S','M',' ')}},     /* Assamese */
+  {"ast",       {HB_TAG('A','S','T',' ')}},     /* Asturian */
+  {"ath",       {HB_TAG('A','T','H',' ')}},     /* Athapascan [family] -> Athapaskan */
+  {"atj",       {HB_TAG('R','C','R',' ')}},     /* Atikamekw -> R-Cree */
+  {"atv",       {HB_TAG('A','L','T',' ')}},     /* Northern Altai -> Altai */
+  {"auz",       {HB_TAG('A','R','A',' ')}},     /* Uzbeki Arabic -> Arabic */
+  {"av",        {HB_TAG('A','V','R',' ')}},     /* Avaric -> Avar */
+  {"avl",       {HB_TAG('A','R','A',' ')}},     /* Eastern Egyptian Bedawi Arabic -> Arabic */
+  {"awa",       {HB_TAG('A','W','A',' ')}},     /* Awadhi */
+  {"ay",        {HB_TAG('A','Y','M',' ')}},     /* Aymara [macrolanguage] */
+  {"ayc",       {HB_TAG('A','Y','M',' ')}},     /* Southern Aymara -> Aymara */
+  {"ayh",       {HB_TAG('A','R','A',' ')}},     /* Hadrami Arabic -> Arabic */
+  {"ayl",       {HB_TAG('A','R','A',' ')}},     /* Libyan Arabic -> Arabic */
+  {"ayn",       {HB_TAG('A','R','A',' ')}},     /* Sanaani Arabic -> Arabic */
+  {"ayp",       {HB_TAG('A','R','A',' ')}},     /* North Mesopotamian Arabic -> Arabic */
+  {"ayr",       {HB_TAG('A','Y','M',' ')}},     /* Central Aymara -> Aymara */
+  {"az",        {HB_TAG('A','Z','E',' ')}},     /* Azerbaijani [macrolanguage] */
+  {"azb",       {HB_TAG('A','Z','B',' ')}},     /* South Azerbaijani -> Torki */
+  {"azj",       {HB_TAG('A','Z','E',' ')}},     /* North Azerbaijani -> Azerbaijani */
+  {"ba",        {HB_TAG('B','S','H',' ')}},     /* Bashkir */
+  {"bad",       {HB_TAG('B','A','D','0')}},     /* Banda [family] */
+  {"bai",       {HB_TAG('B','M','L',' ')}},     /* Bamileke [family] */
+  {"bal",       {HB_TAG('B','L','I',' ')}},     /* Baluchi [macrolanguage] */
+  {"ban",       {HB_TAG('B','A','N',' ')}},     /* Balinese */
+  {"bar",       {HB_TAG('B','A','R',' ')}},     /* Bavarian */
+  {"bbc",       {HB_TAG('B','B','C',' ')}},     /* Batak Toba */
+  {"bbz",       {HB_TAG('A','R','A',' ')}},     /* Babalia Creole Arabic -> Arabic */
+  {"bcc",       {HB_TAG('B','L','I',' ')}},     /* Southern Balochi -> Baluchi */
+  {"bci",       {HB_TAG('B','A','U',' ')}},     /* Baoulé -> Baulé */
+  {"bcl",       {HB_TAG('B','I','K',' ')}},     /* Central Bikol -> Bikol */
+  {"bcq",       {HB_TAG('B','C','H',' ')}},     /* Bench */
+  {"bcr",       {HB_TAG('A','T','H',' ')}},     /* Babine -> Athapaskan */
+  {"bdy",       {HB_TAG('B','D','Y',' ')}},     /* Bandjalang */
+  {"be",        {HB_TAG('B','E','L',' ')}},     /* Belarusian -> Belarussian */
+  {"bea",       {HB_TAG('A','T','H',' ')}},     /* Beaver -> Athapaskan */
+  {"beb",       {HB_TAG('B','T','I',' ')}},     /* Bebele -> Beti */
+  {"bem",       {HB_TAG('B','E','M',' ')}},     /* Bemba (Zambia) */
+  {"ber",       {HB_TAG('B','B','R',' ')}},     /* Berber [family] */
+  {"bfq",       {HB_TAG('B','A','D',' ')}},     /* Badaga */
+  {"bft",       {HB_TAG('B','L','T',' ')}},     /* Balti */
+  {"bfu",       {HB_TAG('L','A','H',' ')}},     /* Gahri -> Lahuli */
+  {"bfy",       {HB_TAG('B','A','G',' ')}},     /* Bagheli -> Baghelkhandi */
+  {"bg",        {HB_TAG('B','G','R',' ')}},     /* Bulgarian */
+  {"bgc",       {HB_TAG('B','G','C',' ')}},     /* Haryanvi */
+  {"bgn",       {HB_TAG('B','L','I',' ')}},     /* Western Balochi -> Baluchi */
+  {"bgp",       {HB_TAG('B','L','I',' ')}},     /* Eastern Balochi -> Baluchi */
+  {"bgq",       {HB_TAG('B','G','Q',' ')}},     /* Bagri */
+  {"bgr",       {HB_TAG('Q','I','N',' ')}},     /* Bawm Chin -> Chin */
+  {"bhb",       {HB_TAG('B','H','I',' ')}},     /* Bhili */
+  {"bhi",       {HB_TAG('B','H','I',' ')}},     /* Bhilali -> Bhili */
+  {"bhk",       {HB_TAG('B','I','K',' ')}},     /* Albay Bicolano (retired code) -> Bikol */
+  {"bho",       {HB_TAG('B','H','O',' ')}},     /* Bhojpuri */
+  {"bhr",       {HB_TAG('M','L','G',' ')}},     /* Bara Malagasy -> Malagasy */
+  {"bi",        {HB_TAG('B','I','S',' ')}},     /* Bislama */
+  {"bik",       {HB_TAG('B','I','K',' ')}},     /* Bikol [macrolanguage] */
+  {"bin",       {HB_TAG('E','D','O',' ')}},     /* Edo */
+  {"bjj",       {HB_TAG('B','J','J',' ')}},     /* Kanauji */
+  {"bjn",       {HB_TAG('M','L','Y',' ')}},     /* Banjar -> Malay */
+  {"bjq",       {HB_TAG('M','L','G',' ')}},     /* Southern Betsimisaraka Malagasy (retired code) -> Malagasy */
+  {"bjt",       {HB_TAG('B','L','N',' ')}},     /* Balanta-Ganja -> Balante */
+  {"bla",       {HB_TAG('B','K','F',' ')}},     /* Siksika -> Blackfoot */
+  {"ble",       {HB_TAG('B','L','N',' ')}},     /* Balanta-Kentohe -> Balante */
+  {"blk",       {HB_TAG('B','L','K',' ')}},     /* Pa'o Karen */
+  {"bln",       {HB_TAG('B','I','K',' ')}},     /* Southern Catanduanes Bikol -> Bikol */
+  {"bm",        {HB_TAG('B','M','B',' ')}},     /* Bambara (Bamanankan) */
+  {"bmm",       {HB_TAG('M','L','G',' ')}},     /* Northern Betsimisaraka Malagasy -> Malagasy */
+  {"bn",        {HB_TAG('B','E','N',' ')}},     /* Bengali */
+  {"bo",        {HB_TAG('T','I','B',' ')}},     /* Tibetan */
+  {"bpy",       {HB_TAG('B','P','Y',' ')}},     /* Bishnupriya -> Bishnupriya Manipuri */
+  {"bqi",       {HB_TAG('L','R','C',' ')}},     /* Bakhtiari -> Luri */
+  {"br",        {HB_TAG('B','R','E',' ')}},     /* Breton */
+  {"bra",       {HB_TAG('B','R','I',' ')}},     /* Braj -> Braj Bhasha */
+  {"brh",       {HB_TAG('B','R','H',' ')}},     /* Brahui */
+  {"brx",       {HB_TAG('B','R','X',' ')}},     /* Bodo (India) */
+  {"bs",        {HB_TAG('B','O','S',' ')}},     /* Bosnian */
+  {"bsk",       {HB_TAG('B','S','K',' ')}},     /* Burushaski */
+  {"btb",       {HB_TAG('B','T','I',' ')}},     /* Beti (Cameroon) (retired code) */
+  {"btj",       {HB_TAG('M','L','Y',' ')}},     /* Bacanese Malay -> Malay */
+  {"bto",       {HB_TAG('B','I','K',' ')}},     /* Rinconada Bikol -> Bikol */
+  {"bts",       {HB_TAG('B','T','S',' ')}},     /* Batak Simalungun */
+  {"bug",       {HB_TAG('B','U','G',' ')}},     /* Buginese -> Bugis */
+  {"bum",       {HB_TAG('B','T','I',' ')}},     /* Bulu (Cameroon) -> Beti */
+  {"bve",       {HB_TAG('M','L','Y',' ')}},     /* Berau Malay -> Malay */
+  {"bvu",       {HB_TAG('M','L','Y',' ')}},     /* Bukit Malay -> Malay */
+  {"bxk",       {HB_TAG('L','U','H',' ')}},     /* Bukusu -> Luyia */
+  {"bxp",       {HB_TAG('B','T','I',' ')}},     /* Bebil -> Beti */
+  {"bxr",       {HB_TAG('R','B','U',' ')}},     /* Russia Buriat -> Russian Buriat */
+  {"byn",       {HB_TAG('B','I','L',' ')}},     /* Bilin -> Bilen */
+  {"byv",       {HB_TAG('B','Y','V',' ')}},     /* Medumba */
+  {"bzc",       {HB_TAG('M','L','G',' ')}},     /* Southern Betsimisaraka Malagasy -> Malagasy */
+  {"ca",        {HB_TAG('C','A','T',' ')}},     /* Catalan */
+  {"caf",       {HB_TAG('C','R','R',' '),       /* Southern Carrier -> Carrier */
+                 HB_TAG('A','T','H',' ')}},     /* Southern Carrier -> Athapaskan */
+  {"cak",       {HB_TAG('C','A','K',' ')}},     /* Kaqchikel */
+  {"cbk",       {HB_TAG('C','B','K',' ')}},     /* Chavacano -> Zamboanga Chavacano */
+  {"cbl",       {HB_TAG('Q','I','N',' ')}},     /* Bualkhaw Chin -> Chin */
+  {"cco",       {HB_TAG('C','C','H','N')}},     /* Comaltepec Chinantec -> Chinantec */
+  {"ccq",       {HB_TAG('A','R','K',' ')}},     /* Chaungtha (retired code) -> Rakhine */
+  {"cdo",       {HB_TAG('Z','H','S',' ')}},     /* Min Dong Chinese -> Chinese Simplified */
+  {"ce",        {HB_TAG('C','H','E',' ')}},     /* Chechen */
+  {"ceb",       {HB_TAG('C','E','B',' ')}},     /* Cebuano */
+  {"cfm",       {HB_TAG('H','A','L',' ')}},     /* Halam (Falam Chin) */
+  {"cgg",       {HB_TAG('C','G','G',' ')}},     /* Chiga */
+  {"ch",        {HB_TAG('C','H','A',' ')}},     /* Chamorro */
+  {"chj",       {HB_TAG('C','C','H','N')}},     /* Ojitlán Chinantec -> Chinantec */
+  {"chk",       {HB_TAG('C','H','K','0')}},     /* Chuukese */
+  {"cho",       {HB_TAG('C','H','O',' ')}},     /* Choctaw */
+  {"chp",       {HB_TAG('C','H','P',' '),       /* Chipewyan */
+                 HB_TAG('S','A','Y',' '),       /* Chipewyan -> Sayisi */
+                 HB_TAG('A','T','H',' ')}},     /* Chipewyan -> Athapaskan */
+  {"chq",       {HB_TAG('C','C','H','N')}},     /* Quiotepec Chinantec -> Chinantec */
+  {"chr",       {HB_TAG('C','H','R',' ')}},     /* Cherokee */
+  {"chy",       {HB_TAG('C','H','Y',' ')}},     /* Cheyenne */
+  {"chz",       {HB_TAG('C','C','H','N')}},     /* Ozumacín Chinantec -> Chinantec */
+  {"ciw",       {HB_TAG('O','J','B',' ')}},     /* Chippewa -> Ojibway */
+  {"cja",       {HB_TAG('C','J','A',' ')}},     /* Western Cham */
+  {"cjm",       {HB_TAG('C','J','M',' ')}},     /* Eastern Cham */
+  {"cjy",       {HB_TAG('Z','H','S',' ')}},     /* Jinyu Chinese -> Chinese Simplified */
+  {"cka",       {HB_TAG('Q','I','N',' ')}},     /* Khumi Awa Chin (retired code) -> Chin */
+  {"ckb",       {HB_TAG('K','U','R',' ')}},     /* Central Kurdish -> Kurdish */
+  {"ckt",       {HB_TAG('C','H','K',' ')}},     /* Chukot -> Chukchi */
+  {"clc",       {HB_TAG('A','T','H',' ')}},     /* Chilcotin -> Athapaskan */
+  {"cld",       {HB_TAG('S','Y','R',' ')}},     /* Chaldean Neo-Aramaic -> Syriac */
+  {"cle",       {HB_TAG('C','C','H','N')}},     /* Lealao Chinantec -> Chinantec */
+  {"cmn",       {HB_TAG('Z','H','S',' ')}},     /* Mandarin Chinese -> Chinese Simplified */
+  {"cmr",       {HB_TAG('Q','I','N',' ')}},     /* Mro-Khimi Chin -> Chin */
+  {"cnb",       {HB_TAG('Q','I','N',' ')}},     /* Chinbon Chin -> Chin */
+  {"cnh",       {HB_TAG('Q','I','N',' ')}},     /* Hakha Chin -> Chin */
+  {"cnk",       {HB_TAG('Q','I','N',' ')}},     /* Khumi Chin -> Chin */
+  {"cnl",       {HB_TAG('C','C','H','N')}},     /* Lalana Chinantec -> Chinantec */
+  {"cnt",       {HB_TAG('C','C','H','N')}},     /* Tepetotutla Chinantec -> Chinantec */
+  {"cnw",       {HB_TAG('Q','I','N',' ')}},     /* Ngawn Chin -> Chin */
+  {"co",        {HB_TAG('C','O','S',' ')}},     /* Corsican */
+  {"coa",       {HB_TAG('M','L','Y',' ')}},     /* Cocos Islands Malay -> Malay */
+  {"cop",       {HB_TAG('C','O','P',' ')}},     /* Coptic */
+  {"coq",       {HB_TAG('A','T','H',' ')}},     /* Coquille -> Athapaskan */
+  {"cpa",       {HB_TAG('C','C','H','N')}},     /* Palantla Chinantec -> Chinantec */
+  {"cpe",       {HB_TAG('C','P','P',' ')}},     /* English-based creoles and pidgins [family] -> Creoles */
+  {"cpf",       {HB_TAG('C','P','P',' ')}},     /* French-based creoles and pidgins [family] -> Creoles */
+  {"cpp",       {HB_TAG('C','P','P',' ')}},     /* Portuguese-based creoles and pidgins [family] -> Creoles */
+  {"cpx",       {HB_TAG('Z','H','S',' ')}},     /* Pu-Xian Chinese -> Chinese Simplified */
+  {"cqd",       {HB_TAG('H','M','N',' ')}},     /* Chuanqiandian Cluster Miao -> Hmong */
+  {"cqu",       {HB_TAG('Q','U','H',' ')}},     /* Chilean Quechua (retired code) -> Quechua (Bolivia) */
+  {"cr",        {HB_TAG('C','R','E',' '),       /* Cree [macrolanguage] */
+                 HB_TAG('Y','C','R',' ')}},     /* Cree [macrolanguage] -> Y-Cree */
+  {"crh",       {HB_TAG('C','R','T',' ')}},     /* Crimean Tatar */
+  {"crj",       {HB_TAG('E','C','R',' ')}},     /* Southern East Cree -> Eastern Cree */
+  {"crk",       {HB_TAG('W','C','R',' ')}},     /* Plains Cree -> West-Cree */
+  {"crl",       {HB_TAG('E','C','R',' ')}},     /* Northern East Cree -> Eastern Cree */
+  {"crm",       {HB_TAG('M','C','R',' '),       /* Moose Cree */
+                 HB_TAG('L','C','R',' ')}},     /* Moose Cree -> L-Cree */
+  {"crp",       {HB_TAG('C','P','P',' ')}},     /* Creoles and pidgins [family] -> Creoles */
+  {"crx",       {HB_TAG('C','R','R',' '),       /* Carrier */
+                 HB_TAG('A','T','H',' ')}},     /* Carrier -> Athapaskan */
+  {"cs",        {HB_TAG('C','S','Y',' ')}},     /* Czech */
+  {"csa",       {HB_TAG('C','C','H','N')}},     /* Chiltepec Chinantec -> Chinantec */
+  {"csb",       {HB_TAG('C','S','B',' ')}},     /* Kashubian */
+  {"csh",       {HB_TAG('Q','I','N',' ')}},     /* Asho Chin -> Chin */
+  {"cso",       {HB_TAG('C','C','H','N')}},     /* Sochiapam Chinantec -> Chinantec */
+  {"csw",       {HB_TAG('N','C','R',' '),       /* Swampy Cree -> N-Cree */
+                 HB_TAG('N','H','C',' ')}},     /* Swampy Cree -> Norway House Cree */
+  {"csy",       {HB_TAG('Q','I','N',' ')}},     /* Siyin Chin -> Chin */
+  {"ctc",       {HB_TAG('A','T','H',' ')}},     /* Chetco -> Athapaskan */
+  {"ctd",       {HB_TAG('Q','I','N',' ')}},     /* Tedim Chin -> Chin */
+  {"cte",       {HB_TAG('C','C','H','N')}},     /* Tepinapa Chinantec -> Chinantec */
+  {"ctg",       {HB_TAG('C','T','G',' ')}},     /* Chittagonian */
+  {"ctl",       {HB_TAG('C','C','H','N')}},     /* Tlacoatzintepec Chinantec -> Chinantec */
+  {"cts",       {HB_TAG('B','I','K',' ')}},     /* Northern Catanduanes Bikol -> Bikol */
+  {"cu",        {HB_TAG('C','S','L',' ')}},     /* Church Slavonic */
+  {"cuc",       {HB_TAG('C','C','H','N')}},     /* Usila Chinantec -> Chinantec */
+  {"cuk",       {HB_TAG('C','U','K',' ')}},     /* San Blas Kuna */
+  {"cv",        {HB_TAG('C','H','U',' ')}},     /* Chuvash */
+  {"cvn",       {HB_TAG('C','C','H','N')}},     /* Valle Nacional Chinantec -> Chinantec */
+  {"cwd",       {HB_TAG('D','C','R',' '),       /* Woods Cree */
+                 HB_TAG('T','C','R',' ')}},     /* Woods Cree -> TH-Cree */
+  {"cy",        {HB_TAG('W','E','L',' ')}},     /* Welsh */
+  {"czh",       {HB_TAG('Z','H','S',' ')}},     /* Huizhou Chinese -> Chinese Simplified */
+  {"czo",       {HB_TAG('Z','H','S',' ')}},     /* Min Zhong Chinese -> Chinese Simplified */
+  {"czt",       {HB_TAG('Q','I','N',' ')}},     /* Zotung Chin -> Chin */
+  {"da",        {HB_TAG('D','A','N',' ')}},     /* Danish */
+  {"dao",       {HB_TAG('Q','I','N',' ')}},     /* Daai Chin -> Chin */
+  {"dap",       {HB_TAG('N','I','S',' ')}},     /* Nisi (India) (retired code) */
+  {"dar",       {HB_TAG('D','A','R',' ')}},     /* Dargwa */
+  {"dax",       {HB_TAG('D','A','X',' ')}},     /* Dayi */
+  {"de",        {HB_TAG('D','E','U',' ')}},     /* German */
+  {"den",       {HB_TAG('S','L','A',' '),       /* Slave (Athapascan) [macrolanguage] -> Slavey */
+                 HB_TAG('A','T','H',' ')}},     /* Slave (Athapascan) [macrolanguage] -> Athapaskan */
+  {"dgo",       {HB_TAG('D','G','O',' ')}},     /* Dogri */
+  {"dgr",       {HB_TAG('A','T','H',' ')}},     /* Dogrib -> Athapaskan */
+  {"dhd",       {HB_TAG('M','A','W',' ')}},     /* Dhundari -> Marwari */
+  {"dhg",       {HB_TAG('D','H','G',' ')}},     /* Dhangu */
+  {"dib",       {HB_TAG('D','N','K',' ')}},     /* South Central Dinka -> Dinka */
+  {"dik",       {HB_TAG('D','N','K',' ')}},     /* Southwestern Dinka -> Dinka */
+  {"din",       {HB_TAG('D','N','K',' ')}},     /* Dinka [macrolanguage] */
+  {"dip",       {HB_TAG('D','N','K',' ')}},     /* Northeastern Dinka -> Dinka */
+  {"diq",       {HB_TAG('D','I','Q',' ')}},     /* Dimli */
+  {"diw",       {HB_TAG('D','N','K',' ')}},     /* Northwestern Dinka -> Dinka */
+  {"dje",       {HB_TAG('D','J','R',' ')}},     /* Zarma */
+  {"djr",       {HB_TAG('D','J','R','0')}},     /* Djambarrpuyngu */
+  {"dks",       {HB_TAG('D','N','K',' ')}},     /* Southeastern Dinka -> Dinka */
+  {"dng",       {HB_TAG('D','U','N',' ')}},     /* Dungan */
+  {"dnj",       {HB_TAG('D','N','J',' ')}},     /* Dan */
+  {"doi",       {HB_TAG('D','G','R',' ')}},     /* Dogri [macrolanguage] */
+  {"drh",       {HB_TAG('M','N','G',' ')}},     /* Darkhat (retired code) -> Mongolian */
+  {"drw",       {HB_TAG('D','R','I',' ')}},     /* Darwazi (retired code) -> Dari */
+  {"dsb",       {HB_TAG('L','S','B',' ')}},     /* Lower Sorbian */
+  {"dty",       {HB_TAG('N','E','P',' ')}},     /* Dotyali -> Nepali */
+  {"duj",       {HB_TAG('D','U','J',' ')}},     /* Dhuwal (retired code) */
+  {"dup",       {HB_TAG('M','L','Y',' ')}},     /* Duano -> Malay */
+  {"dv",        {HB_TAG('D','I','V',' '),       /* Divehi (Dhivehi, Maldivian) */
+                 HB_TAG('D','H','V',' ')}},     /* Divehi (Dhivehi, Maldivian) (deprecated) */
+  {"dwu",       {HB_TAG('D','U','J',' ')}},     /* Dhuwal */
+  {"dwy",       {HB_TAG('D','U','J',' ')}},     /* Dhuwaya -> Dhuwal */
+  {"dyu",       {HB_TAG('J','U','L',' ')}},     /* Dyula -> Jula */
+  {"dz",        {HB_TAG('D','Z','N',' ')}},     /* Dzongkha */
+  {"ee",        {HB_TAG('E','W','E',' ')}},     /* Ewe */
+  {"efi",       {HB_TAG('E','F','I',' ')}},     /* Efik */
+  {"ekk",       {HB_TAG('E','T','I',' ')}},     /* Standard Estonian -> Estonian */
+  {"el",        {HB_TAG('E','L','L',' ')}},     /* Modern Greek (1453-) -> Greek */
+  {"emk",       {HB_TAG('E','M','K',' '),       /* Eastern Maninkakan */
+                 HB_TAG('M','N','K',' ')}},     /* Eastern Maninkakan -> Maninka */
+  {"en",        {HB_TAG('E','N','G',' ')}},     /* English */
+  {"enb",       {HB_TAG('K','A','L',' ')}},     /* Markweeta -> Kalenjin */
+  {"enf",       {HB_TAG('F','N','E',' ')}},     /* Forest Enets -> Forest Nenets */
+  {"enh",       {HB_TAG('T','N','E',' ')}},     /* Tundra Enets -> Tundra Nenets */
+  {"eo",        {HB_TAG('N','T','O',' ')}},     /* Esperanto */
+  {"es",        {HB_TAG('E','S','P',' ')}},     /* Spanish */
+  {"esg",       {HB_TAG('G','O','N',' ')}},     /* Aheri Gondi -> Gondi */
+  {"esi",       {HB_TAG('I','P','K',' ')}},     /* North Alaskan Inupiatun -> Inupiat */
+  {"esk",       {HB_TAG('I','P','K',' ')}},     /* Northwest Alaska Inupiatun -> Inupiat */
+  {"esu",       {HB_TAG('E','S','U',' ')}},     /* Central Yupik */
+  {"et",        {HB_TAG('E','T','I',' ')}},     /* Estonian [macrolanguage] */
+  {"eto",       {HB_TAG('B','T','I',' ')}},     /* Eton (Cameroon) -> Beti */
+  {"eu",        {HB_TAG('E','U','Q',' ')}},     /* Basque */
+  {"eve",       {HB_TAG('E','V','N',' ')}},     /* Even */
+  {"evn",       {HB_TAG('E','V','K',' ')}},     /* Evenki */
+  {"ewo",       {HB_TAG('B','T','I',' ')}},     /* Ewondo -> Beti */
+  {"eyo",       {HB_TAG('K','A','L',' ')}},     /* Keiyo -> Kalenjin */
+  {"fa",        {HB_TAG('F','A','R',' ')}},     /* Persian [macrolanguage] */
+  {"fan",       {HB_TAG('F','A','N','0')}},     /* Fang (Equatorial Guinea) */
+  {"fat",       {HB_TAG('F','A','T',' ')}},     /* Fanti */
+  {"fbl",       {HB_TAG('B','I','K',' ')}},     /* West Albay Bikol -> Bikol */
+  {"ff",        {HB_TAG('F','U','L',' ')}},     /* Fulah [macrolanguage] */
+  {"ffm",       {HB_TAG('F','U','L',' ')}},     /* Maasina Fulfulde -> Fulah */
+  {"fi",        {HB_TAG('F','I','N',' ')}},     /* Finnish */
+  {"fil",       {HB_TAG('P','I','L',' ')}},     /* Filipino */
+  {"fj",        {HB_TAG('F','J','I',' ')}},     /* Fijian */
+  {"flm",       {HB_TAG('H','A','L',' '),       /* Halam (Falam Chin) (retired code) */
+                 HB_TAG('Q','I','N',' ')}},     /* Falam Chin (retired code) -> Chin */
+  {"fmp",       {HB_TAG('F','M','P',' ')}},     /* Fe'fe' */
+  {"fo",        {HB_TAG('F','O','S',' ')}},     /* Faroese */
+  {"fon",       {HB_TAG('F','O','N',' ')}},     /* Fon */
+  {"fr",        {HB_TAG('F','R','A',' ')}},     /* French */
+  {"frc",       {HB_TAG('F','R','C',' ')}},     /* Cajun French */
+  {"frp",       {HB_TAG('F','R','P',' ')}},     /* Arpitan */
+  {"fub",       {HB_TAG('F','U','L',' ')}},     /* Adamawa Fulfulde -> Fulah */
+  {"fuc",       {HB_TAG('F','U','L',' ')}},     /* Pulaar -> Fulah */
+  {"fue",       {HB_TAG('F','U','L',' ')}},     /* Borgu Fulfulde -> Fulah */
+  {"fuf",       {HB_TAG('F','T','A',' ')}},     /* Pular -> Futa */
+  {"fuh",       {HB_TAG('F','U','L',' ')}},     /* Western Niger Fulfulde -> Fulah */
+  {"fui",       {HB_TAG('F','U','L',' ')}},     /* Bagirmi Fulfulde -> Fulah */
+  {"fuq",       {HB_TAG('F','U','L',' ')}},     /* Central-Eastern Niger Fulfulde -> Fulah */
+  {"fur",       {HB_TAG('F','R','L',' ')}},     /* Friulian */
+  {"fuv",       {HB_TAG('F','U','V',' ')}},     /* Nigerian Fulfulde */
+  {"fy",        {HB_TAG('F','R','I',' ')}},     /* Western Frisian -> Frisian */
+  {"ga",        {HB_TAG('I','R','I',' ')}},     /* Irish */
+  {"gaa",       {HB_TAG('G','A','D',' ')}},     /* Ga */
+  {"gag",       {HB_TAG('G','A','G',' ')}},     /* Gagauz */
+  {"gan",       {HB_TAG('Z','H','S',' ')}},     /* Gan Chinese -> Chinese Simplified */
+  {"gax",       {HB_TAG('O','R','O',' ')}},     /* Borana-Arsi-Guji Oromo -> Oromo */
+  {"gaz",       {HB_TAG('O','R','O',' ')}},     /* West Central Oromo -> Oromo */
+  {"gbm",       {HB_TAG('G','A','W',' ')}},     /* Garhwali */
+  {"gce",       {HB_TAG('A','T','H',' ')}},     /* Galice -> Athapaskan */
+  {"gd",        {HB_TAG('G','A','E',' ')}},     /* Scottish Gaelic (Gaelic) */
+  {"gda",       {HB_TAG('R','A','J',' ')}},     /* Gade Lohar -> Rajasthani */
+  {"gez",       {HB_TAG('G','E','Z',' ')}},     /* Geez */
+  {"ggo",       {HB_TAG('G','O','N',' ')}},     /* Southern Gondi (retired code) -> Gondi */
+  {"gih",       {HB_TAG('G','I','H',' ')}},     /* Githabul */
+  {"gil",       {HB_TAG('G','I','L','0')}},     /* Kiribati (Gilbertese) */
+  {"gju",       {HB_TAG('R','A','J',' ')}},     /* Gujari -> Rajasthani */
+  {"gkp",       {HB_TAG('G','K','P',' ')}},     /* Guinea Kpelle -> Kpelle (Guinea) */
+  {"gl",        {HB_TAG('G','A','L',' ')}},     /* Galician */
+  {"gld",       {HB_TAG('N','A','N',' ')}},     /* Nanai */
+  {"glk",       {HB_TAG('G','L','K',' ')}},     /* Gilaki */
+  {"gn",        {HB_TAG('G','U','A',' ')}},     /* Guarani [macrolanguage] */
+  {"gnn",       {HB_TAG('G','N','N',' ')}},     /* Gumatj */
+  {"gno",       {HB_TAG('G','O','N',' ')}},     /* Northern Gondi -> Gondi */
+  {"gnw",       {HB_TAG('G','U','A',' ')}},     /* Western Bolivian Guaraní -> Guarani */
+  {"gog",       {HB_TAG('G','O','G',' ')}},     /* Gogo */
+  {"gom",       {HB_TAG('K','O','K',' ')}},     /* Goan Konkani -> Konkani */
+  {"gon",       {HB_TAG('G','O','N',' ')}},     /* Gondi [macrolanguage] */
+  {"grt",       {HB_TAG('G','R','O',' ')}},     /* Garo */
+  {"gru",       {HB_TAG('S','O','G',' ')}},     /* Kistane -> Sodo Gurage */
+  {"gsw",       {HB_TAG('A','L','S',' ')}},     /* Alsatian */
+  {"gu",        {HB_TAG('G','U','J',' ')}},     /* Gujarati */
+  {"guc",       {HB_TAG('G','U','C',' ')}},     /* Wayuu */
+  {"guf",       {HB_TAG('G','U','F',' ')}},     /* Gupapuyngu */
+  {"gug",       {HB_TAG('G','U','A',' ')}},     /* Paraguayan Guaraní -> Guarani */
+  {"gui",       {HB_TAG('G','U','A',' ')}},     /* Eastern Bolivian Guaraní -> Guarani */
+  {"guk",       {HB_TAG('G','M','Z',' '),       /* Gumuz */
+                 HB_TAG('G','U','K',' ')}},     /* Gumuz (SIL fonts) */
+  {"gun",       {HB_TAG('G','U','A',' ')}},     /* Mbyá Guaraní -> Guarani */
+  {"guz",       {HB_TAG('G','U','Z',' ')}},     /* Gusii */
+  {"gv",        {HB_TAG('M','N','X',' ')}},     /* Manx */
+  {"gwi",       {HB_TAG('A','T','H',' ')}},     /* Gwichʼin -> Athapaskan */
+  {"ha",        {HB_TAG('H','A','U',' ')}},     /* Hausa */
+  {"haa",       {HB_TAG('A','T','H',' ')}},     /* Han -> Athapaskan */
+  {"hae",       {HB_TAG('O','R','O',' ')}},     /* Eastern Oromo -> Oromo */
+  {"hak",       {HB_TAG('Z','H','S',' ')}},     /* Hakka Chinese -> Chinese Simplified */
+  {"har",       {HB_TAG('H','R','I',' ')}},     /* Harari */
+  {"haw",       {HB_TAG('H','A','W',' ')}},     /* Hawaiian */
+  {"hay",       {HB_TAG('H','A','Y',' ')}},     /* Haya */
+  {"haz",       {HB_TAG('H','A','Z',' ')}},     /* Hazaragi */
+  {"he",        {HB_TAG('I','W','R',' ')}},     /* Hebrew */
+  {"hea",       {HB_TAG('H','M','N',' ')}},     /* Northern Qiandong Miao -> Hmong */
+  {"hi",        {HB_TAG('H','I','N',' ')}},     /* Hindi */
+  {"hil",       {HB_TAG('H','I','L',' ')}},     /* Hiligaynon */
+  {"hji",       {HB_TAG('M','L','Y',' ')}},     /* Haji -> Malay */
+  {"hlt",       {HB_TAG('Q','I','N',' ')}},     /* Matu Chin -> Chin */
+  {"hma",       {HB_TAG('H','M','N',' ')}},     /* Southern Mashan Hmong -> Hmong */
+  {"hmc",       {HB_TAG('H','M','N',' ')}},     /* Central Huishui Hmong -> Hmong */
+  {"hmd",       {HB_TAG('H','M','N',' ')}},     /* Large Flowery Miao -> Hmong */
+  {"hme",       {HB_TAG('H','M','N',' ')}},     /* Eastern Huishui Hmong -> Hmong */
+  {"hmg",       {HB_TAG('H','M','N',' ')}},     /* Southwestern Guiyang Hmong -> Hmong */
+  {"hmh",       {HB_TAG('H','M','N',' ')}},     /* Southwestern Huishui Hmong -> Hmong */
+  {"hmi",       {HB_TAG('H','M','N',' ')}},     /* Northern Huishui Hmong -> Hmong */
+  {"hmj",       {HB_TAG('H','M','N',' ')}},     /* Ge -> Hmong */
+  {"hml",       {HB_TAG('H','M','N',' ')}},     /* Luopohe Hmong -> Hmong */
+  {"hmm",       {HB_TAG('H','M','N',' ')}},     /* Central Mashan Hmong -> Hmong */
+  {"hmn",       {HB_TAG('H','M','N',' ')}},     /* Hmong [macrolanguage] */
+  {"hmp",       {HB_TAG('H','M','N',' ')}},     /* Northern Mashan Hmong -> Hmong */
+  {"hmq",       {HB_TAG('H','M','N',' ')}},     /* Eastern Qiandong Miao -> Hmong */
+  {"hms",       {HB_TAG('H','M','N',' ')}},     /* Southern Qiandong Miao -> Hmong */
+  {"hmw",       {HB_TAG('H','M','N',' ')}},     /* Western Mashan Hmong -> Hmong */
+  {"hmy",       {HB_TAG('H','M','N',' ')}},     /* Southern Guiyang Hmong -> Hmong */
+  {"hmz",       {HB_TAG('H','M','N',' ')}},     /* Hmong Shua -> Hmong */
+  {"hnd",       {HB_TAG('H','N','D',' ')}},     /* Southern Hindko -> Hindko */
+  {"hne",       {HB_TAG('C','H','H',' ')}},     /* Chhattisgarhi -> Chattisgarhi */
+  {"hnj",       {HB_TAG('H','M','N',' ')}},     /* Hmong Njua -> Hmong */
+  {"hno",       {HB_TAG('H','N','D',' ')}},     /* Northern Hindko -> Hindko */
+  {"ho",        {HB_TAG('H','M','O',' ')}},     /* Hiri Motu */
+  {"hoc",       {HB_TAG('H','O',' ',' ')}},     /* Ho */
+  {"hoi",       {HB_TAG('A','T','H',' ')}},     /* Holikachuk -> Athapaskan */
+  {"hoj",       {HB_TAG('H','A','R',' ')}},     /* Hadothi -> Harauti */
+  {"hr",        {HB_TAG('H','R','V',' ')}},     /* Croatian */
+  {"hrm",       {HB_TAG('H','M','N',' ')}},     /* Horned Miao -> Hmong */
+  {"hsb",       {HB_TAG('U','S','B',' ')}},     /* Upper Sorbian */
+  {"hsn",       {HB_TAG('Z','H','S',' ')}},     /* Xiang Chinese -> Chinese Simplified */
+  {"ht",        {HB_TAG('H','A','I',' ')}},     /* Haitian (Haitian Creole) */
+  {"hu",        {HB_TAG('H','U','N',' ')}},     /* Hungarian */
+  {"huj",       {HB_TAG('H','M','N',' ')}},     /* Northern Guiyang Hmong -> Hmong */
+  {"hup",       {HB_TAG('A','T','H',' ')}},     /* Hupa -> Athapaskan */
+  {"hy",        {HB_TAG('H','Y','E','0'),       /* Armenian -> Armenian East */
+                 HB_TAG('H','Y','E',' ')}},     /* Armenian */
+  {"hyw",       {HB_TAG('H','Y','E',' ')}},     /* Western Armenian -> Armenian */
+  {"hz",        {HB_TAG('H','E','R',' ')}},     /* Herero */
+  {"ia",        {HB_TAG('I','N','A',' ')}},     /* Interlingua (International Auxiliary Language Association) */
+  {"iba",       {HB_TAG('I','B','A',' ')}},     /* Iban */
+  {"ibb",       {HB_TAG('I','B','B',' ')}},     /* Ibibio */
+  {"id",        {HB_TAG('I','N','D',' ')}},     /* Indonesian */
+  {"ida",       {HB_TAG('L','U','H',' ')}},     /* Idakho-Isukha-Tiriki -> Luyia */
+  {"ie",        {HB_TAG('I','L','E',' ')}},     /* Interlingue */
+  {"ig",        {HB_TAG('I','B','O',' ')}},     /* Igbo */
+  {"igb",       {HB_TAG('E','B','I',' ')}},     /* Ebira */
+  {"ii",        {HB_TAG('Y','I','M',' ')}},     /* Sichuan Yi -> Yi Modern */
+  {"ijc",       {HB_TAG('I','J','O',' ')}},     /* Izon -> Ijo */
+  {"ijo",       {HB_TAG('I','J','O',' ')}},     /* Ijo [family] */
+  {"ik",        {HB_TAG('I','P','K',' ')}},     /* Inupiaq [macrolanguage] -> Inupiat */
+  {"ike",       {HB_TAG('I','N','U',' ')}},     /* Eastern Canadian Inuktitut -> Inuktitut */
+  {"ikt",       {HB_TAG('I','N','U',' ')}},     /* Inuinnaqtun -> Inuktitut */
+  {"ilo",       {HB_TAG('I','L','O',' ')}},     /* Iloko -> Ilokano */
+  {"in",        {HB_TAG('I','N','D',' ')}},     /* Indonesian (retired code) */
+  {"ing",       {HB_TAG('A','T','H',' ')}},     /* Degexit'an -> Athapaskan */
+  {"inh",       {HB_TAG('I','N','G',' ')}},     /* Ingush */
+  {"io",        {HB_TAG('I','D','O',' ')}},     /* Ido */
+  {"is",        {HB_TAG('I','S','L',' ')}},     /* Icelandic */
+  {"it",        {HB_TAG('I','T','A',' ')}},     /* Italian */
+  {"iu",        {HB_TAG('I','N','U',' ')}},     /* Inuktitut [macrolanguage] */
+  {"iw",        {HB_TAG('I','W','R',' ')}},     /* Hebrew (retired code) */
+  {"ja",        {HB_TAG('J','A','N',' ')}},     /* Japanese */
+  {"jak",       {HB_TAG('M','L','Y',' ')}},     /* Jakun -> Malay */
+  {"jam",       {HB_TAG('J','A','M',' ')}},     /* Jamaican Creole English -> Jamaican Creole */
+  {"jax",       {HB_TAG('M','L','Y',' ')}},     /* Jambi Malay -> Malay */
+  {"jbo",       {HB_TAG('J','B','O',' ')}},     /* Lojban */
+  {"jct",       {HB_TAG('J','C','T',' ')}},     /* Krymchak */
+  {"ji",        {HB_TAG('J','I','I',' ')}},     /* Yiddish (retired code) */
+  {"jv",        {HB_TAG('J','A','V',' ')}},     /* Javanese */
+  {"jw",        {HB_TAG('J','A','V',' ')}},     /* Javanese (retired code) */
+  {"ka",        {HB_TAG('K','A','T',' ')}},     /* Georgian */
+  {"kaa",       {HB_TAG('K','R','K',' ')}},     /* Kara-Kalpak -> Karakalpak */
+  {"kab",       {HB_TAG('K','A','B','0')}},     /* Kabyle */
+  {"kam",       {HB_TAG('K','M','B',' ')}},     /* Kamba (Kenya) */
+  {"kar",       {HB_TAG('K','R','N',' ')}},     /* Karen [family] */
+  {"kbd",       {HB_TAG('K','A','B',' ')}},     /* Kabardian */
+  {"kby",       {HB_TAG('K','N','R',' ')}},     /* Manga Kanuri -> Kanuri */
+  {"kca",       {HB_TAG('K','H','K',' '),       /* Khanty -> Khanty-Kazim */
+                 HB_TAG('K','H','S',' '),       /* Khanty -> Khanty-Shurishkar */
+                 HB_TAG('K','H','V',' ')}},     /* Khanty -> Khanty-Vakhi */
+  {"kde",       {HB_TAG('K','D','E',' ')}},     /* Makonde */
+  {"kdr",       {HB_TAG('K','R','M',' ')}},     /* Karaim */
+  {"kdt",       {HB_TAG('K','U','Y',' ')}},     /* Kuy */
+  {"kea",       {HB_TAG('K','E','A',' ')}},     /* Kabuverdianu (Crioulo) */
+  {"kek",       {HB_TAG('K','E','K',' ')}},     /* Kekchi */
+  {"kex",       {HB_TAG('K','K','N',' ')}},     /* Kukna -> Kokni */
+  {"kfa",       {HB_TAG('K','O','D',' ')}},     /* Kodava -> Kodagu */
+  {"kfr",       {HB_TAG('K','A','C',' ')}},     /* Kachhi -> Kachchi */
+  {"kfx",       {HB_TAG('K','U','L',' ')}},     /* Kullu Pahari -> Kulvi */
+  {"kfy",       {HB_TAG('K','M','N',' ')}},     /* Kumaoni */
+  {"kg",        {HB_TAG('K','O','N','0')}},     /* Kongo [macrolanguage] */
+  {"kha",       {HB_TAG('K','S','I',' ')}},     /* Khasi */
+  {"khb",       {HB_TAG('X','B','D',' ')}},     /* Lü */
+  {"khk",       {HB_TAG('M','N','G',' ')}},     /* Halh Mongolian -> Mongolian */
+  {"kht",       {HB_TAG('K','H','N',' '),       /* Khamti -> Khamti Shan (Microsoft fonts) */
+                 HB_TAG('K','H','T',' ')}},     /* Khamti -> Khamti Shan (OpenType spec and SIL fonts) */
+  {"khw",       {HB_TAG('K','H','W',' ')}},     /* Khowar */
+  {"ki",        {HB_TAG('K','I','K',' ')}},     /* Kikuyu (Gikuyu) */
+  {"kiu",       {HB_TAG('K','I','U',' ')}},     /* Kirmanjki */
+  {"kj",        {HB_TAG('K','U','A',' ')}},     /* Kuanyama */
+  {"kjd",       {HB_TAG('K','J','D',' ')}},     /* Southern Kiwai */
+  {"kjh",       {HB_TAG('K','H','A',' ')}},     /* Khakas -> Khakass */
+  {"kjp",       {HB_TAG('K','J','P',' ')}},     /* Pwo Eastern Karen -> Eastern Pwo Karen */
+  {"kjz",       {HB_TAG('K','J','Z',' ')}},     /* Bumthangkha */
+  {"kk",        {HB_TAG('K','A','Z',' ')}},     /* Kazakh */
+  {"kkz",       {HB_TAG('A','T','H',' ')}},     /* Kaska -> Athapaskan */
+  {"kl",        {HB_TAG('G','R','N',' ')}},     /* Greenlandic */
+  {"kln",       {HB_TAG('K','A','L',' ')}},     /* Kalenjin [macrolanguage] */
+  {"km",        {HB_TAG('K','H','M',' ')}},     /* Khmer */
+  {"kmb",       {HB_TAG('M','B','N',' ')}},     /* Kimbundu -> Mbundu */
+  {"kmr",       {HB_TAG('K','U','R',' ')}},     /* Northern Kurdish -> Kurdish */
+  {"kmw",       {HB_TAG('K','M','O',' ')}},     /* Komo (Democratic Republic of Congo) */
+  {"kmz",       {HB_TAG('K','M','Z',' ')}},     /* Khorasani Turkish -> Khorasani Turkic */
+  {"kn",        {HB_TAG('K','A','N',' ')}},     /* Kannada */
+  {"knc",       {HB_TAG('K','N','R',' ')}},     /* Central Kanuri -> Kanuri */
+  {"kng",       {HB_TAG('K','O','N','0')}},     /* Koongo -> Kongo */
+  {"knn",       {HB_TAG('K','O','K',' ')}},     /* Konkani */
+  {"ko",        {HB_TAG('K','O','R',' ')}},     /* Korean */
+  {"koi",       {HB_TAG('K','O','P',' ')}},     /* Komi-Permyak */
+  {"kok",       {HB_TAG('K','O','K',' ')}},     /* Konkani [macrolanguage] */
+  {"kos",       {HB_TAG('K','O','S',' ')}},     /* Kosraean */
+  {"koy",       {HB_TAG('A','T','H',' ')}},     /* Koyukon -> Athapaskan */
+  {"kpe",       {HB_TAG('K','P','L',' ')}},     /* Kpelle [macrolanguage] */
+  {"kpv",       {HB_TAG('K','O','Z',' ')}},     /* Komi-Zyrian */
+  {"kpy",       {HB_TAG('K','Y','K',' ')}},     /* Koryak */
+  {"kqs",       {HB_TAG('K','I','S',' ')}},     /* Northern Kissi -> Kisii */
+  {"kqy",       {HB_TAG('K','R','T',' ')}},     /* Koorete */
+  {"kr",        {HB_TAG('K','N','R',' ')}},     /* Kanuri [macrolanguage] */
+  {"krc",       {HB_TAG('K','A','R',' '),       /* Karachay-Balkar -> Karachay */
+                 HB_TAG('B','A','L',' ')}},     /* Karachay-Balkar -> Balkar */
+  {"kri",       {HB_TAG('K','R','I',' ')}},     /* Krio */
+  {"krl",       {HB_TAG('K','R','L',' ')}},     /* Karelian */
+  {"krt",       {HB_TAG('K','N','R',' ')}},     /* Tumari Kanuri -> Kanuri */
+  {"kru",       {HB_TAG('K','U','U',' ')}},     /* Kurukh */
+  {"ks",        {HB_TAG('K','S','H',' ')}},     /* Kashmiri */
+  {"ksh",       {HB_TAG('K','S','H','0')}},     /* Kölsch -> Ripuarian */
+  {"kss",       {HB_TAG('K','I','S',' ')}},     /* Southern Kisi -> Kisii */
+  {"ksw",       {HB_TAG('K','S','W',' ')}},     /* S’gaw Karen */
+  {"ktb",       {HB_TAG('K','E','B',' ')}},     /* Kambaata -> Kebena */
+  {"ktu",       {HB_TAG('K','O','N',' ')}},     /* Kituba (Democratic Republic of Congo) -> Kikongo */
+  {"ktw",       {HB_TAG('A','T','H',' ')}},     /* Kato -> Athapaskan */
+  {"ku",        {HB_TAG('K','U','R',' ')}},     /* Kurdish [macrolanguage] */
+  {"kum",       {HB_TAG('K','U','M',' ')}},     /* Kumyk */
+  {"kuu",       {HB_TAG('A','T','H',' ')}},     /* Upper Kuskokwim -> Athapaskan */
+  {"kv",        {HB_TAG('K','O','M',' ')}},     /* Komi [macrolanguage] */
+  {"kvb",       {HB_TAG('M','L','Y',' ')}},     /* Kubu -> Malay */
+  {"kvr",       {HB_TAG('M','L','Y',' ')}},     /* Kerinci -> Malay */
+  {"kw",        {HB_TAG('C','O','R',' ')}},     /* Cornish */
+  {"kwy",       {HB_TAG('K','O','N','0')}},     /* San Salvador Kongo -> Kongo */
+  {"kxc",       {HB_TAG('K','M','S',' ')}},     /* Konso -> Komso */
+  {"kxd",       {HB_TAG('M','L','Y',' ')}},     /* Brunei -> Malay */
+  {"kxu",       {HB_TAG('K','U','I',' ')}},     /* Kui (India) */
+  {"ky",        {HB_TAG('K','I','R',' ')}},     /* Kirghiz (Kyrgyz) */
+  {"kyu",       {HB_TAG('K','Y','U',' ')}},     /* Western Kayah */
+  {"la",        {HB_TAG('L','A','T',' ')}},     /* Latin */
+  {"lad",       {HB_TAG('J','U','D',' ')}},     /* Ladino */
+  {"lb",        {HB_TAG('L','T','Z',' ')}},     /* Luxembourgish */
+  {"lbe",       {HB_TAG('L','A','K',' ')}},     /* Lak */
+  {"lbj",       {HB_TAG('L','D','K',' ')}},     /* Ladakhi */
+  {"lbl",       {HB_TAG('B','I','K',' ')}},     /* Libon Bikol -> Bikol */
+  {"lce",       {HB_TAG('M','L','Y',' ')}},     /* Loncong -> Malay */
+  {"lcf",       {HB_TAG('M','L','Y',' ')}},     /* Lubu -> Malay */
+  {"ldi",       {HB_TAG('K','O','N','0')}},     /* Laari -> Kongo */
+  {"lez",       {HB_TAG('L','E','Z',' ')}},     /* Lezghian -> Lezgi */
+  {"lg",        {HB_TAG('L','U','G',' ')}},     /* Ganda */
+  {"li",        {HB_TAG('L','I','M',' ')}},     /* Limburgish */
+  {"lif",       {HB_TAG('L','M','B',' ')}},     /* Limbu */
+  {"lij",       {HB_TAG('L','I','J',' ')}},     /* Ligurian */
+  {"lis",       {HB_TAG('L','I','S',' ')}},     /* Lisu */
+  {"liw",       {HB_TAG('M','L','Y',' ')}},     /* Col -> Malay */
+  {"ljp",       {HB_TAG('L','J','P',' ')}},     /* Lampung Api -> Lampung */
+  {"lkb",       {HB_TAG('L','U','H',' ')}},     /* Kabras -> Luyia */
+  {"lki",       {HB_TAG('L','K','I',' ')}},     /* Laki */
+  {"lko",       {HB_TAG('L','U','H',' ')}},     /* Khayo -> Luyia */
+  {"lks",       {HB_TAG('L','U','H',' ')}},     /* Kisa -> Luyia */
+  {"lld",       {HB_TAG('L','A','D',' ')}},     /* Ladin */
+  {"lmn",       {HB_TAG('L','A','M',' ')}},     /* Lambadi -> Lambani */
+  {"lmo",       {HB_TAG('L','M','O',' ')}},     /* Lombard */
+  {"ln",        {HB_TAG('L','I','N',' ')}},     /* Lingala */
+  {"lo",        {HB_TAG('L','A','O',' ')}},     /* Lao */
+  {"lom",       {HB_TAG('L','O','M',' ')}},     /* Loma (Liberia) */
+  {"lrc",       {HB_TAG('L','R','C',' ')}},     /* Northern Luri -> Luri */
+  {"lri",       {HB_TAG('L','U','H',' ')}},     /* Marachi -> Luyia */
+  {"lrm",       {HB_TAG('L','U','H',' ')}},     /* Marama -> Luyia */
+  {"lsm",       {HB_TAG('L','U','H',' ')}},     /* Saamia -> Luyia */
+  {"lt",        {HB_TAG('L','T','H',' ')}},     /* Lithuanian */
+  {"ltg",       {HB_TAG('L','V','I',' ')}},     /* Latgalian -> Latvian */
+  {"lto",       {HB_TAG('L','U','H',' ')}},     /* Tsotso -> Luyia */
+  {"lts",       {HB_TAG('L','U','H',' ')}},     /* Tachoni -> Luyia */
+  {"lu",        {HB_TAG('L','U','B',' ')}},     /* Luba-Katanga */
+  {"lua",       {HB_TAG('L','U','A',' ')}},     /* Luba-Lulua */
+  {"luo",       {HB_TAG('L','U','O',' ')}},     /* Luo (Kenya and Tanzania) */
+  {"lus",       {HB_TAG('M','I','Z',' ')}},     /* Lushai -> Mizo */
+  {"luy",       {HB_TAG('L','U','H',' ')}},     /* Luyia [macrolanguage] */
+  {"luz",       {HB_TAG('L','R','C',' ')}},     /* Southern Luri -> Luri */
+  {"lv",        {HB_TAG('L','V','I',' ')}},     /* Latvian [macrolanguage] */
+  {"lvs",       {HB_TAG('L','V','I',' ')}},     /* Standard Latvian -> Latvian */
+  {"lwg",       {HB_TAG('L','U','H',' ')}},     /* Wanga -> Luyia */
+  {"lzh",       {HB_TAG('Z','H','T',' ')}},     /* Literary Chinese -> Chinese Traditional */
+  {"lzz",       {HB_TAG('L','A','Z',' ')}},     /* Laz */
+  {"mad",       {HB_TAG('M','A','D',' ')}},     /* Madurese -> Madura */
+  {"mag",       {HB_TAG('M','A','G',' ')}},     /* Magahi */
+  {"mai",       {HB_TAG('M','T','H',' ')}},     /* Maithili */
+  {"mak",       {HB_TAG('M','K','R',' ')}},     /* Makasar */
+  {"mam",       {HB_TAG('M','A','M',' ')}},     /* Mam */
+  {"man",       {HB_TAG('M','N','K',' ')}},     /* Mandingo [macrolanguage] -> Maninka */
+  {"max",       {HB_TAG('M','L','Y',' ')}},     /* North Moluccan Malay -> Malay */
+  {"mbo",       {HB_TAG('M','B','O',' ')}},     /* Mbo (Cameroon) */
+  {"mct",       {HB_TAG('B','T','I',' ')}},     /* Mengisa -> Beti */
+  {"mdf",       {HB_TAG('M','O','K',' ')}},     /* Moksha */
+  {"mdr",       {HB_TAG('M','D','R',' ')}},     /* Mandar */
+  {"mdy",       {HB_TAG('M','L','E',' ')}},     /* Male (Ethiopia) */
+  {"men",       {HB_TAG('M','D','E',' ')}},     /* Mende (Sierra Leone) */
+  {"meo",       {HB_TAG('M','L','Y',' ')}},     /* Kedah Malay -> Malay */
+  {"mer",       {HB_TAG('M','E','R',' ')}},     /* Meru */
+  {"mfa",       {HB_TAG('M','F','A',' ')}},     /* Pattani Malay */
+  {"mfb",       {HB_TAG('M','L','Y',' ')}},     /* Bangka -> Malay */
+  {"mfe",       {HB_TAG('M','F','E',' ')}},     /* Morisyen */
+  {"mg",        {HB_TAG('M','L','G',' ')}},     /* Malagasy [macrolanguage] */
+  {"mh",        {HB_TAG('M','A','H',' ')}},     /* Marshallese */
+  {"mhr",       {HB_TAG('L','M','A',' ')}},     /* Eastern Mari -> Low Mari */
+  {"mhv",       {HB_TAG('A','R','K',' ')}},     /* Arakanese (retired code) -> Rakhine */
+  {"mi",        {HB_TAG('M','R','I',' ')}},     /* Maori */
+  {"min",       {HB_TAG('M','I','N',' ')}},     /* Minangkabau */
+  {"mk",        {HB_TAG('M','K','D',' ')}},     /* Macedonian */
+  {"mku",       {HB_TAG('M','N','K',' ')}},     /* Konyanka Maninka -> Maninka */
+  {"mkw",       {HB_TAG('M','K','W',' ')}},     /* Kituba (Congo) */
+  {"ml",        {HB_TAG('M','A','L',' '),       /* Malayalam -> Malayalam Traditional */
+                 HB_TAG('M','L','R',' ')}},     /* Malayalam -> Malayalam Reformed */
+  {"mlq",       {HB_TAG('M','L','N',' '),       /* Western Maninkakan -> Malinke */
+                 HB_TAG('M','N','K',' ')}},     /* Western Maninkakan -> Maninka */
+  {"mmr",       {HB_TAG('H','M','N',' ')}},     /* Western Xiangxi Miao -> Hmong */
+  {"mn",        {HB_TAG('M','N','G',' ')}},     /* Mongolian [macrolanguage] */
+  {"mnc",       {HB_TAG('M','C','H',' ')}},     /* Manchu */
+  {"mni",       {HB_TAG('M','N','I',' ')}},     /* Manipuri */
+  {"mnk",       {HB_TAG('M','N','D',' '),       /* Mandinka */
+                 HB_TAG('M','N','K',' ')}},     /* Mandinka -> Maninka */
+  {"mnp",       {HB_TAG('Z','H','S',' ')}},     /* Min Bei Chinese -> Chinese Simplified */
+  {"mns",       {HB_TAG('M','A','N',' ')}},     /* Mansi */
+  {"mnw",       {HB_TAG('M','O','N',' ')}},     /* Mon */
+  {"mo",        {HB_TAG('M','O','L',' ')}},     /* Moldavian (retired code) */
+  {"moh",       {HB_TAG('M','O','H',' ')}},     /* Mohawk */
+  {"mos",       {HB_TAG('M','O','S',' ')}},     /* Mossi */
+  {"mpe",       {HB_TAG('M','A','J',' ')}},     /* Majang */
+  {"mqg",       {HB_TAG('M','L','Y',' ')}},     /* Kota Bangun Kutai Malay -> Malay */
+  {"mr",        {HB_TAG('M','A','R',' ')}},     /* Marathi */
+  {"mrh",       {HB_TAG('Q','I','N',' ')}},     /* Mara Chin -> Chin */
+  {"mrj",       {HB_TAG('H','M','A',' ')}},     /* Western Mari -> High Mari */
+  {"ms",        {HB_TAG('M','L','Y',' ')}},     /* Malay [macrolanguage] */
+  {"msc",       {HB_TAG('M','N','K',' ')}},     /* Sankaran Maninka -> Maninka */
+  {"msh",       {HB_TAG('M','L','G',' ')}},     /* Masikoro Malagasy -> Malagasy */
+  {"msi",       {HB_TAG('M','L','Y',' ')}},     /* Sabah Malay -> Malay */
+  {"mt",        {HB_TAG('M','T','S',' ')}},     /* Maltese */
+  {"mtr",       {HB_TAG('M','A','W',' ')}},     /* Mewari -> Marwari */
+  {"mui",       {HB_TAG('M','L','Y',' ')}},     /* Musi -> Malay */
+  {"mup",       {HB_TAG('R','A','J',' ')}},     /* Malvi -> Rajasthani */
+  {"muq",       {HB_TAG('H','M','N',' ')}},     /* Eastern Xiangxi Miao -> Hmong */
+  {"mus",       {HB_TAG('M','U','S',' ')}},     /* Creek -> Muscogee */
+  {"mvb",       {HB_TAG('A','T','H',' ')}},     /* Mattole -> Athapaskan */
+  {"mve",       {HB_TAG('M','A','W',' ')}},     /* Marwari (Pakistan) */
+  {"mvf",       {HB_TAG('M','N','G',' ')}},     /* Peripheral Mongolian -> Mongolian */
+  {"mwk",       {HB_TAG('M','N','K',' ')}},     /* Kita Maninkakan -> Maninka */
+  {"mwl",       {HB_TAG('M','W','L',' ')}},     /* Mirandese */
+  {"mwr",       {HB_TAG('M','A','W',' ')}},     /* Marwari [macrolanguage] */
+  {"mww",       {HB_TAG('M','W','W',' ')}},     /* Hmong Daw */
+  {"my",        {HB_TAG('B','R','M',' ')}},     /* Burmese */
+  {"mym",       {HB_TAG('M','E','N',' ')}},     /* Me'en */
+  {"myn",       {HB_TAG('M','Y','N',' ')}},     /* Mayan [family] */
+  {"myq",       {HB_TAG('M','N','K',' ')}},     /* Forest Maninka (retired code) -> Maninka */
+  {"myv",       {HB_TAG('E','R','Z',' ')}},     /* Erzya */
+  {"mzn",       {HB_TAG('M','Z','N',' ')}},     /* Mazanderani */
+  {"na",        {HB_TAG('N','A','U',' ')}},     /* Nauru -> Nauruan */
+  {"nag",       {HB_TAG('N','A','G',' ')}},     /* Naga Pidgin -> Naga-Assamese */
+  {"nah",       {HB_TAG('N','A','H',' ')}},     /* Nahuatl [family] */
+  {"nan",       {HB_TAG('Z','H','S',' ')}},     /* Min Nan Chinese -> Chinese Simplified */
+  {"nap",       {HB_TAG('N','A','P',' ')}},     /* Neapolitan */
+  {"nb",        {HB_TAG('N','O','R',' ')}},     /* Norwegian Bokmål -> Norwegian */
+  {"nd",        {HB_TAG('N','D','B',' ')}},     /* North Ndebele -> Ndebele */
+  {"ndc",       {HB_TAG('N','D','C',' ')}},     /* Ndau */
+  {"nds",       {HB_TAG('N','D','S',' ')}},     /* Low Saxon */
+  {"ne",        {HB_TAG('N','E','P',' ')}},     /* Nepali [macrolanguage] */
+  {"new",       {HB_TAG('N','E','W',' ')}},     /* Newari */
+  {"ng",        {HB_TAG('N','D','G',' ')}},     /* Ndonga */
+  {"nga",       {HB_TAG('N','G','A',' ')}},     /* Ngbaka */
+  {"ngl",       {HB_TAG('L','M','W',' ')}},     /* Lomwe */
+  {"ngo",       {HB_TAG('S','X','T',' ')}},     /* Ngoni -> Sutu */
+  {"nhd",       {HB_TAG('G','U','A',' ')}},     /* Chiripá -> Guarani */
+  {"niq",       {HB_TAG('K','A','L',' ')}},     /* Nandi -> Kalenjin */
+  {"niu",       {HB_TAG('N','I','U',' ')}},     /* Niuean */
+  {"niv",       {HB_TAG('G','I','L',' ')}},     /* Gilyak */
+  {"njz",       {HB_TAG('N','I','S',' ')}},     /* Nyishi -> Nisi */
+  {"nl",        {HB_TAG('N','L','D',' ')}},     /* Dutch */
+  {"nle",       {HB_TAG('L','U','H',' ')}},     /* East Nyala -> Luyia */
+  {"nn",        {HB_TAG('N','Y','N',' ')}},     /* Norwegian Nynorsk (Nynorsk, Norwegian) */
+  {"no",        {HB_TAG('N','O','R',' ')}},     /* Norwegian [macrolanguage] */
+  {"nod",       {HB_TAG('N','T','A',' ')}},     /* Northern Thai -> Northern Tai */
+  {"noe",       {HB_TAG('N','O','E',' ')}},     /* Nimadi */
+  {"nog",       {HB_TAG('N','O','G',' ')}},     /* Nogai */
+  {"nov",       {HB_TAG('N','O','V',' ')}},     /* Novial */
+  {"npi",       {HB_TAG('N','E','P',' ')}},     /* Nepali */
+  {"nqo",       {HB_TAG('N','K','O',' ')}},     /* N'Ko */
+  {"nr",        {HB_TAG('N','D','B',' ')}},     /* South Ndebele -> Ndebele */
+  {"nsk",       {HB_TAG('N','A','S',' ')}},     /* Naskapi */
+  {"nso",       {HB_TAG('N','S','O',' ')}},     /* Pedi -> Sotho, Northern */
+  {"nv",        {HB_TAG('N','A','V',' '),       /* Navajo */
+                 HB_TAG('A','T','H',' ')}},     /* Navajo -> Athapaskan */
+  {"ny",        {HB_TAG('C','H','I',' ')}},     /* Chichewa (Chewa, Nyanja) */
+  {"nyd",       {HB_TAG('L','U','H',' ')}},     /* Nyore -> Luyia */
+  {"nym",       {HB_TAG('N','Y','M',' ')}},     /* Nyamwezi */
+  {"nyn",       {HB_TAG('N','K','L',' ')}},     /* Nyankole */
+  {"nza",       {HB_TAG('N','Z','A',' ')}},     /* Tigon Mbembe -> Mbembe Tigon */
+  {"oc",        {HB_TAG('O','C','I',' ')}},     /* Occitan (post 1500) */
+  {"oj",        {HB_TAG('O','J','B',' ')}},     /* Ojibwa [macrolanguage] -> Ojibway */
+  {"ojb",       {HB_TAG('O','J','B',' ')}},     /* Northwestern Ojibwa -> Ojibway */
+  {"ojc",       {HB_TAG('O','J','B',' ')}},     /* Central Ojibwa -> Ojibway */
+  {"ojg",       {HB_TAG('O','J','B',' ')}},     /* Eastern Ojibwa -> Ojibway */
+  {"ojs",       {HB_TAG('O','C','R',' ')}},     /* Severn Ojibwa -> Oji-Cree */
+  {"ojw",       {HB_TAG('O','J','B',' ')}},     /* Western Ojibwa -> Ojibway */
+  {"oki",       {HB_TAG('K','A','L',' ')}},     /* Okiek -> Kalenjin */
+  {"okm",       {HB_TAG('K','O','H',' ')}},     /* Middle Korean (10th-16th cent.) -> Korean Old Hangul */
+  {"om",        {HB_TAG('O','R','O',' ')}},     /* Oromo [macrolanguage] */
+  {"or",        {HB_TAG('O','R','I',' ')}},     /* Odia (formerly Oriya) [macrolanguage] */
+  {"orc",       {HB_TAG('O','R','O',' ')}},     /* Orma -> Oromo */
+  {"orn",       {HB_TAG('M','L','Y',' ')}},     /* Orang Kanaq -> Malay */
+  {"ors",       {HB_TAG('M','L','Y',' ')}},     /* Orang Seletar -> Malay */
+  {"ory",       {HB_TAG('O','R','I',' ')}},     /* Odia (formerly Oriya) */
+  {"os",        {HB_TAG('O','S','S',' ')}},     /* Ossetian */
+  {"otw",       {HB_TAG('O','J','B',' ')}},     /* Ottawa -> Ojibway */
+  {"pa",        {HB_TAG('P','A','N',' ')}},     /* Punjabi */
+  {"pag",       {HB_TAG('P','A','G',' ')}},     /* Pangasinan */
+  {"pam",       {HB_TAG('P','A','M',' ')}},     /* Pampanga -> Pampangan */
+  {"pap",       {HB_TAG('P','A','P','0')}},     /* Papiamento -> Papiamentu */
+  {"pau",       {HB_TAG('P','A','U',' ')}},     /* Palauan */
+  {"pbt",       {HB_TAG('P','A','S',' ')}},     /* Southern Pashto -> Pashto */
+  {"pbu",       {HB_TAG('P','A','S',' ')}},     /* Northern Pashto -> Pashto */
+  {"pcc",       {HB_TAG('P','C','C',' ')}},     /* Bouyei */
+  {"pcd",       {HB_TAG('P','C','D',' ')}},     /* Picard */
+  {"pce",       {HB_TAG('P','L','G',' ')}},     /* Ruching Palaung -> Palaung */
+  {"pck",       {HB_TAG('Q','I','N',' ')}},     /* Paite Chin -> Chin */
+  {"pdc",       {HB_TAG('P','D','C',' ')}},     /* Pennsylvania German */
+  {"pel",       {HB_TAG('M','L','Y',' ')}},     /* Pekal -> Malay */
+  {"pes",       {HB_TAG('F','A','R',' ')}},     /* Iranian Persian -> Persian */
+  {"pga",       {HB_TAG('A','R','A',' ')}},     /* Sudanese Creole Arabic -> Arabic */
+  {"phk",       {HB_TAG('P','H','K',' ')}},     /* Phake */
+  {"pi",        {HB_TAG('P','A','L',' ')}},     /* Pali */
+  {"pih",       {HB_TAG('P','I','H',' ')}},     /* Pitcairn-Norfolk -> Norfolk */
+  {"pko",       {HB_TAG('K','A','L',' ')}},     /* Pökoot -> Kalenjin */
+  {"pl",        {HB_TAG('P','L','K',' ')}},     /* Polish */
+  {"pll",       {HB_TAG('P','L','G',' ')}},     /* Shwe Palaung -> Palaung */
+  {"plp",       {HB_TAG('P','A','P',' ')}},     /* Palpa */
+  {"plt",       {HB_TAG('M','L','G',' ')}},     /* Plateau Malagasy -> Malagasy */
+  {"pms",       {HB_TAG('P','M','S',' ')}},     /* Piemontese */
+  {"pnb",       {HB_TAG('P','N','B',' ')}},     /* Western Panjabi */
+  {"poh",       {HB_TAG('P','O','H',' ')}},     /* Poqomchi' -> Pocomchi */
+  {"pon",       {HB_TAG('P','O','N',' ')}},     /* Pohnpeian */
+  {"ppa",       {HB_TAG('B','A','G',' ')}},     /* Pao (retired code) -> Baghelkhandi */
+  {"pro",       {HB_TAG('P','R','O',' ')}},     /* Old Provençal (to 1500) -> Provençal / Old Provençal */
+  {"prs",       {HB_TAG('D','R','I',' ')}},     /* Dari */
+  {"ps",        {HB_TAG('P','A','S',' ')}},     /* Pashto [macrolanguage] */
+  {"pse",       {HB_TAG('M','L','Y',' ')}},     /* Central Malay -> Malay */
+  {"pst",       {HB_TAG('P','A','S',' ')}},     /* Central Pashto -> Pashto */
+  {"pt",        {HB_TAG('P','T','G',' ')}},     /* Portuguese */
+  {"pwo",       {HB_TAG('P','W','O',' ')}},     /* Pwo Western Karen -> Western Pwo Karen */
+  {"qu",        {HB_TAG('Q','U','Z',' ')}},     /* Quechua [macrolanguage] */
+  {"qub",       {HB_TAG('Q','W','H',' ')}},     /* Huallaga Huánuco Quechua -> Quechua (Peru) */
+  {"quc",       {HB_TAG('Q','U','C',' ')}},     /* K’iche’ */
+  {"qud",       {HB_TAG('Q','V','I',' ')}},     /* Calderón Highland Quichua -> Quechua (Ecuador) */
+  {"quf",       {HB_TAG('Q','U','Z',' ')}},     /* Lambayeque Quechua -> Quechua */
+  {"qug",       {HB_TAG('Q','V','I',' ')}},     /* Chimborazo Highland Quichua -> Quechua (Ecuador) */
+  {"quh",       {HB_TAG('Q','U','H',' ')}},     /* South Bolivian Quechua -> Quechua (Bolivia) */
+  {"quk",       {HB_TAG('Q','U','Z',' ')}},     /* Chachapoyas Quechua -> Quechua */
+  {"qul",       {HB_TAG('Q','U','Z',' ')}},     /* North Bolivian Quechua -> Quechua */
+  {"qup",       {HB_TAG('Q','V','I',' ')}},     /* Southern Pastaza Quechua -> Quechua (Ecuador) */
+  {"qur",       {HB_TAG('Q','W','H',' ')}},     /* Yanahuanca Pasco Quechua -> Quechua (Peru) */
+  {"qus",       {HB_TAG('Q','U','H',' ')}},     /* Santiago del Estero Quichua -> Quechua (Bolivia) */
+  {"quw",       {HB_TAG('Q','V','I',' ')}},     /* Tena Lowland Quichua -> Quechua (Ecuador) */
+  {"qux",       {HB_TAG('Q','W','H',' ')}},     /* Yauyos Quechua -> Quechua (Peru) */
+  {"quy",       {HB_TAG('Q','U','Z',' ')}},     /* Ayacucho Quechua -> Quechua */
+  {"quz",       {HB_TAG('Q','U','Z',' ')}},     /* Cusco Quechua -> Quechua */
+  {"qva",       {HB_TAG('Q','W','H',' ')}},     /* Ambo-Pasco Quechua -> Quechua (Peru) */
+  {"qvc",       {HB_TAG('Q','U','Z',' ')}},     /* Cajamarca Quechua -> Quechua */
+  {"qve",       {HB_TAG('Q','U','Z',' ')}},     /* Eastern Apurímac Quechua -> Quechua */
+  {"qvh",       {HB_TAG('Q','W','H',' ')}},     /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua (Peru) */
+  {"qvi",       {HB_TAG('Q','V','I',' ')}},     /* Imbabura Highland Quichua -> Quechua (Ecuador) */
+  {"qvj",       {HB_TAG('Q','V','I',' ')}},     /* Loja Highland Quichua -> Quechua (Ecuador) */
+  {"qvl",       {HB_TAG('Q','W','H',' ')}},     /* Cajatambo North Lima Quechua -> Quechua (Peru) */
+  {"qvm",       {HB_TAG('Q','W','H',' ')}},     /* Margos-Yarowilca-Lauricocha Quechua -> Quechua (Peru) */
+  {"qvn",       {HB_TAG('Q','W','H',' ')}},     /* North Junín Quechua -> Quechua (Peru) */
+  {"qvo",       {HB_TAG('Q','V','I',' ')}},     /* Napo Lowland Quechua -> Quechua (Ecuador) */
+  {"qvp",       {HB_TAG('Q','W','H',' ')}},     /* Pacaraos Quechua -> Quechua (Peru) */
+  {"qvs",       {HB_TAG('Q','U','Z',' ')}},     /* San Martín Quechua -> Quechua */
+  {"qvw",       {HB_TAG('Q','W','H',' ')}},     /* Huaylla Wanca Quechua -> Quechua (Peru) */
+  {"qvz",       {HB_TAG('Q','V','I',' ')}},     /* Northern Pastaza Quichua -> Quechua (Ecuador) */
+  {"qwa",       {HB_TAG('Q','W','H',' ')}},     /* Corongo Ancash Quechua -> Quechua (Peru) */
+  {"qwc",       {HB_TAG('Q','U','Z',' ')}},     /* Classical Quechua -> Quechua */
+  {"qwh",       {HB_TAG('Q','W','H',' ')}},     /* Huaylas Ancash Quechua -> Quechua (Peru) */
+  {"qws",       {HB_TAG('Q','W','H',' ')}},     /* Sihuas Ancash Quechua -> Quechua (Peru) */
+  {"qxa",       {HB_TAG('Q','W','H',' ')}},     /* Chiquián Ancash Quechua -> Quechua (Peru) */
+  {"qxc",       {HB_TAG('Q','W','H',' ')}},     /* Chincha Quechua -> Quechua (Peru) */
+  {"qxh",       {HB_TAG('Q','W','H',' ')}},     /* Panao Huánuco Quechua -> Quechua (Peru) */
+  {"qxl",       {HB_TAG('Q','V','I',' ')}},     /* Salasaca Highland Quichua -> Quechua (Ecuador) */
+  {"qxn",       {HB_TAG('Q','W','H',' ')}},     /* Northern Conchucos Ancash Quechua -> Quechua (Peru) */
+  {"qxo",       {HB_TAG('Q','W','H',' ')}},     /* Southern Conchucos Ancash Quechua -> Quechua (Peru) */
+  {"qxp",       {HB_TAG('Q','U','Z',' ')}},     /* Puno Quechua -> Quechua */
+  {"qxr",       {HB_TAG('Q','V','I',' ')}},     /* Cañar Highland Quichua -> Quechua (Ecuador) */
+  {"qxt",       {HB_TAG('Q','W','H',' ')}},     /* Santa Ana de Tusi Pasco Quechua -> Quechua (Peru) */
+  {"qxu",       {HB_TAG('Q','U','Z',' ')}},     /* Arequipa-La Unión Quechua -> Quechua */
+  {"qxw",       {HB_TAG('Q','W','H',' ')}},     /* Jauja Wanca Quechua -> Quechua (Peru) */
+  {"rag",       {HB_TAG('L','U','H',' ')}},     /* Logooli -> Luyia */
+  {"raj",       {HB_TAG('R','A','J',' ')}},     /* Rajasthani [macrolanguage] */
+  {"rar",       {HB_TAG('R','A','R',' ')}},     /* Rarotongan */
+  {"rbb",       {HB_TAG('P','L','G',' ')}},     /* Rumai Palaung -> Palaung */
+  {"rbl",       {HB_TAG('B','I','K',' ')}},     /* Miraya Bikol -> Bikol */
+  {"rej",       {HB_TAG('R','E','J',' ')}},     /* Rejang */
+  {"ria",       {HB_TAG('R','I','A',' ')}},     /* Riang (India) */
+  {"rif",       {HB_TAG('R','I','F',' ')}},     /* Tarifit */
+  {"rit",       {HB_TAG('R','I','T',' ')}},     /* Ritarungo */
+  {"rki",       {HB_TAG('A','R','K',' ')}},     /* Rakhine */
+  {"rkw",       {HB_TAG('R','K','W',' ')}},     /* Arakwal */
+  {"rm",        {HB_TAG('R','M','S',' ')}},     /* Romansh */
+  {"rmc",       {HB_TAG('R','O','Y',' ')}},     /* Carpathian Romani -> Romany */
+  {"rmf",       {HB_TAG('R','O','Y',' ')}},     /* Kalo Finnish Romani -> Romany */
+  {"rml",       {HB_TAG('R','O','Y',' ')}},     /* Baltic Romani -> Romany */
+  {"rmn",       {HB_TAG('R','O','Y',' ')}},     /* Balkan Romani -> Romany */
+  {"rmo",       {HB_TAG('R','O','Y',' ')}},     /* Sinte Romani -> Romany */
+  {"rmw",       {HB_TAG('R','O','Y',' ')}},     /* Welsh Romani -> Romany */
+  {"rmy",       {HB_TAG('R','M','Y',' ')}},     /* Vlax Romani */
+  {"rmz",       {HB_TAG('A','R','K',' ')}},     /* Marma -> Rakhine */
+  {"rn",        {HB_TAG('R','U','N',' ')}},     /* Rundi */
+  {"rnl",       {HB_TAG('H','A','L',' ')}},     /* Ranglong -> Halam (Falam Chin) */
+  {"ro",        {HB_TAG('R','O','M',' ')}},     /* Romanian */
+  {"rom",       {HB_TAG('R','O','Y',' ')}},     /* Romany [macrolanguage] */
+  {"rtm",       {HB_TAG('R','T','M',' ')}},     /* Rotuman */
+  {"ru",        {HB_TAG('R','U','S',' ')}},     /* Russian */
+  {"rue",       {HB_TAG('R','S','Y',' ')}},     /* Rusyn */
+  {"rup",       {HB_TAG('R','U','P',' ')}},     /* Aromanian */
+  {"rw",        {HB_TAG('R','U','A',' ')}},     /* Kinyarwanda */
+  {"rwr",       {HB_TAG('M','A','W',' ')}},     /* Marwari (India) */
+  {"sa",        {HB_TAG('S','A','N',' ')}},     /* Sanskrit */
+  {"sah",       {HB_TAG('Y','A','K',' ')}},     /* Yakut -> Sakha */
+  {"sam",       {HB_TAG('P','A','A',' ')}},     /* Samaritan Aramaic -> Palestinian Aramaic */
+  {"sas",       {HB_TAG('S','A','S',' ')}},     /* Sasak */
+  {"sat",       {HB_TAG('S','A','T',' ')}},     /* Santali */
+  {"sc",        {HB_TAG('S','R','D',' ')}},     /* Sardinian [macrolanguage] */
+  {"sck",       {HB_TAG('S','A','D',' ')}},     /* Sadri */
+  {"scn",       {HB_TAG('S','C','N',' ')}},     /* Sicilian */
+  {"sco",       {HB_TAG('S','C','O',' ')}},     /* Scots */
+  {"scs",       {HB_TAG('S','C','S',' '),       /* North Slavey */
+                 HB_TAG('S','L','A',' '),       /* North Slavey -> Slavey */
+                 HB_TAG('A','T','H',' ')}},     /* North Slavey -> Athapaskan */
+  {"sd",        {HB_TAG('S','N','D',' ')}},     /* Sindhi */
+  {"sdc",       {HB_TAG('S','R','D',' ')}},     /* Sassarese Sardinian -> Sardinian */
+  {"sdh",       {HB_TAG('K','U','R',' ')}},     /* Southern Kurdish -> Kurdish */
+  {"sdn",       {HB_TAG('S','R','D',' ')}},     /* Gallurese Sardinian -> Sardinian */
+  {"se",        {HB_TAG('N','S','M',' ')}},     /* Northern Sami */
+  {"seh",       {HB_TAG('S','N','A',' ')}},     /* Sena */
+  {"sek",       {HB_TAG('A','T','H',' ')}},     /* Sekani -> Athapaskan */
+  {"sel",       {HB_TAG('S','E','L',' ')}},     /* Selkup */
+  {"sez",       {HB_TAG('Q','I','N',' ')}},     /* Senthang Chin -> Chin */
+  {"sfm",       {HB_TAG('H','M','N',' ')}},     /* Small Flowery Miao -> Hmong */
+  {"sg",        {HB_TAG('S','G','O',' ')}},     /* Sango */
+  {"sga",       {HB_TAG('S','G','A',' ')}},     /* Old Irish (to 900) */
+  {"sgc",       {HB_TAG('K','A','L',' ')}},     /* Kipsigis -> Kalenjin */
+  {"sgs",       {HB_TAG('S','G','S',' ')}},     /* Samogitian */
+  {"sgw",       {HB_TAG('C','H','G',' '),       /* Sebat Bet Gurage -> Chaha Gurage */
+                 HB_TAG('S','G','W',' ')}},     /* Sebat Bet Gurage -> Chaha Gurage (SIL fonts) */
+  {"shi",       {HB_TAG('S','H','I',' ')}},     /* Tachelhit */
+  {"shn",       {HB_TAG('S','H','N',' ')}},     /* Shan */
+  {"shu",       {HB_TAG('A','R','A',' ')}},     /* Chadian Arabic -> Arabic */
+  {"si",        {HB_TAG('S','N','H',' ')}},     /* Sinhala (Sinhalese) */
+  {"sid",       {HB_TAG('S','I','D',' ')}},     /* Sidamo */
+  {"sjd",       {HB_TAG('K','S','M',' ')}},     /* Kildin Sami */
+  {"sjo",       {HB_TAG('S','I','B',' ')}},     /* Xibe -> Sibe */
+  {"sk",        {HB_TAG('S','K','Y',' ')}},     /* Slovak */
+  {"skg",       {HB_TAG('M','L','G',' ')}},     /* Sakalava Malagasy -> Malagasy */
+  {"skr",       {HB_TAG('S','R','K',' ')}},     /* Saraiki */
+  {"sl",        {HB_TAG('S','L','V',' ')}},     /* Slovenian */
+  {"sm",        {HB_TAG('S','M','O',' ')}},     /* Samoan */
+  {"sma",       {HB_TAG('S','S','M',' ')}},     /* Southern Sami */
+  {"smj",       {HB_TAG('L','S','M',' ')}},     /* Lule Sami */
+  {"smn",       {HB_TAG('I','S','M',' ')}},     /* Inari Sami */
+  {"sms",       {HB_TAG('S','K','S',' ')}},     /* Skolt Sami */
+  {"sn",        {HB_TAG('S','N','A','0')}},     /* Shona */
+  {"snk",       {HB_TAG('S','N','K',' ')}},     /* Soninke */
+  {"so",        {HB_TAG('S','M','L',' ')}},     /* Somali */
+  {"sop",       {HB_TAG('S','O','P',' ')}},     /* Songe */
+  {"spv",       {HB_TAG('O','R','I',' ')}},     /* Sambalpuri -> Odia (formerly Oriya) */
+  {"spy",       {HB_TAG('K','A','L',' ')}},     /* Sabaot -> Kalenjin */
+  {"sq",        {HB_TAG('S','Q','I',' ')}},     /* Albanian [macrolanguage] */
+  {"sr",        {HB_TAG('S','R','B',' ')}},     /* Serbian */
+  {"src",       {HB_TAG('S','R','D',' ')}},     /* Logudorese Sardinian -> Sardinian */
+  {"sro",       {HB_TAG('S','R','D',' ')}},     /* Campidanese Sardinian -> Sardinian */
+  {"srr",       {HB_TAG('S','R','R',' ')}},     /* Serer */
+  {"srs",       {HB_TAG('A','T','H',' ')}},     /* Sarsi -> Athapaskan */
+  {"ss",        {HB_TAG('S','W','Z',' ')}},     /* Swati */
+  {"ssh",       {HB_TAG('A','R','A',' ')}},     /* Shihhi Arabic -> Arabic */
+  {"st",        {HB_TAG('S','O','T',' ')}},     /* Southern Sotho -> Sotho, Southern */
+  {"stq",       {HB_TAG('S','T','Q',' ')}},     /* Saterfriesisch -> Saterland Frisian */
+  {"stv",       {HB_TAG('S','I','G',' ')}},     /* Silt'e -> Silte Gurage */
+  {"su",        {HB_TAG('S','U','N',' ')}},     /* Sundanese */
+  {"suk",       {HB_TAG('S','U','K',' ')}},     /* Sukuma */
+  {"suq",       {HB_TAG('S','U','R',' ')}},     /* Suri */
+  {"sv",        {HB_TAG('S','V','E',' ')}},     /* Swedish */
+  {"sva",       {HB_TAG('S','V','A',' ')}},     /* Svan */
+  {"sw",        {HB_TAG('S','W','K',' ')}},     /* Swahili [macrolanguage] */
+  {"swb",       {HB_TAG('C','M','R',' ')}},     /* Maore Comorian -> Comorian */
+  {"swc",       {HB_TAG('S','W','K',' ')}},     /* Congo Swahili -> Swahili */
+  {"swh",       {HB_TAG('S','W','K',' ')}},     /* Swahili */
+  {"swv",       {HB_TAG('M','A','W',' ')}},     /* Shekhawati -> Marwari */
+  {"sxu",       {HB_TAG('S','X','U',' ')}},     /* Upper Saxon */
+  {"syc",       {HB_TAG('S','Y','R',' ')}},     /* Classical Syriac -> Syriac */
+  {"syl",       {HB_TAG('S','Y','L',' ')}},     /* Sylheti */
+  {"syr",       {HB_TAG('S','Y','R',' ')}},     /* Syriac [macrolanguage] */
+  {"szl",       {HB_TAG('S','Z','L',' ')}},     /* Silesian */
+  {"ta",        {HB_TAG('T','A','M',' ')}},     /* Tamil */
+  {"taa",       {HB_TAG('A','T','H',' ')}},     /* Lower Tanana -> Athapaskan */
+  {"tab",       {HB_TAG('T','A','B',' ')}},     /* Tabassaran -> Tabasaran */
+  {"taq",       {HB_TAG('T','M','H',' ')}},     /* Tamasheq -> Tamashek */
+  {"tau",       {HB_TAG('A','T','H',' ')}},     /* Upper Tanana -> Athapaskan */
+  {"tcb",       {HB_TAG('A','T','H',' ')}},     /* Tanacross -> Athapaskan */
+  {"tce",       {HB_TAG('A','T','H',' ')}},     /* Southern Tutchone -> Athapaskan */
+  {"tcp",       {HB_TAG('Q','I','N',' ')}},     /* Tawr Chin -> Chin */
+  {"tcy",       {HB_TAG('T','U','L',' ')}},     /* Tulu -> Tumbuka */
+  {"tcz",       {HB_TAG('Q','I','N',' ')}},     /* Thado Chin -> Chin */
+  {"tdd",       {HB_TAG('T','D','D',' ')}},     /* Tai Nüa -> Dehong Dai */
+  {"tdx",       {HB_TAG('M','L','G',' ')}},     /* Tandroy-Mahafaly Malagasy -> Malagasy */
+  {"te",        {HB_TAG('T','E','L',' ')}},     /* Telugu */
+  {"tec",       {HB_TAG('K','A','L',' ')}},     /* Terik -> Kalenjin */
+  {"tem",       {HB_TAG('T','M','N',' ')}},     /* Timne -> Temne */
+  {"tet",       {HB_TAG('T','E','T',' ')}},     /* Tetum */
+  {"tfn",       {HB_TAG('A','T','H',' ')}},     /* Tanaina -> Athapaskan */
+  {"tg",        {HB_TAG('T','A','J',' ')}},     /* Tajik -> Tajiki */
+  {"tgj",       {HB_TAG('N','I','S',' ')}},     /* Tagin -> Nisi */
+  {"tgx",       {HB_TAG('A','T','H',' ')}},     /* Tagish -> Athapaskan */
+  {"th",        {HB_TAG('T','H','A',' ')}},     /* Thai */
+  {"tht",       {HB_TAG('A','T','H',' ')}},     /* Tahltan -> Athapaskan */
+  {"thv",       {HB_TAG('T','M','H',' ')}},     /* Tahaggart Tamahaq -> Tamashek */
+  {"thz",       {HB_TAG('T','M','H',' ')}},     /* Tayart Tamajeq -> Tamashek */
+  {"ti",        {HB_TAG('T','G','Y',' ')}},     /* Tigrinya */
+  {"tig",       {HB_TAG('T','G','R',' ')}},     /* Tigre */
+  {"tiv",       {HB_TAG('T','I','V',' ')}},     /* Tiv */
+  {"tk",        {HB_TAG('T','K','M',' ')}},     /* Turkmen */
+  {"tkg",       {HB_TAG('M','L','G',' ')}},     /* Tesaka Malagasy -> Malagasy */
+  {"tl",        {HB_TAG('T','G','L',' ')}},     /* Tagalog */
+  {"tmh",       {HB_TAG('T','M','H',' ')}},     /* Tamashek [macrolanguage] */
+  {"tmw",       {HB_TAG('M','L','Y',' ')}},     /* Temuan -> Malay */
+  {"tn",        {HB_TAG('T','N','A',' ')}},     /* Tswana */
+  {"tnf",       {HB_TAG('D','R','I',' ')}},     /* Tangshewi (retired code) -> Dari */
+  {"to",        {HB_TAG('T','G','N',' ')}},     /* Tonga (Tonga Islands) -> Tongan */
+  {"tod",       {HB_TAG('T','O','D','0')}},     /* Toma */
+  {"toi",       {HB_TAG('T','N','G',' ')}},     /* Tonga (Zambia) */
+  {"tol",       {HB_TAG('A','T','H',' ')}},     /* Tolowa -> Athapaskan */
+  {"tpi",       {HB_TAG('T','P','I',' ')}},     /* Tok Pisin */
+  {"tr",        {HB_TAG('T','R','K',' ')}},     /* Turkish */
+  {"tru",       {HB_TAG('T','U','A',' '),       /* Turoyo -> Turoyo Aramaic */
+                 HB_TAG('S','Y','R',' ')}},     /* Turoyo -> Syriac */
+  {"ts",        {HB_TAG('T','S','G',' ')}},     /* Tsonga */
+  {"tsj",       {HB_TAG('T','S','J',' ')}},     /* Tshangla */
+  {"tt",        {HB_TAG('T','A','T',' ')}},     /* Tatar */
+  {"ttm",       {HB_TAG('A','T','H',' ')}},     /* Northern Tutchone -> Athapaskan */
+  {"ttq",       {HB_TAG('T','M','H',' ')}},     /* Tawallammat Tamajaq -> Tamashek */
+  {"tum",       {HB_TAG('T','U','M',' ')}},     /* Tumbuka -> Tulu */
+  {"tuu",       {HB_TAG('A','T','H',' ')}},     /* Tututni -> Athapaskan */
+  {"tuy",       {HB_TAG('K','A','L',' ')}},     /* Tugen -> Kalenjin */
+  {"tvl",       {HB_TAG('T','V','L',' ')}},     /* Tuvalu */
+  {"tw",        {HB_TAG('T','W','I',' '),       /* Twi */
+                 HB_TAG('A','K','A',' ')}},     /* Twi -> Akan */
+  {"txc",       {HB_TAG('A','T','H',' ')}},     /* Tsetsaut -> Athapaskan */
+  {"txy",       {HB_TAG('M','L','G',' ')}},     /* Tanosy Malagasy -> Malagasy */
+  {"ty",        {HB_TAG('T','H','T',' ')}},     /* Tahitian */
+  {"tyv",       {HB_TAG('T','U','V',' ')}},     /* Tuvinian -> Tuvin */
+  {"tyz",       {HB_TAG('T','Y','Z',' ')}},     /* Tày */
+  {"tzm",       {HB_TAG('T','Z','M',' ')}},     /* Central Atlas Tamazight -> Tamazight */
+  {"tzo",       {HB_TAG('T','Z','O',' ')}},     /* Tzotzil */
+  {"ubl",       {HB_TAG('B','I','K',' ')}},     /* Buhi'non Bikol -> Bikol */
+  {"udm",       {HB_TAG('U','D','M',' ')}},     /* Udmurt */
+  {"ug",        {HB_TAG('U','Y','G',' ')}},     /* Uyghur */
+  {"uk",        {HB_TAG('U','K','R',' ')}},     /* Ukrainian */
+  {"umb",       {HB_TAG('U','M','B',' ')}},     /* Umbundu */
+  {"unr",       {HB_TAG('M','U','N',' ')}},     /* Mundari */
+  {"ur",        {HB_TAG('U','R','D',' ')}},     /* Urdu */
+  {"urk",       {HB_TAG('M','L','Y',' ')}},     /* Urak Lawoi' -> Malay */
+  {"uz",        {HB_TAG('U','Z','B',' ')}},     /* Uzbek [macrolanguage] */
+  {"uzn",       {HB_TAG('U','Z','B',' ')}},     /* Northern Uzbek -> Uzbek */
+  {"uzs",       {HB_TAG('U','Z','B',' ')}},     /* Southern Uzbek -> Uzbek */
+  {"ve",        {HB_TAG('V','E','N',' ')}},     /* Venda */
+  {"vec",       {HB_TAG('V','E','C',' ')}},     /* Venetian */
+  {"vi",        {HB_TAG('V','I','T',' ')}},     /* Vietnamese */
+  {"vkk",       {HB_TAG('M','L','Y',' ')}},     /* Kaur -> Malay */
+  {"vkt",       {HB_TAG('M','L','Y',' ')}},     /* Tenggarong Kutai Malay -> Malay */
+  {"vls",       {HB_TAG('F','L','E',' ')}},     /* Vlaams -> Dutch (Flemish) */
+  {"vmw",       {HB_TAG('M','A','K',' ')}},     /* Makhuwa */
+  {"vo",        {HB_TAG('V','O','L',' ')}},     /* Volapük */
+  {"vro",       {HB_TAG('V','R','O',' ')}},     /* Võro */
+  {"wa",        {HB_TAG('W','L','N',' ')}},     /* Walloon */
+  {"war",       {HB_TAG('W','A','R',' ')}},     /* Waray (Philippines) -> Waray-Waray */
+  {"wbm",       {HB_TAG('W','A',' ',' ')}},     /* Wa */
+  {"wbr",       {HB_TAG('W','A','G',' ')}},     /* Wagdi */
+  {"wlc",       {HB_TAG('C','M','R',' ')}},     /* Mwali Comorian -> Comorian */
+  {"wle",       {HB_TAG('S','I','G',' ')}},     /* Wolane -> Silte Gurage */
+  {"wlk",       {HB_TAG('A','T','H',' ')}},     /* Wailaki -> Athapaskan */
+  {"wni",       {HB_TAG('C','M','R',' ')}},     /* Ndzwani Comorian -> Comorian */
+  {"wo",        {HB_TAG('W','L','F',' ')}},     /* Wolof */
+  {"wry",       {HB_TAG('M','A','W',' ')}},     /* Merwari -> Marwari */
+  {"wsg",       {HB_TAG('G','O','N',' ')}},     /* Adilabad Gondi -> Gondi */
+  {"wtm",       {HB_TAG('W','T','M',' ')}},     /* Mewati */
+  {"wuu",       {HB_TAG('Z','H','S',' ')}},     /* Wu Chinese -> Chinese Simplified */
+  {"xal",       {HB_TAG('K','L','M',' '),       /* Kalmyk */
+                 HB_TAG('T','O','D',' ')}},     /* Kalmyk -> Todo */
+  {"xan",       {HB_TAG('S','E','K',' ')}},     /* Xamtanga -> Sekota */
+  {"xh",        {HB_TAG('X','H','S',' ')}},     /* Xhosa */
+  {"xjb",       {HB_TAG('X','J','B',' ')}},     /* Minjungbal -> Minjangbal */
+  {"xkf",       {HB_TAG('X','K','F',' ')}},     /* Khengkha */
+  {"xmm",       {HB_TAG('M','L','Y',' ')}},     /* Manado Malay -> Malay */
+  {"xmv",       {HB_TAG('M','L','G',' ')}},     /* Antankarana Malagasy -> Malagasy */
+  {"xmw",       {HB_TAG('M','L','G',' ')}},     /* Tsimihety Malagasy -> Malagasy */
+  {"xnr",       {HB_TAG('D','G','R',' ')}},     /* Kangri -> Dogri */
+  {"xog",       {HB_TAG('X','O','G',' ')}},     /* Soga */
+  {"xpe",       {HB_TAG('X','P','E',' ')}},     /* Liberia Kpelle -> Kpelle (Liberia) */
+  {"xsl",       {HB_TAG('S','S','L',' '),       /* South Slavey */
+                 HB_TAG('S','L','A',' '),       /* South Slavey -> Slavey */
+                 HB_TAG('A','T','H',' ')}},     /* South Slavey -> Athapaskan */
+  {"xst",       {HB_TAG('S','I','G',' ')}},     /* Silt'e (retired code) -> Silte Gurage */
+  {"xwo",       {HB_TAG('T','O','D',' ')}},     /* Written Oirat -> Todo */
+  {"yao",       {HB_TAG('Y','A','O',' ')}},     /* Yao */
+  {"yap",       {HB_TAG('Y','A','P',' ')}},     /* Yapese */
+  {"ybd",       {HB_TAG('A','R','K',' ')}},     /* Yangbye (retired code) -> Rakhine */
+  {"ydd",       {HB_TAG('J','I','I',' ')}},     /* Eastern Yiddish -> Yiddish */
+  {"yi",        {HB_TAG('J','I','I',' ')}},     /* Yiddish [macrolanguage] */
+  {"yih",       {HB_TAG('J','I','I',' ')}},     /* Western Yiddish -> Yiddish */
+  {"yo",        {HB_TAG('Y','B','A',' ')}},     /* Yoruba */
+  {"yos",       {HB_TAG('Q','I','N',' ')}},     /* Yos (retired code) -> Chin */
+  {"yrk",       {HB_TAG('T','N','E',' '),       /* Nenets -> Tundra Nenets */
+                 HB_TAG('F','N','E',' ')}},     /* Nenets -> Forest Nenets */
+  {"yue",       {HB_TAG('Z','H','H',' ')}},     /* Yue Chinese -> Chinese, Hong Kong SAR */
+  {"za",        {HB_TAG('Z','H','A',' ')}},     /* Zhuang [macrolanguage] */
+  {"zch",       {HB_TAG('Z','H','A',' ')}},     /* Central Hongshuihe Zhuang -> Zhuang */
+  {"zdj",       {HB_TAG('C','M','R',' ')}},     /* Ngazidja Comorian -> Comorian */
+  {"zea",       {HB_TAG('Z','E','A',' ')}},     /* Zeeuws -> Zealandic */
+  {"zeh",       {HB_TAG('Z','H','A',' ')}},     /* Eastern Hongshuihe Zhuang -> Zhuang */
+  {"zgb",       {HB_TAG('Z','H','A',' ')}},     /* Guibei Zhuang -> Zhuang */
+  {"zgh",       {HB_TAG('Z','G','H',' ')}},     /* Standard Moroccan Tamazight */
+  {"zgm",       {HB_TAG('Z','H','A',' ')}},     /* Minz Zhuang -> Zhuang */
+  {"zgn",       {HB_TAG('Z','H','A',' ')}},     /* Guibian Zhuang -> Zhuang */
+  {"zh",        {HB_TAG('Z','H','S',' ')}},     /* Chinese [macrolanguage] -> Chinese Simplified */
+  {"zhd",       {HB_TAG('Z','H','A',' ')}},     /* Dai Zhuang -> Zhuang */
+  {"zhn",       {HB_TAG('Z','H','A',' ')}},     /* Nong Zhuang -> Zhuang */
+  {"zlj",       {HB_TAG('Z','H','A',' ')}},     /* Liujiang Zhuang -> Zhuang */
+  {"zlm",       {HB_TAG('M','L','Y',' ')}},     /* Malay */
+  {"zln",       {HB_TAG('Z','H','A',' ')}},     /* Lianshan Zhuang -> Zhuang */
+  {"zlq",       {HB_TAG('Z','H','A',' ')}},     /* Liuqian Zhuang -> Zhuang */
+  {"zmi",       {HB_TAG('M','L','Y',' ')}},     /* Negeri Sembilan Malay -> Malay */
+  {"zne",       {HB_TAG('Z','N','D',' ')}},     /* Zande */
+  {"zom",       {HB_TAG('Q','I','N',' ')}},     /* Zou -> Chin */
+  {"zqe",       {HB_TAG('Z','H','A',' ')}},     /* Qiubei Zhuang -> Zhuang */
+  {"zsm",       {HB_TAG('M','L','Y',' ')}},     /* Standard Malay -> Malay */
+  {"zu",        {HB_TAG('Z','U','L',' ')}},     /* Zulu */
+  {"zum",       {HB_TAG('L','R','C',' ')}},     /* Kumzari -> Luri */
+  {"zyb",       {HB_TAG('Z','H','A',' ')}},     /* Yongbei Zhuang -> Zhuang */
+  {"zyg",       {HB_TAG('Z','H','A',' ')}},     /* Yang Zhuang -> Zhuang */
+  {"zyj",       {HB_TAG('Z','H','A',' ')}},     /* Youjiang Zhuang -> Zhuang */
+  {"zyn",       {HB_TAG('Z','H','A',' ')}},     /* Yongnan Zhuang -> Zhuang */
+  {"zza",       {HB_TAG('Z','Z','A',' ')}},     /* Zazaki [macrolanguage] */
+  {"zzj",       {HB_TAG('Z','H','A',' ')}},     /* Zuojiang Zhuang -> Zhuang */
+};
+
+static_assert (HB_OT_MAX_TAGS_PER_LANGUAGE == 3u, "");
+
+/**
+ * hb_ot_tags_from_complex_language:
+ * @lang_str: a BCP 47 language tag to convert.
+ * @limit: a pointer to the end of the substring of @lang_str to consider for
+ * conversion.
+ * @count: maximum number of language tags to retrieve (IN) and actual number of
+ * language tags retrieved (OUT). If no tags are retrieved, it is not modified.
+ * @tags: array of size at least @language_count to store the language tag
+ * results
+ *
+ * Converts a multi-subtag BCP 47 language tag to language tags.
+ *
+ * Return value: Whether any language systems were retrieved.
+ **/
+static bool
+hb_ot_tags_from_complex_language (const char   *lang_str,
+                                  const char   *limit,
+                                  unsigned int *count /* IN/OUT */,
+                                  hb_tag_t     *tags /* OUT */)
+{
+  if (subtag_matches (lang_str, limit, "-fonnapa"))
+  {
+    /* Undetermined; North American Phonetic Alphabet */
+    tags[0] = HB_TAG('A','P','P','H');  /* Phonetic transcription—Americanist conventions */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-polyton"))
+  {
+    /* Modern Greek (1453-); Polytonic Greek */
+    tags[0] = HB_TAG('P','G','R',' ');  /* Polytonic Greek */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-provenc"))
+  {
+    /* Occitan (post 1500); Provençal */
+    tags[0] = HB_TAG('P','R','O',' ');  /* Provençal / Old Provençal */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-fonipa"))
+  {
+    /* Undetermined; International Phonetic Alphabet */
+    tags[0] = HB_TAG('I','P','P','H');  /* Phonetic transcription—IPA conventions */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-geok"))
+  {
+    /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
+    tags[0] = HB_TAG('K','G','E',' ');  /* Khutsuri Georgian */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-syre"))
+  {
+    /* Undetermined; Syriac (Estrangelo variant) */
+    tags[0] = HB_TAG('S','Y','R','E');  /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-syrj"))
+  {
+    /* Undetermined; Syriac (Western variant) */
+    tags[0] = HB_TAG('S','Y','R','J');  /* Syriac, Western script-variant (equivalent to ISO 15924 'Syrj') */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-syrn"))
+  {
+    /* Undetermined; Syriac (Eastern variant) */
+    tags[0] = HB_TAG('S','Y','R','N');  /* Syriac, Eastern script-variant (equivalent to ISO 15924 'Syrn') */
+    *count = 1;
+    return true;
+  }
+  switch (lang_str[0])
+  {
+  case 'a':
+    if (0 == strcmp (&lang_str[1], "rt-lojban"))
+    {
+      /* Lojban */
+      tags[0] = HB_TAG('J','B','O',' ');  /* Lojban */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'c':
+    if (lang_matches (&lang_str[1], "do-hant-hk"))
+    {
+      /* Min Dong Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "do-hant-mo"))
+    {
+      /* Min Dong Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "jy-hant-hk"))
+    {
+      /* Jinyu Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "jy-hant-mo"))
+    {
+      /* Jinyu Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "mn-hant-hk"))
+    {
+      /* Mandarin Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "mn-hant-mo"))
+    {
+      /* Mandarin Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "px-hant-hk"))
+    {
+      /* Pu-Xian Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "px-hant-mo"))
+    {
+      /* Pu-Xian Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zh-hant-hk"))
+    {
+      /* Huizhou Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zh-hant-mo"))
+    {
+      /* Huizhou Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zo-hant-hk"))
+    {
+      /* Min Zhong Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zo-hant-mo"))
+    {
+      /* Min Zhong Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "do-hans"))
+    {
+      /* Min Dong Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "do-hant"))
+    {
+      /* Min Dong Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "jy-hans"))
+    {
+      /* Jinyu Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "jy-hant"))
+    {
+      /* Jinyu Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "mn-hans"))
+    {
+      /* Mandarin Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "mn-hant"))
+    {
+      /* Mandarin Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "px-hans"))
+    {
+      /* Pu-Xian Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "px-hant"))
+    {
+      /* Pu-Xian Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zh-hans"))
+    {
+      /* Huizhou Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zh-hant"))
+    {
+      /* Huizhou Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zo-hans"))
+    {
+      /* Min Zhong Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zo-hant"))
+    {
+      /* Min Zhong Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "do-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Min Dong Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "do-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Min Dong Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "do-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Min Dong Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "jy-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Jinyu Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "jy-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Jinyu Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "jy-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Jinyu Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "mn-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Mandarin Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "mn-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Mandarin Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "mn-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Mandarin Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "px-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Pu-Xian Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "px-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Pu-Xian Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "px-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Pu-Xian Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zh-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Huizhou Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zh-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Huizhou Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zh-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Huizhou Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zo-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Min Zhong Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zo-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Min Zhong Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zo-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Min Zhong Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'g':
+    if (lang_matches (&lang_str[1], "an-hant-hk"))
+    {
+      /* Gan Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hant-mo"))
+    {
+      /* Gan Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hans"))
+    {
+      /* Gan Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hant"))
+    {
+      /* Gan Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "a-latg"))
+    {
+      /* Irish */
+      tags[0] = HB_TAG('I','R','T',' ');  /* Irish Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Gan Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Gan Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Gan Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'h':
+    if (lang_matches (&lang_str[1], "ak-hant-hk"))
+    {
+      /* Hakka Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "ak-hant-mo"))
+    {
+      /* Hakka Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "sn-hant-hk"))
+    {
+      /* Xiang Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "sn-hant-mo"))
+    {
+      /* Xiang Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "ak-hans"))
+    {
+      /* Hakka Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "ak-hant"))
+    {
+      /* Hakka Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "sn-hans"))
+    {
+      /* Xiang Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "sn-hant"))
+    {
+      /* Xiang Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "ak-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Hakka Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "ak-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Hakka Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "ak-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Hakka Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "sn-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Xiang Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "sn-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Xiang Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "sn-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Xiang Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'i':
+    if (0 == strcmp (&lang_str[1], "-navajo"))
+    {
+      /* Navajo */
+      unsigned int i;
+      hb_tag_t possible_tags[] = {
+        HB_TAG('N','A','V',' '),  /* Navajo */
+        HB_TAG('A','T','H',' '),  /* Athapaskan */
+      };
+      for (i = 0; i < 2 && i < *count; i++)
+        tags[i] = possible_tags[i];
+      *count = i;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "-hak"))
+    {
+      /* Hakka */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "-lux"))
+    {
+      /* Luxembourgish */
+      tags[0] = HB_TAG('L','T','Z',' ');  /* Luxembourgish */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'l':
+    if (lang_matches (&lang_str[1], "zh-hans"))
+    {
+      /* Literary Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'm':
+    if (lang_matches (&lang_str[1], "np-hant-hk"))
+    {
+      /* Min Bei Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "np-hant-mo"))
+    {
+      /* Min Bei Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "np-hans"))
+    {
+      /* Min Bei Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "np-hant"))
+    {
+      /* Min Bei Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "np-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Min Bei Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "np-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Min Bei Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "np-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Min Bei Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'n':
+    if (lang_matches (&lang_str[1], "an-hant-hk"))
+    {
+      /* Min Nan Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hant-mo"))
+    {
+      /* Min Nan Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hans"))
+    {
+      /* Min Nan Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hant"))
+    {
+      /* Min Nan Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Min Nan Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Min Nan Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Min Nan Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "o-bok"))
+    {
+      /* Norwegian Bokmal */
+      tags[0] = HB_TAG('N','O','R',' ');  /* Norwegian */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "o-nyn"))
+    {
+      /* Norwegian Nynorsk */
+      tags[0] = HB_TAG('N','Y','N',' ');  /* Norwegian Nynorsk (Nynorsk, Norwegian) */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'r':
+    if (0 == strncmp (&lang_str[1], "o-", 2)
+        && subtag_matches (lang_str, limit, "-md"))
+    {
+      /* Romanian; Moldova */
+      tags[0] = HB_TAG('M','O','L',' ');  /* Moldavian */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'w':
+    if (lang_matches (&lang_str[1], "uu-hant-hk"))
+    {
+      /* Wu Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "uu-hant-mo"))
+    {
+      /* Wu Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "uu-hans"))
+    {
+      /* Wu Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "uu-hant"))
+    {
+      /* Wu Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "uu-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Wu Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "uu-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Wu Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "uu-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Wu Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'y':
+    if (lang_matches (&lang_str[1], "ue-hans"))
+    {
+      /* Yue Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'z':
+    if (lang_matches (&lang_str[1], "h-hant-hk"))
+    {
+      /* Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "h-hant-mo"))
+    {
+      /* Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "h-min-nan"))
+    {
+      /* Minnan, Hokkien, Amoy, Taiwanese, Southern Min, Southern Fujian, Hoklo, Southern Fukien, Ho-lo */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "h-hans"))
+    {
+      /* Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "h-hant"))
+    {
+      /* Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "h-min"))
+    {
+      /* Min, Fuzhou, Hokkien, Amoy, or Taiwanese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "h-", 2)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "h-", 2)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "h-", 2)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  }
+  return false;
+}
+
+/**
+ * hb_ot_ambiguous_tag_to_language
+ * @tag: A language tag.
+ *
+ * Converts @tag to a BCP 47 language tag if it is ambiguous (it corresponds to
+ * many language tags) and the best tag is not the alphabetically first, or if
+ * the best tag consists of multiple subtags.
+ *
+ * Return value: The #hb_language_t corresponding to the BCP 47 language tag,
+ * or #HB_LANGUAGE_INVALID if @tag is not ambiguous.
+ **/
+static hb_language_t
+hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
+{
+  switch (tag)
+  {
+  case HB_TAG('A','P','P','H'):  /* Phonetic transcription—Americanist conventions */
+    return hb_language_from_string ("und-fonnapa", -1);  /* Undetermined; North American Phonetic Alphabet */
+  case HB_TAG('A','R','A',' '):  /* Arabic */
+    return hb_language_from_string ("ar", -1);  /* Arabic */
+  case HB_TAG('A','R','K',' '):  /* Rakhine */
+    return hb_language_from_string ("rki", -1);  /* Rakhine */
+  case HB_TAG('A','T','H',' '):  /* Athapaskan */
+    return hb_language_from_string ("ath", -1);  /* Athapascan */
+  case HB_TAG('B','I','K',' '):  /* Bikol */
+    return hb_language_from_string ("bik", -1);  /* Bikol */
+  case HB_TAG('C','P','P',' '):  /* Creoles */
+    return hb_language_from_string ("crp", -1);  /* Creoles and pidgins */
+  case HB_TAG('C','R','R',' '):  /* Carrier */
+    return hb_language_from_string ("crx", -1);  /* Carrier */
+  case HB_TAG('D','N','K',' '):  /* Dinka */
+    return hb_language_from_string ("din", -1);  /* Dinka */
+  case HB_TAG('D','R','I',' '):  /* Dari */
+    return hb_language_from_string ("prs", -1);  /* Dari */
+  case HB_TAG('D','U','J',' '):  /* Dhuwal */
+    return hb_language_from_string ("dwu", -1);  /* Dhuwal */
+  case HB_TAG('D','Z','N',' '):  /* Dzongkha */
+    return hb_language_from_string ("dz", -1);  /* Dzongkha */
+  case HB_TAG('E','T','I',' '):  /* Estonian */
+    return hb_language_from_string ("et", -1);  /* Estonian */
+  case HB_TAG('G','O','N',' '):  /* Gondi */
+    return hb_language_from_string ("gon", -1);  /* Gondi */
+  case HB_TAG('H','M','N',' '):  /* Hmong */
+    return hb_language_from_string ("hmn", -1);  /* Hmong */
+  case HB_TAG('I','J','O',' '):  /* Ijo */
+    return hb_language_from_string ("ijo", -1);  /* Ijo */
+  case HB_TAG('I','N','U',' '):  /* Inuktitut */
+    return hb_language_from_string ("iu", -1);  /* Inuktitut */
+  case HB_TAG('I','P','K',' '):  /* Inupiat */
+    return hb_language_from_string ("ik", -1);  /* Inupiaq */
+  case HB_TAG('I','P','P','H'):  /* Phonetic transcription—IPA conventions */
+    return hb_language_from_string ("und-fonipa", -1);  /* Undetermined; International Phonetic Alphabet */
+  case HB_TAG('I','R','T',' '):  /* Irish Traditional */
+    return hb_language_from_string ("ga-Latg", -1);  /* Irish; Latin (Gaelic variant) */
+  case HB_TAG('J','I','I',' '):  /* Yiddish */
+    return hb_language_from_string ("yi", -1);  /* Yiddish */
+  case HB_TAG('K','A','L',' '):  /* Kalenjin */
+    return hb_language_from_string ("kln", -1);  /* Kalenjin */
+  case HB_TAG('K','G','E',' '):  /* Khutsuri Georgian */
+    return hb_language_from_string ("und-Geok", -1);  /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
+  case HB_TAG('K','N','R',' '):  /* Kanuri */
+    return hb_language_from_string ("kr", -1);  /* Kanuri */
+  case HB_TAG('K','O','K',' '):  /* Konkani */
+    return hb_language_from_string ("kok", -1);  /* Konkani */
+  case HB_TAG('K','U','R',' '):  /* Kurdish */
+    return hb_language_from_string ("ku", -1);  /* Kurdish */
+  case HB_TAG('L','U','H',' '):  /* Luyia */
+    return hb_language_from_string ("luy", -1);  /* Luyia */
+  case HB_TAG('L','V','I',' '):  /* Latvian */
+    return hb_language_from_string ("lv", -1);  /* Latvian */
+  case HB_TAG('M','A','W',' '):  /* Marwari */
+    return hb_language_from_string ("mwr", -1);  /* Marwari */
+  case HB_TAG('M','L','G',' '):  /* Malagasy */
+    return hb_language_from_string ("mg", -1);  /* Malagasy */
+  case HB_TAG('M','L','Y',' '):  /* Malay */
+    return hb_language_from_string ("ms", -1);  /* Malay */
+  case HB_TAG('M','N','G',' '):  /* Mongolian */
+    return hb_language_from_string ("mn", -1);  /* Mongolian */
+  case HB_TAG('M','O','L',' '):  /* Moldavian */
+    return hb_language_from_string ("ro-MD", -1);  /* Romanian; Moldova */
+  case HB_TAG('N','E','P',' '):  /* Nepali */
+    return hb_language_from_string ("ne", -1);  /* Nepali */
+  case HB_TAG('N','I','S',' '):  /* Nisi */
+    return hb_language_from_string ("njz", -1);  /* Nyishi */
+  case HB_TAG('N','O','R',' '):  /* Norwegian */
+    return hb_language_from_string ("no", -1);  /* Norwegian */
+  case HB_TAG('O','J','B',' '):  /* Ojibway */
+    return hb_language_from_string ("oj", -1);  /* Ojibwa */
+  case HB_TAG('O','R','O',' '):  /* Oromo */
+    return hb_language_from_string ("om", -1);  /* Oromo */
+  case HB_TAG('P','A','S',' '):  /* Pashto */
+    return hb_language_from_string ("ps", -1);  /* Pashto */
+  case HB_TAG('P','G','R',' '):  /* Polytonic Greek */
+    return hb_language_from_string ("el-polyton", -1);  /* Modern Greek (1453-); Polytonic Greek */
+  case HB_TAG('P','R','O',' '):  /* Provençal / Old Provençal */
+    return hb_language_from_string ("pro", -1);  /* Old Provençal (to 1500) */
+  case HB_TAG('Q','U','H',' '):  /* Quechua (Bolivia) */
+    return hb_language_from_string ("quh", -1);  /* South Bolivian Quechua */
+  case HB_TAG('Q','V','I',' '):  /* Quechua (Ecuador) */
+    return hb_language_from_string ("qvi", -1);  /* Imbabura Highland Quichua */
+  case HB_TAG('Q','W','H',' '):  /* Quechua (Peru) */
+    return hb_language_from_string ("qwh", -1);  /* Huaylas Ancash Quechua */
+  case HB_TAG('R','A','J',' '):  /* Rajasthani */
+    return hb_language_from_string ("raj", -1);  /* Rajasthani */
+  case HB_TAG('R','O','Y',' '):  /* Romany */
+    return hb_language_from_string ("rom", -1);  /* Romany */
+  case HB_TAG('S','Q','I',' '):  /* Albanian */
+    return hb_language_from_string ("sq", -1);  /* Albanian */
+  case HB_TAG('S','Y','R',' '):  /* Syriac */
+    return hb_language_from_string ("syr", -1);  /* Syriac */
+  case HB_TAG('S','Y','R','E'):  /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */
+    return hb_language_from_string ("und-Syre", -1);  /* Undetermined; Syriac (Estrangelo variant) */
+  case HB_TAG('S','Y','R','J'):  /* Syriac, Western script-variant (equivalent to ISO 15924 'Syrj') */
+    return hb_language_from_string ("und-Syrj", -1);  /* Undetermined; Syriac (Western variant) */
+  case HB_TAG('S','Y','R','N'):  /* Syriac, Eastern script-variant (equivalent to ISO 15924 'Syrn') */
+    return hb_language_from_string ("und-Syrn", -1);  /* Undetermined; Syriac (Eastern variant) */
+  case HB_TAG('T','M','H',' '):  /* Tamashek */
+    return hb_language_from_string ("tmh", -1);  /* Tamashek */
+  case HB_TAG('T','N','E',' '):  /* Tundra Nenets */
+    return hb_language_from_string ("yrk", -1);  /* Nenets */
+  case HB_TAG('Z','H','H',' '):  /* Chinese, Hong Kong SAR */
+    return hb_language_from_string ("zh-HK", -1);  /* Chinese; Hong Kong */
+  case HB_TAG('Z','H','S',' '):  /* Chinese Simplified */
+    return hb_language_from_string ("zh-Hans", -1);  /* Chinese; Han (Simplified variant) */
+  case HB_TAG('Z','H','T',' '):  /* Chinese Traditional */
+    return hb_language_from_string ("zh-Hant", -1);  /* Chinese; Han (Traditional variant) */
+  default:
+    return HB_LANGUAGE_INVALID;
+  }
+}
+
+#endif /* HB_OT_TAG_TABLE_HH */
+
+/* == End of generated table == */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-tag.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-tag.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -26,7 +26,7 @@
  * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 /* hb_script_t */
@@ -36,7 +36,8 @@
 {
   /* This seems to be accurate as of end of 2012. */
 
-  switch ((hb_tag_t) script) {
+  switch ((hb_tag_t) script)
+  {
     case HB_SCRIPT_INVALID:             return HB_OT_TAG_DEFAULT_SCRIPT;
 
     /* KATAKANA and HIRAGANA both map to 'kana' */
@@ -49,8 +50,6 @@
     case HB_SCRIPT_NKO:                 return HB_TAG('n','k','o',' ');
     /* Unicode-5.1 additions */
     case HB_SCRIPT_VAI:                 return HB_TAG('v','a','i',' ');
-    /* Unicode-5.2 additions */
-    /* Unicode-6.0 additions */
   }
 
   /* Else, just change first char to lowercase and return */
@@ -114,6 +113,18 @@
   return HB_SCRIPT_UNKNOWN;
 }
 
+void
+hb_ot_tags_from_script (hb_script_t  script,
+                        hb_tag_t    *script_tag_1,
+                        hb_tag_t    *script_tag_2)
+{
+  unsigned int count = 2;
+  hb_tag_t tags[2];
+  hb_ot_tags_from_script_and_language (script, HB_LANGUAGE_INVALID, &count, tags, nullptr, nullptr);
+  *script_tag_1 = count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_SCRIPT;
+  *script_tag_2 = count > 1 ? tags[1] : HB_OT_TAG_DEFAULT_SCRIPT;
+}
+
 /*
  * Complete list at:
  * https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags
@@ -122,28 +133,37 @@
  * So we just do that, and handle the exceptional cases in a switch.
  */
 
-void
-hb_ot_tags_from_script (hb_script_t  script,
-                        hb_tag_t    *script_tag_1,
-                        hb_tag_t    *script_tag_2)
+static void
+hb_ot_all_tags_from_script (hb_script_t   script,
+                            unsigned int *count /* IN/OUT */,
+                            hb_tag_t     *tags /* OUT */)
 {
-  hb_tag_t new_tag;
+  unsigned int i = 0;
 
-  *script_tag_2 = HB_OT_TAG_DEFAULT_SCRIPT;
-  *script_tag_1 = hb_ot_old_tag_from_script (script);
+  hb_tag_t new_tag = hb_ot_new_tag_from_script (script);
+  if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT))
+  {
+    tags[i++] = new_tag | '3';
+    if (*count > i)
+      tags[i++] = new_tag;
+  }
 
-  new_tag = hb_ot_new_tag_from_script (script);
-  if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT)) {
-    *script_tag_2 = *script_tag_1;
-    *script_tag_1 = new_tag;
+  if (*count > i)
+  {
+    hb_tag_t old_tag = hb_ot_old_tag_from_script (script);
+    if (old_tag != HB_OT_TAG_DEFAULT_SCRIPT)
+      tags[i++] = old_tag;
   }
+
+  *count = i;
 }
 
 hb_script_t
 hb_ot_tag_to_script (hb_tag_t tag)
 {
-  if (unlikely ((tag & 0x000000FFu) == '2'))
-    return hb_ot_new_tag_to_script (tag);
+  unsigned char digit = tag & 0x000000FFu;
+  if (unlikely (digit == '2' || digit == '3'))
+    return hb_ot_new_tag_to_script (tag & 0xFFFFFF32);
 
   return hb_ot_old_tag_to_script (tag);
 }
@@ -151,732 +171,6 @@
 
 /* hb_language_t */
 
-typedef struct {
-  char language[4];
-  hb_tag_t tag;
-} LangTag;
-
-/*
- * Complete list at:
- * https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags
- *
- * Generated by intersecting the OpenType language tag list from
- * Draft OpenType 1.5 spec, with with the ISO 639-3 codes from
- * 2008-08-04, matching on name, and finally adjusted manually.
- *
- * Updated on 2012-12-07 with more research into remaining codes.
- *
- * Updated on 2013-11-23 based on usage in SIL and Microsoft fonts,
- * the new proposal from Microsoft, and latest ISO 639-3 names.
- *
- * Some items still missing.  Those are commented out at the end.
- * Keep sorted for bsearch.
- *
- * Updated as of 2015-05-06: OT1.7 on MS website has some newer
- * items that we don't have here, eg. Zazaki.  This is the new
- * items in OpenType 1.7 (red items), most of which we have:
- * https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags
- */
-
-static const LangTag ot_languages[] = {
-  {"aa",        HB_TAG('A','F','R',' ')},       /* Afar */
-  {"ab",        HB_TAG('A','B','K',' ')},       /* Abkhazian */
-  {"abq",       HB_TAG('A','B','A',' ')},       /* Abaza */
-  {"acf",       HB_TAG('F','A','N',' ')},       /* French Antillean */
-  {"ach",       HB_TAG('A','C','H',' ')},       /* Acoli */
-  {"acr",       HB_TAG('A','C','R',' ')},       /* Achi */
-  {"ada",       HB_TAG('D','N','G',' ')},       /* Dangme */
-  {"ady",       HB_TAG('A','D','Y',' ')},       /* Adyghe */
-  {"af",        HB_TAG('A','F','K',' ')},       /* Afrikaans */
-  {"ahg",       HB_TAG('A','G','W',' ')},       /* Agaw */
-  {"aii",       HB_TAG('S','W','A',' ')},       /* Swadaya Aramaic */
-  {"aio",       HB_TAG('A','I','O',' ')},       /* Aiton */
-  {"aiw",       HB_TAG('A','R','I',' ')},       /* Aari */
-  {"ak",        HB_TAG('T','W','I',' ')},       /* Akan [macrolanguage] */
-  {"aka",       HB_TAG('A','K','A',' ')},       /* Akan */
-  {"alt",       HB_TAG('A','L','T',' ')},       /* [Southern] Altai */
-  {"am",        HB_TAG('A','M','H',' ')},       /* Amharic */
-  {"amf",       HB_TAG('H','B','N',' ')},       /* Hammer-Banna */
-  {"amw",       HB_TAG('S','Y','R',' ')},       /* Western Neo-Aramaic */
-  {"an",        HB_TAG('A','R','G',' ')},       /* Aragonese */
-  {"ang",       HB_TAG('A','N','G',' ')},       /* Old English (ca. 450-1100) */
-  {"ar",        HB_TAG('A','R','A',' ')},       /* Arabic [macrolanguage] */
-  {"arb",       HB_TAG('A','R','A',' ')},       /* Standard Arabic */
-  {"arn",       HB_TAG('M','A','P',' ')},       /* Mapudungun */
-  {"ary",       HB_TAG('M','O','R',' ')},       /* Moroccan Arabic */
-  {"as",        HB_TAG('A','S','M',' ')},       /* Assamese */
-  {"ast",       HB_TAG('A','S','T',' ')},       /* Asturian/Asturleonese/Bable/Leonese */
-  {"ath",       HB_TAG('A','T','H',' ')},       /* Athapaskan [family] */
-  {"atj",       HB_TAG('R','C','R',' ')},       /* R-Cree */
-  {"atv",       HB_TAG('A','L','T',' ')},       /* [Northern] Altai */
-  {"av",        HB_TAG('A','V','R',' ')},       /* Avaric */
-  {"awa",       HB_TAG('A','W','A',' ')},       /* Awadhi */
-  {"ay",        HB_TAG('A','Y','M',' ')},       /* Aymara [macrolanguage] */
-  {"az",        HB_TAG('A','Z','E',' ')},       /* Azerbaijani [macrolanguage] */
-  {"azb",       HB_TAG('A','Z','B',' ')},       /* South Azerbaijani */
-  {"azj",       HB_TAG('A','Z','E',' ')},       /* North Azerbaijani */
-  {"ba",        HB_TAG('B','S','H',' ')},       /* Bashkir */
-  {"bad",       HB_TAG('B','A','D','0')},       /* Banda */
-  {"bai",       HB_TAG('B','M','L',' ')},       /* Bamileke [family] */
-  {"bal",       HB_TAG('B','L','I',' ')},       /* Baluchi [macrolangauge] */
-  {"ban",       HB_TAG('B','A','N',' ')},       /* Balinese */
-  {"bar",       HB_TAG('B','A','R',' ')},       /* Bavarian */
-  {"bbc",       HB_TAG('B','B','C',' ')},       /* Batak Toba */
-  {"bci",       HB_TAG('B','A','U',' ')},       /* Baoulé */
-  {"bcl",       HB_TAG('B','I','K',' ')},       /* Central Bikol */
-  {"bcq",       HB_TAG('B','C','H',' ')},       /* Bench */
-  {"bdy",       HB_TAG('B','D','Y',' ')},       /* Bandjalang */
-  {"be",        HB_TAG('B','E','L',' ')},       /* Belarusian */
-  {"bem",       HB_TAG('B','E','M',' ')},       /* Bemba (Zambia) */
-  {"ber",       HB_TAG('B','E','R',' ')},       /* Berber [family] */
-  {"bfq",       HB_TAG('B','A','D',' ')},       /* Badaga */
-  {"bft",       HB_TAG('B','L','T',' ')},       /* Balti */
-  {"bfu",       HB_TAG('L','A','H',' ')},       /* Lahuli */
-  {"bfy",       HB_TAG('B','A','G',' ')},       /* Baghelkhandi */
-  {"bg",        HB_TAG('B','G','R',' ')},       /* Bulgarian */
-  {"bgc",       HB_TAG('B','G','C',' ')},       /* Haryanvi */
-  {"bgq",       HB_TAG('B','G','Q',' ')},       /* Bagri */
-  {"bgr",       HB_TAG('Q','I','N',' ')},       /* Bawm Chin */
-  {"bhb",       HB_TAG('B','H','I',' ')},       /* Bhili */
-  {"bhk",       HB_TAG('B','I','K',' ')},       /* Albay Bicolano (retired code) */
-  {"bho",       HB_TAG('B','H','O',' ')},       /* Bhojpuri */
-  {"bi",        HB_TAG('B','I','S',' ')},       /* Bislama */
-  {"bik",       HB_TAG('B','I','K',' ')},       /* Bikol [macrolanguage] */
-  {"bin",       HB_TAG('E','D','O',' ')},       /* Bini */
-  {"bjj",       HB_TAG('B','J','J',' ')},       /* Kanauji */
-  {"bjt",       HB_TAG('B','L','N',' ')},       /* Balanta-Ganja */
-  {"bla",       HB_TAG('B','K','F',' ')},       /* Blackfoot */
-  {"ble",       HB_TAG('B','L','N',' ')},       /* Balanta-Kentohe */
-  {"blk",       HB_TAG('B','L','K',' ')},       /* Pa'O/Pa'o Karen */
-  {"bln",       HB_TAG('B','I','K',' ')},       /* Southern Catanduanes Bikol */
-  {"bm",        HB_TAG('B','M','B',' ')},       /* Bambara */
-  {"bn",        HB_TAG('B','E','N',' ')},       /* Bengali */
-  {"bo",        HB_TAG('T','I','B',' ')},       /* Tibetan */
-  {"bpy",       HB_TAG('B','P','Y',' ')},       /* Bishnupriya */
-  {"bqi",       HB_TAG('L','R','C',' ')},       /* Bakhtiari */
-  {"br",        HB_TAG('B','R','E',' ')},       /* Breton */
-  {"bra",       HB_TAG('B','R','I',' ')},       /* Braj Bhasha */
-  {"brh",       HB_TAG('B','R','H',' ')},       /* Brahui */
-  {"brx",       HB_TAG('B','R','X',' ')},       /* Bodo (India) */
-  {"bs",        HB_TAG('B','O','S',' ')},       /* Bosnian */
-  {"btb",       HB_TAG('B','T','I',' ')},       /* Beti (Cameroon) */
-  {"bto",       HB_TAG('B','I','K',' ')},       /* Rinconada Bikol */
-  {"bts",       HB_TAG('B','T','S',' ')},       /* Batak Simalungun */
-  {"bug",       HB_TAG('B','U','G',' ')},       /* Buginese */
-  {"bxr",       HB_TAG('R','B','U',' ')},       /* Russian Buriat */
-  {"byn",       HB_TAG('B','I','L',' ')},       /* Bilen */
-  {"ca",        HB_TAG('C','A','T',' ')},       /* Catalan */
-  {"cak",       HB_TAG('C','A','K',' ')},       /* Kaqchikel */
-  {"cbk",       HB_TAG('C','B','K',' ')},       /* Chavacano */
-  {"cbl",       HB_TAG('Q','I','N',' ')},       /* Bualkhaw Chin */
-  {"cco",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"ce",        HB_TAG('C','H','E',' ')},       /* Chechen */
-  {"ceb",       HB_TAG('C','E','B',' ')},       /* Cebuano */
-  {"cfm",       HB_TAG('H','A','L',' ')},       /* Halam/Falam Chin */
-  {"cgg",       HB_TAG('C','G','G',' ')},       /* Chiga */
-  {"ch",        HB_TAG('C','H','A',' ')},       /* Chamorro */
-  {"chj",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"chk",       HB_TAG('C','H','K','0')},       /* Chuukese */
-  {"cho",       HB_TAG('C','H','O',' ')},       /* Choctaw */
-  {"chp",       HB_TAG('C','H','P',' ')},       /* Chipewyan */
-  {"chq",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"chr",       HB_TAG('C','H','R',' ')},       /* Cherokee */
-  {"chy",       HB_TAG('C','H','Y',' ')},       /* Cheyenne */
-  {"chz",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cja",       HB_TAG('C','J','A',' ')},       /* Western Cham */
-  {"cjm",       HB_TAG('C','J','M',' ')},       /* Eastern Cham */
-  {"cka",       HB_TAG('Q','I','N',' ')},       /* Khumi Awa Chin */
-  {"ckb",       HB_TAG('K','U','R',' ')},       /* Central Kurdish (Sorani) */
-  {"ckt",       HB_TAG('C','H','K',' ')},       /* Chukchi */
-  {"cld",       HB_TAG('S','Y','R',' ')},       /* Chaldean Neo-Aramaic */
-  {"cle",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cmr",       HB_TAG('Q','I','N',' ')},       /* Mro-Khimi Chin */
-  {"cnb",       HB_TAG('Q','I','N',' ')},       /* Chinbon Chin */
-  {"cnh",       HB_TAG('Q','I','N',' ')},       /* Hakha Chin */
-  {"cnk",       HB_TAG('Q','I','N',' ')},       /* Khumi Chin */
-  {"cnl",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cnt",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cnw",       HB_TAG('Q','I','N',' ')},       /* Ngawn Chin */
-  {"cop",       HB_TAG('C','O','P',' ')},       /* Coptic */
-  {"cpa",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cpp",       HB_TAG('C','P','P',' ')},       /* Creoles */
-  {"cr",        HB_TAG('C','R','E',' ')},       /* Cree */
-  {"cre",       HB_TAG('Y','C','R',' ')},       /* Y-Cree */
-  {"crh",       HB_TAG('C','R','T',' ')},       /* Crimean Tatar */
-  {"crj",       HB_TAG('E','C','R',' ')},       /* [Southern] East Cree */
-  {"crk",       HB_TAG('W','C','R',' ')},       /* West-Cree */
-  {"crl",       HB_TAG('E','C','R',' ')},       /* [Northern] East Cree */
-  {"crm",       HB_TAG('M','C','R',' ')},       /* Moose Cree */
-  {"crx",       HB_TAG('C','R','R',' ')},       /* Carrier */
-  {"cs",        HB_TAG('C','S','Y',' ')},       /* Czech */
-  {"csa",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"csb",       HB_TAG('C','S','B',' ')},       /* Kashubian */
-  {"csh",       HB_TAG('Q','I','N',' ')},       /* Asho Chin */
-  {"cso",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"csy",       HB_TAG('Q','I','N',' ')},       /* Siyin Chin */
-  {"ctd",       HB_TAG('Q','I','N',' ')},       /* Tedim Chin */
-  {"cte",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"ctg",       HB_TAG('C','T','G',' ')},       /* Chittagonian */
-  {"ctl",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cts",       HB_TAG('B','I','K',' ')},       /* Northern Catanduanes Bikol */
-  {"cu",        HB_TAG('C','S','L',' ')},       /* Church Slavic */
-  {"cuc",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cuk",       HB_TAG('C','U','K',' ')},       /* San Blas Kuna */
-  {"cv",        HB_TAG('C','H','U',' ')},       /* Chuvash */
-  {"cvn",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cwd",       HB_TAG('D','C','R',' ')},       /* Woods Cree */
-  {"cy",        HB_TAG('W','E','L',' ')},       /* Welsh */
-  {"czt",       HB_TAG('Q','I','N',' ')},       /* Zotung Chin */
-  {"da",        HB_TAG('D','A','N',' ')},       /* Danish */
-  {"dao",       HB_TAG('Q','I','N',' ')},       /* Daai Chin */
-  {"dap",       HB_TAG('N','I','S',' ')},       /* Nisi (India) */
-  {"dar",       HB_TAG('D','A','R',' ')},       /* Dargwa */
-  {"dax",       HB_TAG('D','A','X',' ')},       /* Dayi */
-  {"de",        HB_TAG('D','E','U',' ')},       /* German */
-  {"dgo",       HB_TAG('D','G','O',' ')},       /* Dogri */
-  {"dhd",       HB_TAG('M','A','W',' ')},       /* Dhundari */
-  {"dhg",       HB_TAG('D','H','G',' ')},       /* Dhangu */
-  {"din",       HB_TAG('D','N','K',' ')},       /* Dinka [macrolanguage] */
-  {"diq",       HB_TAG('D','I','Q',' ')},       /* Dimli */
-  {"dje",       HB_TAG('D','J','R',' ')},       /* Zarma */
-  {"djr",       HB_TAG('D','J','R','0')},       /* Djambarrpuyngu */
-  {"dng",       HB_TAG('D','U','N',' ')},       /* Dungan */
-  {"dnj",       HB_TAG('D','N','J',' ')},       /* Dan */
-  {"doi",       HB_TAG('D','G','R',' ')},       /* Dogri [macrolanguage] */
-  {"dsb",       HB_TAG('L','S','B',' ')},       /* Lower Sorbian */
-  {"duj",       HB_TAG('D','U','J',' ')},       /* Dhuwal */
-  {"dv",        HB_TAG('D','I','V',' ')},       /* Dhivehi/Divehi/Maldivian */
-  {"dyu",       HB_TAG('J','U','L',' ')},       /* Jula */
-  {"dz",        HB_TAG('D','Z','N',' ')},       /* Dzongkha */
-  {"ee",        HB_TAG('E','W','E',' ')},       /* Ewe */
-  {"efi",       HB_TAG('E','F','I',' ')},       /* Efik */
-  {"ekk",       HB_TAG('E','T','I',' ')},       /* Standard Estonian */
-  {"el",        HB_TAG('E','L','L',' ')},       /* Modern Greek (1453-) */
-  {"emk",       HB_TAG('M','N','K',' ')},       /* Eastern Maninkakan */
-  {"en",        HB_TAG('E','N','G',' ')},       /* English */
-  {"enf",       HB_TAG('F','N','E',' ')},       /* Forest Nenets */
-  {"enh",       HB_TAG('T','N','E',' ')},       /* Tundra Nenets */
-  {"eo",        HB_TAG('N','T','O',' ')},       /* Esperanto */
-  {"eot",       HB_TAG('B','T','I',' ')},       /* Beti (Côte d'Ivoire) */
-  {"es",        HB_TAG('E','S','P',' ')},       /* Spanish */
-  {"esu",       HB_TAG('E','S','U',' ')},       /* Central Yupik */
-  {"et",        HB_TAG('E','T','I',' ')},       /* Estonian [macrolanguage] */
-  {"eu",        HB_TAG('E','U','Q',' ')},       /* Basque */
-  {"eve",       HB_TAG('E','V','N',' ')},       /* Even */
-  {"evn",       HB_TAG('E','V','K',' ')},       /* Evenki */
-  {"fa",        HB_TAG('F','A','R',' ')},       /* Persian [macrolanguage] */
-  {"fan",       HB_TAG('F','A','N','0')},       /* Fang */
-  {"fat",       HB_TAG('F','A','T',' ')},       /* Fanti */
-  {"ff",        HB_TAG('F','U','L',' ')},       /* Fulah [macrolanguage] */
-  {"fi",        HB_TAG('F','I','N',' ')},       /* Finnish */
-  {"fil",       HB_TAG('P','I','L',' ')},       /* Filipino */
-  {"fj",        HB_TAG('F','J','I',' ')},       /* Fijian */
-  {"flm",       HB_TAG('H','A','L',' ')},       /* Halam/Falam Chin [retired ISO639 code] */
-  {"fo",        HB_TAG('F','O','S',' ')},       /* Faroese */
-  {"fon",       HB_TAG('F','O','N',' ')},       /* Fon */
-  {"fr",        HB_TAG('F','R','A',' ')},       /* French */
-  {"frc",       HB_TAG('F','R','C',' ')},       /* Cajun French */
-  {"frp",       HB_TAG('F','R','P',' ')},       /* Arpitan/Francoprovençal */
-  {"fuf",       HB_TAG('F','T','A',' ')},       /* Futa */
-  {"fur",       HB_TAG('F','R','L',' ')},       /* Friulian */
-  {"fuv",       HB_TAG('F','U','V',' ')},       /* Nigerian Fulfulde */
-  {"fy",        HB_TAG('F','R','I',' ')},       /* Western Frisian */
-  {"ga",        HB_TAG('I','R','I',' ')},       /* Irish */
-  {"gaa",       HB_TAG('G','A','D',' ')},       /* Ga */
-  {"gag",       HB_TAG('G','A','G',' ')},       /* Gagauz */
-  {"gbm",       HB_TAG('G','A','W',' ')},       /* Garhwali */
-  {"gd",        HB_TAG('G','A','E',' ')},       /* Scottish Gaelic */
-  {"gez",       HB_TAG('G','E','Z',' ')},       /* Ge'ez */
-  {"ggo",       HB_TAG('G','O','N',' ')},       /* Southern Gondi */
-  {"gih",       HB_TAG('G','I','H',' ')},       /* Githabul */
-  {"gil",       HB_TAG('G','I','L','0')},       /* Kiribati (Gilbertese) */
-  {"gkp",       HB_TAG('G','K','P',' ')},       /* Kpelle (Guinea) */
-  {"gl",        HB_TAG('G','A','L',' ')},       /* Galician */
-  {"gld",       HB_TAG('N','A','N',' ')},       /* Nanai */
-  {"glk",       HB_TAG('G','L','K',' ')},       /* Gilaki */
-  {"gn",        HB_TAG('G','U','A',' ')},       /* Guarani [macrolanguage] */
-  {"gnn",       HB_TAG('G','N','N',' ')},       /* Gumatj */
-  {"gno",       HB_TAG('G','O','N',' ')},       /* Northern Gondi */
-  {"gog",       HB_TAG('G','O','G',' ')},       /* Gogo */
-  {"gon",       HB_TAG('G','O','N',' ')},       /* Gondi [macrolanguage] */
-  {"grt",       HB_TAG('G','R','O',' ')},       /* Garo */
-  {"gru",       HB_TAG('S','O','G',' ')},       /* Sodo Gurage */
-  {"gsw",       HB_TAG('A','L','S',' ')},       /* Alsatian */
-  {"gu",        HB_TAG('G','U','J',' ')},       /* Gujarati */
-  {"guc",       HB_TAG('G','U','C',' ')},       /* Wayuu */
-  {"guf",       HB_TAG('G','U','F',' ')},       /* Gupapuyngu */
-  {"guk",       HB_TAG('G','M','Z',' ')},       /* Gumuz */
-/*{"guk",       HB_TAG('G','U','K',' ')},*/     /* Gumuz (in SIL fonts) */
-  {"guz",       HB_TAG('G','U','Z',' ')},       /* Ekegusii/Gusii */
-  {"gv",        HB_TAG('M','N','X',' ')},       /* Manx */
-  {"ha",        HB_TAG('H','A','U',' ')},       /* Hausa */
-  {"har",       HB_TAG('H','R','I',' ')},       /* Harari */
-  {"haw",       HB_TAG('H','A','W',' ')},       /* Hawaiian */
-  {"hay",       HB_TAG('H','A','Y',' ')},       /* Haya */
-  {"haz",       HB_TAG('H','A','Z',' ')},       /* Hazaragi */
-  {"he",        HB_TAG('I','W','R',' ')},       /* Hebrew */
-  {"hi",        HB_TAG('H','I','N',' ')},       /* Hindi */
-  {"hil",       HB_TAG('H','I','L',' ')},       /* Hiligaynon */
-  {"hlt",       HB_TAG('Q','I','N',' ')},       /* Matu Chin */
-  {"hmn",       HB_TAG('H','M','N',' ')},       /* Hmong */
-  {"hnd",       HB_TAG('H','N','D',' ')},       /* [Southern] Hindko */
-  {"hne",       HB_TAG('C','H','H',' ')},       /* Chattisgarhi */
-  {"hno",       HB_TAG('H','N','D',' ')},       /* [Northern] Hindko */
-  {"ho",        HB_TAG('H','M','O',' ')},       /* Hiri Motu */
-  {"hoc",       HB_TAG('H','O',' ',' ')},       /* Ho */
-  {"hoj",       HB_TAG('H','A','R',' ')},       /* Harauti */
-  {"hr",        HB_TAG('H','R','V',' ')},       /* Croatian */
-  {"hsb",       HB_TAG('U','S','B',' ')},       /* Upper Sorbian */
-  {"ht",        HB_TAG('H','A','I',' ')},       /* Haitian/Haitian Creole */
-  {"hu",        HB_TAG('H','U','N',' ')},       /* Hungarian */
-  {"hy",        HB_TAG('H','Y','E',' ')},       /* Armenian */
-  {"hz",        HB_TAG('H','E','R',' ')},       /* Herero */
-  {"ia",        HB_TAG('I','N','A',' ')},       /* Interlingua (International Auxiliary Language Association) */
-  {"iba",       HB_TAG('I','B','A',' ')},       /* Iban */
-  {"ibb",       HB_TAG('I','B','B',' ')},       /* Ibibio */
-  {"id",        HB_TAG('I','N','D',' ')},       /* Indonesian */
-  {"ie",        HB_TAG('I','L','E',' ')},       /* Interlingue/Occidental */
-  {"ig",        HB_TAG('I','B','O',' ')},       /* Igbo */
-  {"igb",       HB_TAG('E','B','I',' ')},       /* Ebira */
-  {"ii",        HB_TAG('Y','I','M',' ')},       /* Yi Modern */
-  {"ijc",       HB_TAG('I','J','O',' ')},       /* Izon */
-  {"ijo",       HB_TAG('I','J','O',' ')},       /* Ijo [family] */
-  {"ik",        HB_TAG('I','P','K',' ')},       /* Inupiaq [macrolanguage] */
-  {"ilo",       HB_TAG('I','L','O',' ')},       /* Ilokano */
-  {"inh",       HB_TAG('I','N','G',' ')},       /* Ingush */
-  {"io",        HB_TAG('I','D','O',' ')},       /* Ido */
-  {"is",        HB_TAG('I','S','L',' ')},       /* Icelandic */
-  {"it",        HB_TAG('I','T','A',' ')},       /* Italian */
-  {"iu",        HB_TAG('I','N','U',' ')},       /* Inuktitut [macrolanguage] */
-  {"ja",        HB_TAG('J','A','N',' ')},       /* Japanese */
-  {"jam",       HB_TAG('J','A','M',' ')},       /* Jamaican Creole English */
-  {"jbo",       HB_TAG('J','B','O',' ')},       /* Lojban */
-  {"jv",        HB_TAG('J','A','V',' ')},       /* Javanese */
-  {"ka",        HB_TAG('K','A','T',' ')},       /* Georgian */
-  {"kaa",       HB_TAG('K','R','K',' ')},       /* Karakalpak */
-  {"kab",       HB_TAG('K','A','B','0')},       /* Kabyle */
-  {"kam",       HB_TAG('K','M','B',' ')},       /* Kamba (Kenya) */
-  {"kar",       HB_TAG('K','R','N',' ')},       /* Karen [family] */
-  {"kat",       HB_TAG('K','G','E',' ')},       /* Khutsuri Georgian */
-  {"kbd",       HB_TAG('K','A','B',' ')},       /* Kabardian */
-  {"kde",       HB_TAG('K','D','E',' ')},       /* Makonde */
-  {"kdr",       HB_TAG('K','R','M',' ')},       /* Karaim */
-  {"kdt",       HB_TAG('K','U','Y',' ')},       /* Kuy */
-  {"kea",       HB_TAG('K','E','A',' ')},       /* Kabuverdianu (Crioulo) */
-  {"kek",       HB_TAG('K','E','K',' ')},       /* Kekchi */
-  {"kex",       HB_TAG('K','K','N',' ')},       /* Kokni */
-  {"kfa",       HB_TAG('K','O','D',' ')},       /* Kodagu */
-  {"kfr",       HB_TAG('K','A','C',' ')},       /* Kachchi */
-  {"kfx",       HB_TAG('K','U','L',' ')},       /* Kulvi */
-  {"kfy",       HB_TAG('K','M','N',' ')},       /* Kumaoni */
-  {"kg",        HB_TAG('K','O','N',' ')},       /* Kongo [macrolanguage] */
-  {"kha",       HB_TAG('K','S','I',' ')},       /* Khasi */
-  {"khb",       HB_TAG('X','B','D',' ')},       /* Lü */
-  {"kht",       HB_TAG('K','H','N',' ')},       /* Khamti (Microsoft fonts) */
-/*{"kht",       HB_TAG('K','H','T',' ')},*/     /* Khamti (OpenType spec and SIL fonts) */
-  {"khw",       HB_TAG('K','H','W',' ')},       /* Khowar */
-  {"ki",        HB_TAG('K','I','K',' ')},       /* Gikuyu/Kikuyu */
-  {"kiu",       HB_TAG('K','I','U',' ')},       /* Kirmanjki */
-  {"kj",        HB_TAG('K','U','A',' ')},       /* Kuanyama/Kwanyama */
-  {"kjd",       HB_TAG('K','J','D',' ')},       /* Southern Kiwai */
-  {"kjh",       HB_TAG('K','H','A',' ')},       /* Khakass */
-  {"kjp",       HB_TAG('K','J','P',' ')},       /* Pwo Eastern Karen */
-  {"kk",        HB_TAG('K','A','Z',' ')},       /* Kazakh */
-  {"kl",        HB_TAG('G','R','N',' ')},       /* Kalaallisut */
-  {"kln",       HB_TAG('K','A','L',' ')},       /* Kalenjin */
-  {"km",        HB_TAG('K','H','M',' ')},       /* Central Khmer */
-  {"kmb",       HB_TAG('M','B','N',' ')},       /* Kimbundu */
-  {"kmw",       HB_TAG('K','M','O',' ')},       /* Komo (Democratic Republic of Congo) */
-  {"kn",        HB_TAG('K','A','N',' ')},       /* Kannada */
-  {"knn",       HB_TAG('K','O','K',' ')},       /* Konkani */
-  {"ko",        HB_TAG('K','O','R',' ')},       /* Korean */
-  {"koi",       HB_TAG('K','O','P',' ')},       /* Komi-Permyak */
-  {"kok",       HB_TAG('K','O','K',' ')},       /* Konkani [macrolanguage] */
-  {"kon",       HB_TAG('K','O','N','0')},       /* Kongo */
-  {"kos",       HB_TAG('K','O','S',' ')},       /* Kosraean */
-  {"kpe",       HB_TAG('K','P','L',' ')},       /* Kpelle [macrolanguage] */
-  {"kpv",       HB_TAG('K','O','Z',' ')},       /* Komi-Zyrian */
-  {"kpy",       HB_TAG('K','Y','K',' ')},       /* Koryak */
-  {"kqy",       HB_TAG('K','R','T',' ')},       /* Koorete */
-  {"kr",        HB_TAG('K','N','R',' ')},       /* Kanuri [macrolanguage] */
-  {"kri",       HB_TAG('K','R','I',' ')},       /* Krio */
-  {"krl",       HB_TAG('K','R','L',' ')},       /* Karelian */
-  {"kru",       HB_TAG('K','U','U',' ')},       /* Kurukh */
-  {"ks",        HB_TAG('K','S','H',' ')},       /* Kashmiri */
-  {"ksh",       HB_TAG('K','S','H','0')},       /* Ripuarian, Kölsch */
-/*{"ksw",       HB_TAG('K','R','N',' ')},*/     /* S'gaw Karen (Microsoft fonts?) */
-  {"ksw",       HB_TAG('K','S','W',' ')},       /* S'gaw Karen (OpenType spec and SIL fonts) */
-  {"ktb",       HB_TAG('K','E','B',' ')},       /* Kebena */
-  {"ktu",       HB_TAG('K','O','N',' ')},       /* Kikongo */
-  {"ku",        HB_TAG('K','U','R',' ')},       /* Kurdish [macrolanguage] */
-  {"kum",       HB_TAG('K','U','M',' ')},       /* Kumyk */
-  {"kv",        HB_TAG('K','O','M',' ')},       /* Komi [macrolanguage] */
-  {"kvd",       HB_TAG('K','U','I',' ')},       /* Kui (Indonesia) */
-  {"kw",        HB_TAG('C','O','R',' ')},       /* Cornish */
-  {"kxc",       HB_TAG('K','M','S',' ')},       /* Komso */
-  {"kxu",       HB_TAG('K','U','I',' ')},       /* Kui (India) */
-  {"ky",        HB_TAG('K','I','R',' ')},       /* Kirghiz/Kyrgyz */
-  {"kyu",       HB_TAG('K','Y','U',' ')},       /* Western Kayah */
-  {"la",        HB_TAG('L','A','T',' ')},       /* Latin */
-  {"lad",       HB_TAG('J','U','D',' ')},       /* Ladino */
-  {"lb",        HB_TAG('L','T','Z',' ')},       /* Luxembourgish */
-  {"lbe",       HB_TAG('L','A','K',' ')},       /* Lak */
-  {"lbj",       HB_TAG('L','D','K',' ')},       /* Ladakhi */
-  {"lez",       HB_TAG('L','E','Z',' ')},       /* Lezgi */
-  {"lg",        HB_TAG('L','U','G',' ')},       /* Ganda */
-  {"li",        HB_TAG('L','I','M',' ')},       /* Limburgan/Limburger/Limburgish */
-  {"lif",       HB_TAG('L','M','B',' ')},       /* Limbu */
-  {"lij",       HB_TAG('L','I','J',' ')},       /* Ligurian */
-  {"lis",       HB_TAG('L','I','S',' ')},       /* Lisu */
-  {"ljp",       HB_TAG('L','J','P',' ')},       /* Lampung Api */
-  {"lki",       HB_TAG('L','K','I',' ')},       /* Laki */
-  {"lld",       HB_TAG('L','A','D',' ')},       /* Ladin */
-  {"lmn",       HB_TAG('L','A','M',' ')},       /* Lambani */
-  {"lmo",       HB_TAG('L','M','O',' ')},       /* Lombard */
-  {"ln",        HB_TAG('L','I','N',' ')},       /* Lingala */
-  {"lo",        HB_TAG('L','A','O',' ')},       /* Lao */
-  {"lom",       HB_TAG('L','O','M',' ')},       /* Loma */
-  {"lrc",       HB_TAG('L','R','C',' ')},       /* Northern Luri */
-  {"lt",        HB_TAG('L','T','H',' ')},       /* Lithuanian */
-  {"lu",        HB_TAG('L','U','B',' ')},       /* Luba-Katanga */
-  {"lua",       HB_TAG('L','U','B',' ')},       /* Luba-Kasai */
-  {"luo",       HB_TAG('L','U','O',' ')},       /* Luo (Kenya and Tanzania) */
-  {"lus",       HB_TAG('M','I','Z',' ')},       /* Mizo */
-  {"luy",       HB_TAG('L','U','H',' ')},       /* Luyia/Oluluyia [macrolanguage] */
-  {"luz",       HB_TAG('L','R','C',' ')},       /* Southern Luri */
-  {"lv",        HB_TAG('L','V','I',' ')},       /* Latvian */
-  {"lzz",       HB_TAG('L','A','Z',' ')},       /* Laz */
-  {"mad",       HB_TAG('M','A','D',' ')},       /* Madurese */
-  {"mag",       HB_TAG('M','A','G',' ')},       /* Magahi */
-  {"mai",       HB_TAG('M','T','H',' ')},       /* Maithili */
-  {"mak",       HB_TAG('M','K','R',' ')},       /* Makasar */
-  {"mam",       HB_TAG('M','A','M',' ')},       /* Mam */
-  {"man",       HB_TAG('M','N','K',' ')},       /* Manding/Mandingo [macrolanguage] */
-  {"mdc",       HB_TAG('M','L','E',' ')},       /* Male (Papua New Guinea) */
-  {"mdf",       HB_TAG('M','O','K',' ')},       /* Moksha */
-  {"mdr",       HB_TAG('M','D','R',' ')},       /* Mandar */
-  {"mdy",       HB_TAG('M','L','E',' ')},       /* Male (Ethiopia) */
-  {"men",       HB_TAG('M','D','E',' ')},       /* Mende (Sierra Leone) */
-  {"mer",       HB_TAG('M','E','R',' ')},       /* Meru */
-  {"mfe",       HB_TAG('M','F','E',' ')},       /* Morisyen */
-  {"mg",        HB_TAG('M','L','G',' ')},       /* Malagasy [macrolanguage] */
-  {"mh",        HB_TAG('M','A','H',' ')},       /* Marshallese */
-  {"mhr",       HB_TAG('L','M','A',' ')},       /* Low Mari */
-  {"mi",        HB_TAG('M','R','I',' ')},       /* Maori */
-  {"min",       HB_TAG('M','I','N',' ')},       /* Minangkabau */
-  {"mk",        HB_TAG('M','K','D',' ')},       /* Macedonian */
-  {"mku",       HB_TAG('M','N','K',' ')},       /* Konyanka Maninka */
-  {"mkw",       HB_TAG('M','K','W',' ')},       /* Kituba (Congo) */
-  {"ml",        HB_TAG('M','L','R',' ')},       /* Malayalam */
-  {"mlq",       HB_TAG('M','N','K',' ')},       /* Western Maninkakan */
-  {"mn",        HB_TAG('M','N','G',' ')},       /* Mongolian [macrolanguage] */
-  {"mnc",       HB_TAG('M','C','H',' ')},       /* Manchu */
-  {"mni",       HB_TAG('M','N','I',' ')},       /* Manipuri */
-  {"mnk",       HB_TAG('M','N','D',' ')},       /* Mandinka */
-  {"mns",       HB_TAG('M','A','N',' ')},       /* Mansi */
-  {"mnw",       HB_TAG('M','O','N',' ')},       /* Mon */
-  {"mo",        HB_TAG('M','O','L',' ')},       /* Moldavian */
-  {"moh",       HB_TAG('M','O','H',' ')},       /* Mohawk */
-  {"mos",       HB_TAG('M','O','S',' ')},       /* Mossi */
-  {"mpe",       HB_TAG('M','A','J',' ')},       /* Majang */
-  {"mr",        HB_TAG('M','A','R',' ')},       /* Marathi */
-  {"mrh",       HB_TAG('Q','I','N',' ')},       /* Mara Chin */
-  {"mrj",       HB_TAG('H','M','A',' ')},       /* High Mari */
-  {"ms",        HB_TAG('M','L','Y',' ')},       /* Malay [macrolanguage] */
-  {"msc",       HB_TAG('M','N','K',' ')},       /* Sankaran Maninka */
-  {"mt",        HB_TAG('M','T','S',' ')},       /* Maltese */
-  {"mtr",       HB_TAG('M','A','W',' ')},       /* Mewari */
-  {"mus",       HB_TAG('M','U','S',' ')},       /* Creek */
-  {"mve",       HB_TAG('M','A','W',' ')},       /* Marwari (Pakistan) */
-  {"mwk",       HB_TAG('M','N','K',' ')},       /* Kita Maninkakan */
-  {"mwl",       HB_TAG('M','W','L',' ')},       /* Mirandese */
-  {"mwr",       HB_TAG('M','A','W',' ')},       /* Marwari [macrolanguage] */
-  {"mww",       HB_TAG('M','W','W',' ')},       /* Hmong Daw */
-  {"my",        HB_TAG('B','R','M',' ')},       /* Burmese */
-  {"mym",       HB_TAG('M','E','N',' ')},       /* Me'en */
-  {"myn",       HB_TAG('M','Y','N',' ')},       /* Mayan */
-  {"myq",       HB_TAG('M','N','K',' ')},       /* Forest Maninka (retired code) */
-  {"myv",       HB_TAG('E','R','Z',' ')},       /* Erzya */
-  {"mzn",       HB_TAG('M','Z','N',' ')},       /* Mazanderani */
-  {"na",        HB_TAG('N','A','U',' ')},       /* Nauru */
-  {"nag",       HB_TAG('N','A','G',' ')},       /* Naga-Assamese */
-  {"nah",       HB_TAG('N','A','H',' ')},       /* Nahuatl [family] */
-  {"nap",       HB_TAG('N','A','P',' ')},       /* Neapolitan */
-  {"nb",        HB_TAG('N','O','R',' ')},       /* Norwegian Bokmål */
-  {"nco",       HB_TAG('S','I','B',' ')},       /* Sibe */
-  {"nd",        HB_TAG('N','D','B',' ')},       /* [North] Ndebele */
-  {"ndc",       HB_TAG('N','D','C',' ')},       /* Ndau */
-  {"nds",       HB_TAG('N','D','S',' ')},       /* Low German/Low Saxon */
-  {"ne",        HB_TAG('N','E','P',' ')},       /* Nepali */
-  {"new",       HB_TAG('N','E','W',' ')},       /* Newari */
-  {"ng",        HB_TAG('N','D','G',' ')},       /* Ndonga */
-  {"nga",       HB_TAG('N','G','A',' ')},       /* Ngabaka */
-  {"ngl",       HB_TAG('L','M','W',' ')},       /* Lomwe */
-  {"ngo",       HB_TAG('S','X','T',' ')},       /* Sutu */
-  {"niu",       HB_TAG('N','I','U',' ')},       /* Niuean */
-  {"niv",       HB_TAG('G','I','L',' ')},       /* Gilyak */
-  {"nl",        HB_TAG('N','L','D',' ')},       /* Dutch */
-  {"nn",        HB_TAG('N','Y','N',' ')},       /* Norwegian Nynorsk */
-  {"no",        HB_TAG('N','O','R',' ')},       /* Norwegian [macrolanguage] */
-  {"nod",       HB_TAG('N','T','A',' ')},       /* Northern Thai */
-  {"noe",       HB_TAG('N','O','E',' ')},       /* Nimadi */
-  {"nog",       HB_TAG('N','O','G',' ')},       /* Nogai */
-  {"nov",       HB_TAG('N','O','V',' ')},       /* Novial */
-  {"nqo",       HB_TAG('N','K','O',' ')},       /* N'Ko */
-  {"nr",        HB_TAG('N','D','B',' ')},       /* [South] Ndebele */
-  {"nsk",       HB_TAG('N','A','S',' ')},       /* Naskapi */
-  {"nso",       HB_TAG('S','O','T',' ')},       /* [Northern] Sotho */
-  {"nv",        HB_TAG('N','A','V',' ')},       /* Navajo */
-  {"ny",        HB_TAG('C','H','I',' ')},       /* Chewa/Chichwa/Nyanja */
-  {"nym",       HB_TAG('N','Y','M',' ')},       /* Nyamwezi */
-  {"nyn",       HB_TAG('N','K','L',' ')},       /* Nyankole */
-  {"oc",        HB_TAG('O','C','I',' ')},       /* Occitan (post 1500) */
-  {"oj",        HB_TAG('O','J','B',' ')},       /* Ojibwa [macrolanguage] */
-  {"ojs",       HB_TAG('O','C','R',' ')},       /* Oji-Cree */
-  {"okm",       HB_TAG('K','O','H',' ')},       /* Korean Old Hangul */
-  {"om",        HB_TAG('O','R','O',' ')},       /* Oromo [macrolanguage] */
-  {"or",        HB_TAG('O','R','I',' ')},       /* Oriya */
-  {"os",        HB_TAG('O','S','S',' ')},       /* Ossetian */
-  {"pa",        HB_TAG('P','A','N',' ')},       /* Panjabi */
-  {"pag",       HB_TAG('P','A','G',' ')},       /* Pangasinan */
-  {"pam",       HB_TAG('P','A','M',' ')},       /* Kapampangan/Pampanga */
-  {"pap",       HB_TAG('P','A','P','0')},       /* Papiamento */
-  {"pau",       HB_TAG('P','A','U',' ')},       /* Palauan */
-  {"pcc",       HB_TAG('P','C','C',' ')},       /* Bouyei */
-  {"pcd",       HB_TAG('P','C','D',' ')},       /* Picard */
-  {"pce",       HB_TAG('P','L','G',' ')},       /* [Ruching] Palaung */
-  {"pck",       HB_TAG('Q','I','N',' ')},       /* Paite Chin */
-  {"pdc",       HB_TAG('P','D','C',' ')},       /* Pennsylvania German */
-  {"pes",       HB_TAG('F','A','R',' ')},       /* Iranian Persian */
-  {"phk",       HB_TAG('P','H','K',' ')},       /* Phake */
-  {"pi",        HB_TAG('P','A','L',' ')},       /* Pali */
-  {"pih",       HB_TAG('P','I','H',' ')},       /* Pitcairn-Norfolk */
-  {"pl",        HB_TAG('P','L','K',' ')},       /* Polish */
-  {"pll",       HB_TAG('P','L','G',' ')},       /* [Shwe] Palaung */
-  {"plp",       HB_TAG('P','A','P',' ')},       /* Palpa */
-  {"pms",       HB_TAG('P','M','S',' ')},       /* Piemontese */
-  {"pnb",       HB_TAG('P','N','B',' ')},       /* Western Panjabi */
-  {"poh",       HB_TAG('P','O','H',' ')},       /* Pocomchi */
-  {"pon",       HB_TAG('P','O','N',' ')},       /* Pohnpeian */
-  {"prs",       HB_TAG('D','R','I',' ')},       /* Afghan Persian/Dari */
-  {"ps",        HB_TAG('P','A','S',' ')},       /* Pashto/Pushto [macrolanguage] */
-  {"pt",        HB_TAG('P','T','G',' ')},       /* Portuguese */
-  {"pwo",       HB_TAG('P','W','O',' ')},       /* Pwo Western Karen */
-  {"qu",        HB_TAG('Q','U','Z',' ')},       /* Quechua [macrolanguage] */
-  {"quc",       HB_TAG('Q','U','C',' ')},       /* K'iche'/Quiché */
-  {"quh",       HB_TAG('Q','U','H',' ')},       /* Quechua (Bolivia) */
-  {"quz",       HB_TAG('Q','U','Z',' ')},       /* Cusco Quechua */
-  {"qvi",       HB_TAG('Q','V','I',' ')},       /* Quechua (Ecuador) */
-  {"qwh",       HB_TAG('Q','W','H',' ')},       /* Quechua (Peru) */
-  {"raj",       HB_TAG('R','A','J',' ')},       /* Rajasthani [macrolanguage] */
-  {"rar",       HB_TAG('R','A','R',' ')},       /* Rarotongan */
-  {"rbb",       HB_TAG('P','L','G',' ')},       /* Rumai Palaung */
-  {"rej",       HB_TAG('R','E','J',' ')},       /* Rejang */
-  {"ria",       HB_TAG('R','I','A',' ')},       /* Riang (India) */
-  {"rif",       HB_TAG('R','I','F',' ')},       /* Tarifit */
-  {"ril",       HB_TAG('R','I','A',' ')},       /* Riang (Myanmar) */
-  {"rit",       HB_TAG('R','I','T',' ')},       /* Ritarungo */
-  {"rki",       HB_TAG('A','R','K',' ')},       /* Rakhine */
-  {"rkw",       HB_TAG('R','K','W',' ')},       /* Arakwal */
-  {"rm",        HB_TAG('R','M','S',' ')},       /* Romansh */
-  {"rmy",       HB_TAG('R','M','Y',' ')},       /* Vlax Romani */
-  {"rn",        HB_TAG('R','U','N',' ')},       /* Rundi */
-  {"ro",        HB_TAG('R','O','M',' ')},       /* Romanian */
-  {"rom",       HB_TAG('R','O','Y',' ')},       /* Romany [macrolanguage] */
-  {"rtm",       HB_TAG('R','T','M',' ')},       /* Rotuman */
-  {"ru",        HB_TAG('R','U','S',' ')},       /* Russian */
-  {"rue",       HB_TAG('R','S','Y',' ')},       /* Rusyn */
-  {"rup",       HB_TAG('R','U','P',' ')},       /* Aromanian/Arumanian/Macedo-Romanian */
-  {"rw",        HB_TAG('R','U','A',' ')},       /* Kinyarwanda */
-  {"rwr",       HB_TAG('M','A','W',' ')},       /* Marwari (India) */
-  {"sa",        HB_TAG('S','A','N',' ')},       /* Sanskrit */
-  {"sah",       HB_TAG('Y','A','K',' ')},       /* Yakut */
-  {"sam",       HB_TAG('P','A','A',' ')},       /* Palestinian Aramaic */
-  {"sas",       HB_TAG('S','A','S',' ')},       /* Sasak */
-  {"sat",       HB_TAG('S','A','T',' ')},       /* Santali */
-  {"sc",        HB_TAG('S','R','D',' ')},       /* Sardinian [macrolanguage] */
-  {"sck",       HB_TAG('S','A','D',' ')},       /* Sadri */
-  {"scn",       HB_TAG('S','C','N',' ')},       /* Sicilian */
-  {"sco",       HB_TAG('S','C','O',' ')},       /* Scots */
-  {"scs",       HB_TAG('S','L','A',' ')},       /* [North] Slavey */
-  {"sd",        HB_TAG('S','N','D',' ')},       /* Sindhi */
-  {"se",        HB_TAG('N','S','M',' ')},       /* Northern Sami */
-  {"seh",       HB_TAG('S','N','A',' ')},       /* Sena */
-  {"sel",       HB_TAG('S','E','L',' ')},       /* Selkup */
-  {"sez",       HB_TAG('Q','I','N',' ')},       /* Senthang Chin */
-  {"sg",        HB_TAG('S','G','O',' ')},       /* Sango */
-  {"sga",       HB_TAG('S','G','A',' ')},       /* Old Irish (to 900) */
-  {"sgs",       HB_TAG('S','G','S',' ')},       /* Samogitian */
-  {"sgw",       HB_TAG('C','H','G',' ')},       /* Sebat Bet Gurage */
-/*{"sgw",       HB_TAG('S','G','W',' ')},*/     /* Sebat Bet Gurage (in SIL fonts) */
-  {"shi",       HB_TAG('S','H','I',' ')},       /* Tachelhit */
-  {"shn",       HB_TAG('S','H','N',' ')},       /* Shan */
-  {"si",        HB_TAG('S','N','H',' ')},       /* Sinhala */
-  {"sid",       HB_TAG('S','I','D',' ')},       /* Sidamo */
-  {"sjd",       HB_TAG('K','S','M',' ')},       /* Kildin Sami */
-  {"sk",        HB_TAG('S','K','Y',' ')},       /* Slovak */
-  {"skr",       HB_TAG('S','R','K',' ')},       /* Seraiki */
-  {"sl",        HB_TAG('S','L','V',' ')},       /* Slovenian */
-  {"sm",        HB_TAG('S','M','O',' ')},       /* Samoan */
-  {"sma",       HB_TAG('S','S','M',' ')},       /* Southern Sami */
-  {"smj",       HB_TAG('L','S','M',' ')},       /* Lule Sami */
-  {"smn",       HB_TAG('I','S','M',' ')},       /* Inari Sami */
-  {"sms",       HB_TAG('S','K','S',' ')},       /* Skolt Sami */
-  {"sn",        HB_TAG('S','N','A','0')},       /* Shona */
-  {"snk",       HB_TAG('S','N','K',' ')},       /* Soninke */
-  {"so",        HB_TAG('S','M','L',' ')},       /* Somali */
-  {"sop",       HB_TAG('S','O','P',' ')},       /* Songe */
-  {"sq",        HB_TAG('S','Q','I',' ')},       /* Albanian [macrolanguage] */
-  {"sr",        HB_TAG('S','R','B',' ')},       /* Serbian */
-  {"srr",       HB_TAG('S','R','R',' ')},       /* Serer */
-  {"ss",        HB_TAG('S','W','Z',' ')},       /* Swati */
-  {"st",        HB_TAG('S','O','T',' ')},       /* [Southern] Sotho */
-  {"stq",       HB_TAG('S','T','Q',' ')},       /* Saterfriesisch */
-  {"stv",       HB_TAG('S','I','G',' ')},       /* Silt'e */
-  {"su",        HB_TAG('S','U','N',' ')},       /* Sundanese */
-  {"suk",       HB_TAG('S','U','K',' ')},       /* Sukama */
-  {"suq",       HB_TAG('S','U','R',' ')},       /* Suri */
-  {"sv",        HB_TAG('S','V','E',' ')},       /* Swedish */
-  {"sva",       HB_TAG('S','V','A',' ')},       /* Svan */
-  {"sw",        HB_TAG('S','W','K',' ')},       /* Swahili [macrolanguage] */
-  {"swb",       HB_TAG('C','M','R',' ')},       /* Comorian */
-  {"swh",       HB_TAG('S','W','K',' ')},       /* Kiswahili/Swahili */
-  {"swv",       HB_TAG('M','A','W',' ')},       /* Shekhawati */
-  {"sxu",       HB_TAG('S','X','U',' ')},       /* Upper Saxon */
-  {"syc",       HB_TAG('S','Y','R',' ')},       /* Classical Syriac */
-  {"syl",       HB_TAG('S','Y','L',' ')},       /* Sylheti */
-  {"syr",       HB_TAG('S','Y','R',' ')},       /* Syriac [macrolanguage] */
-  {"szl",       HB_TAG('S','Z','L',' ')},       /* Silesian */
-  {"ta",        HB_TAG('T','A','M',' ')},       /* Tamil */
-  {"tab",       HB_TAG('T','A','B',' ')},       /* Tabasaran */
-  {"tcp",       HB_TAG('Q','I','N',' ')},       /* Tawr Chin */
-  {"tcy",       HB_TAG('T','U','L',' ')},       /* Tulu */
-  {"tcz",       HB_TAG('Q','I','N',' ')},       /* Thado Chin */
-  {"tdd",       HB_TAG('T','D','D',' ')},       /* Tai Nüa */
-  {"te",        HB_TAG('T','E','L',' ')},       /* Telugu */
-  {"tem",       HB_TAG('T','M','N',' ')},       /* Temne */
-  {"tet",       HB_TAG('T','E','T',' ')},       /* Tetum */
-  {"tg",        HB_TAG('T','A','J',' ')},       /* Tajik */
-  {"th",        HB_TAG('T','H','A',' ')},       /* Thai */
-  {"ti",        HB_TAG('T','G','Y',' ')},       /* Tigrinya */
-  {"tig",       HB_TAG('T','G','R',' ')},       /* Tigre */
-  {"tiv",       HB_TAG('T','I','V',' ')},       /* Tiv */
-  {"tk",        HB_TAG('T','K','M',' ')},       /* Turkmen */
-  {"tl",        HB_TAG('T','G','L',' ')},       /* Tagalog */
-  {"tmh",       HB_TAG('T','M','H',' ')},       /* Tamashek */
-  {"tn",        HB_TAG('T','N','A',' ')},       /* Tswana */
-  {"to",        HB_TAG('T','G','N',' ')},       /* Tonga (Tonga Islands) */
-  {"tod",       HB_TAG('T','O','D','0')},       /* Toma */
-  {"toi",       HB_TAG('T','N','G',' ')},       /* Tonga */
-  {"tpi",       HB_TAG('T','P','I',' ')},       /* Tok Pisin */
-  {"tr",        HB_TAG('T','R','K',' ')},       /* Turkish */
-  {"tru",       HB_TAG('T','U','A',' ')},       /* Turoyo Aramaic */
-  {"ts",        HB_TAG('T','S','G',' ')},       /* Tsonga */
-  {"tt",        HB_TAG('T','A','T',' ')},       /* Tatar */
-  {"tum",       HB_TAG('T','U','M',' ')},       /* Tumbuka */
-  {"tvl",       HB_TAG('T','V','L',' ')},       /* Tuvalu */
-  {"tw",        HB_TAG('T','W','I',' ')},       /* Twi */
-  {"ty",        HB_TAG('T','H','T',' ')},       /* Tahitian */
-  {"tyv",       HB_TAG('T','U','V',' ')},       /* Tuvin */
-  {"tyz",       HB_TAG('T','Y','Z',' ')},       /* Tày */
-  {"tzm",       HB_TAG('T','Z','M',' ')},       /* Central Atlas Tamazight */
-  {"tzo",       HB_TAG('T','Z','O',' ')},       /* Tzotzil */
-  {"udm",       HB_TAG('U','D','M',' ')},       /* Udmurt */
-  {"ug",        HB_TAG('U','Y','G',' ')},       /* Uighur */
-  {"uk",        HB_TAG('U','K','R',' ')},       /* Ukrainian */
-  {"umb",       HB_TAG('U','M','B',' ')},       /* Umbundu */
-  {"unr",       HB_TAG('M','U','N',' ')},       /* Mundari */
-  {"ur",        HB_TAG('U','R','D',' ')},       /* Urdu */
-  {"uz",        HB_TAG('U','Z','B',' ')},       /* Uzbek [macrolanguage] */
-  {"uzn",       HB_TAG('U','Z','B',' ')},       /* Northern Uzbek */
-  {"uzs",       HB_TAG('U','Z','B',' ')},       /* Southern Uzbek */
-  {"ve",        HB_TAG('V','E','N',' ')},       /* Venda */
-  {"vec",       HB_TAG('V','E','C',' ')},       /* Venetian */
-  {"vi",        HB_TAG('V','I','T',' ')},       /* Vietnamese */
-  {"vls",       HB_TAG('F','L','E',' ')},       /* Vlaams */
-  {"vmw",       HB_TAG('M','A','K',' ')},       /* Makhuwa */
-  {"vo",        HB_TAG('V','O','L',' ')},       /* Volapük */
-  {"vro",       HB_TAG('V','R','O',' ')},       /* Võro */
-  {"wa",        HB_TAG('W','L','N',' ')},       /* Walloon */
-  {"war",       HB_TAG('W','A','R',' ')},       /* Waray (Philippines) */
-  {"wbm",       HB_TAG('W','A',' ',' ')},       /* Wa */
-  {"wbr",       HB_TAG('W','A','G',' ')},       /* Wagdi */
-  {"wle",       HB_TAG('S','I','G',' ')},       /* Wolane */
-  {"wo",        HB_TAG('W','L','F',' ')},       /* Wolof */
-  {"wry",       HB_TAG('M','A','W',' ')},       /* Merwari */
-  {"wtm",       HB_TAG('W','T','M',' ')},       /* Mewati */
-  {"xal",       HB_TAG('K','L','M',' ')},       /* Kalmyk */
-  {"xan",       HB_TAG('S','E','K',' ')},       /* Sekota */
-  {"xh",        HB_TAG('X','H','S',' ')},       /* Xhosa */
-  {"xjb",       HB_TAG('X','J','B',' ')},       /* Minjangbal */
-  {"xog",       HB_TAG('X','O','G',' ')},       /* Soga */
-  {"xom",       HB_TAG('K','M','O',' ')},       /* Komo (Sudan) */
-  {"xpe",       HB_TAG('X','P','E',' ')},       /* Kpelle (Liberia) */
-  {"xsl",       HB_TAG('S','S','L',' ')},       /* South Slavey */
-  {"xst",       HB_TAG('S','I','G',' ')},       /* Silt'e (retired code) */
-  {"xwo",       HB_TAG('T','O','D',' ')},       /* Written Oirat (Todo) */
-  {"yao",       HB_TAG('Y','A','O',' ')},       /* Yao */
-  {"yap",       HB_TAG('Y','A','P',' ')},       /* Yapese */
-  {"yi",        HB_TAG('J','I','I',' ')},       /* Yiddish [macrolanguage] */
-  {"yo",        HB_TAG('Y','B','A',' ')},       /* Yoruba */
-  {"yos",       HB_TAG('Q','I','N',' ')},       /* Yos, deprecated by IANA in favor of Zou [zom] */
-  {"yso",       HB_TAG('N','I','S',' ')},       /* Nisi (China) */
-  {"za",        HB_TAG('Z','H','A',' ')},       /* Chuang/Zhuang [macrolanguage] */
-  {"zea",       HB_TAG('Z','E','A',' ')},       /* Zeeuws */
-  {"zgh",       HB_TAG('Z','G','H',' ')},       /* Standard Morrocan Tamazigh */
-  {"zne",       HB_TAG('Z','N','D',' ')},       /* Zande */
-  {"zom",       HB_TAG('Q','I','N',' ')},       /* Zou */
-  {"zu",        HB_TAG('Z','U','L',' ')},       /* Zulu */
-  {"zum",       HB_TAG('L','R','C',' ')},       /* Kumzari */
-  {"zza",       HB_TAG('Z','Z','A',' ')},       /* Zazaki */
-
-  /* The corresponding languages IDs for the following IDs are unclear,
-   * overlap, or are architecturally weird. Needs more research. */
-
-/*{"chp",       HB_TAG('S','A','Y',' ')},*/     /* Sayisi */
-/*{"cwd",       HB_TAG('T','C','R',' ')},*/     /* TH-Cree */
-/*{"emk",       HB_TAG('E','M','K',' ')},*/     /* Eastern Maninkakan */
-/*{"krc",       HB_TAG('B','A','L',' ')},*/     /* Balkar */
-/*{"??",        HB_TAG('B','C','R',' ')},*/     /* Bible Cree */
-/*{"zh?",       HB_TAG('C','H','N',' ')},*/     /* Chinese (seen in Microsoft fonts) */
-/*{"ar-Syrc?",  HB_TAG('G','A','R',' ')},*/     /* Garshuni */
-/*{"hy?",       HB_TAG('H','Y','E','0')},*/     /* Armenian East (ISO 639-3 hye according to Microsoft, but that’s equivalent to ISO 639-1 hy) */
-/*{"ga-Latg?/"  HB_TAG('I','R','T',' ')},*/     /* Irish Traditional */
-/*{"krc",       HB_TAG('K','A','R',' ')},*/     /* Karachay */
-/*{"ka-Geok?",  HB_TAG('K','G','E',' ')},*/     /* Khutsuri Georgian */
-/*{"kca",       HB_TAG('K','H','K',' ')},*/     /* Khanty-Kazim */
-/*{"kca",       HB_TAG('K','H','S',' ')},*/     /* Khanty-Shurishkar */
-/*{"kca",       HB_TAG('K','H','V',' ')},*/     /* Khanty-Vakhi */
-/*{"kqs, kss",  HB_TAG('K','I','S',' ')},*/     /* Kisii */
-/*{"lua",       HB_TAG('L','U','A',' ')},*/     /* Luba-Lulua */
-/*{"mlq",       HB_TAG('M','L','N',' ')},*/     /* Malinke */
-/*{"nso",       HB_TAG('N','S','O',' ')},*/     /* Sotho, Northern */
-/*{"??",        HB_TAG('M','A','L',' ')},*/     /* Malayalam Traditional */
-/*{"csw",       HB_TAG('N','C','R',' ')},*/     /* N-Cree */
-/*{"csw",       HB_TAG('N','H','C',' ')},*/     /* Norway House Cree */
-/*{"el-polyton",        HB_TAG('P','G','R',' ')},*/     /* Polytonic Greek */
-/*{"bgr, cnh, cnw, czt, sez, tcp, csy, ctd, flm, pck, tcz, zom, cmr, dao, hlt, cka, cnk, mrh, mwg, cbl, cnb, csh",      HB_TAG('Q','I','N',' ')},*/     /* Chin */
-/*{"??",        HB_TAG('Y','I','C',' ')},*/     /* Yi Classic */
-/*{"zh-Latn-pinyin",    HB_TAG('Z','H','P',' ')},*/     /* Chinese Phonetic */
-};
-
-typedef struct {
-  char language[11];
-  hb_tag_t tag;
-} LangTagLong;
-static const LangTagLong ot_languages_zh[] = {
-  /* Store longest-first, if one is a prefix of another. */
-  {"zh-cn",     HB_TAG('Z','H','S',' ')},       /* Chinese (China) */
-  {"zh-hk",     HB_TAG('Z','H','H',' ')},       /* Chinese (Hong Kong) */
-  {"zh-mo",     HB_TAG('Z','H','H',' ')},       /* Chinese (Macao) */
-  {"zh-sg",     HB_TAG('Z','H','S',' ')},       /* Chinese (Singapore) */
-  {"zh-tw",     HB_TAG('Z','H','T',' ')},       /* Chinese (Taiwan) */
-  {"zh-hans",   HB_TAG('Z','H','S',' ')},       /* Chinese (Simplified) */
-  {"zh-hant-hk",HB_TAG('Z','H','H',' ')},       /* Chinese (Hong Kong) */
-  {"zh-hant-mo",HB_TAG('Z','H','H',' ')},       /* Chinese (Macao) */
-  {"zh-hant",   HB_TAG('Z','H','T',' ')},       /* Chinese (Traditional) */
-};
-
 static int
 lang_compare_first_component (const void *pa,
                               const void *pb)
@@ -895,6 +189,21 @@
   return strncmp (a, b, MAX (da, db));
 }
 
+static bool
+subtag_matches (const char *lang_str,
+                const char *limit,
+                const char *subtag)
+{
+  do {
+    const char *s = strstr (lang_str, subtag);
+    if (!s || s >= limit)
+      return false;
+    if (!ISALNUM (s[strlen (subtag)]))
+      return true;
+    lang_str = s + strlen (subtag);
+  } while (true);
+}
+
 static hb_bool_t
 lang_matches (const char *lang_str, const char *spec)
 {
@@ -904,106 +213,186 @@
          (lang_str[len] == '\0' || lang_str[len] == '-');
 }
 
+typedef struct {
+  char language[4];
+  hb_tag_t tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
+} LangTag;
+
+#include "hb-ot-tag-table.hh"
+
+/* The corresponding languages IDs for the following IDs are unclear,
+ * overlap, or are architecturally weird. Needs more research. */
+
+/*{"??",        {HB_TAG('B','C','R',' ')}},*/   /* Bible Cree */
+/*{"zh?",       {HB_TAG('C','H','N',' ')}},*/   /* Chinese (seen in Microsoft fonts) */
+/*{"ar-Syrc?",  {HB_TAG('G','A','R',' ')}},*/   /* Garshuni */
+/*{"??",        {HB_TAG('N','G','R',' ')}},*/   /* Nagari */
+/*{"??",        {HB_TAG('Y','I','C',' ')}},*/   /* Yi Classic */
+/*{"zh?",       {HB_TAG('Z','H','P',' ')}},*/   /* Chinese Phonetic */
+
 hb_tag_t
 hb_ot_tag_from_language (hb_language_t language)
 {
-  const char *lang_str, *s;
-
-  if (language == HB_LANGUAGE_INVALID)
-    return HB_OT_TAG_DEFAULT_LANGUAGE;
-
-  lang_str = hb_language_to_string (language);
-
-  s = strstr (lang_str, "x-hbot");
-  if (s) {
-    char tag[4];
-    int i;
-    s += 6;
-    for (i = 0; i < 4 && ISALNUM (s[i]); i++)
-      tag[i] = TOUPPER (s[i]);
-    if (i) {
-      for (; i < 4; i++)
-        tag[i] = ' ';
-      return HB_TAG (tag[0], tag[1], tag[2], tag[3]);
-    }
-  }
-
-  /*
-   * "fonipa" is a variant tag in BCP-47, meaning the International Phonetic Alphabet.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-fonipa")) {
-    return HB_TAG('I','P','P','H');  /* Phonetic transcription—IPA conventions */
-  }
+  unsigned int count = 1;
+  hb_tag_t tags[1];
+  hb_ot_tags_from_script_and_language (HB_SCRIPT_UNKNOWN, language, nullptr, nullptr, &count, tags);
+  return count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_LANGUAGE;
+}
 
-  /*
-   * "fonnapa" is a variant tag in BCP-47, meaning the North American Phonetic Alphabet
-   * also known as Americanist Phonetic Notation.  It can be applied to any language.
-   */
-  if (strstr (lang_str, "-fonnapa")) {
-    return HB_TAG('A','P','P','H');  /* Phonetic transcription—Americanist conventions */
-  }
-
-  /*
-   * "Syre" is a BCP-47 script tag, meaning the Estrangela variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syre")) {
-    return HB_TAG('S','Y','R','E');  /* Estrangela Syriac */
-  }
+static void
+hb_ot_tags_from_language (const char   *lang_str,
+                          const char   *limit,
+                          unsigned int *count,
+                          hb_tag_t     *tags)
+{
+  const char *s;
 
-  /*
-   * "Syrj" is a BCP-47 script tag, meaning the Western variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syrj")) {
-    return HB_TAG('S','Y','R','J');  /* Western Syriac */
-  }
+  /* Check for matches of multiple subtags. */
+  if (hb_ot_tags_from_complex_language (lang_str, limit, count, tags))
+    return;
 
-  /*
-   * "Syrn" is a BCP-47 script tag, meaning the Eastern variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syrn")) {
-    return HB_TAG('S','Y','R','N');  /* Eastern Syriac */
-  }
-
-  /* Find a language matching in the first component */
+  /* Find a language matching in the first component. */
+  s = strchr (lang_str, '-');
   {
     const LangTag *lang_tag;
+    if (s && limit - lang_str >= 6)
+    {
+      const char *extlang_end = strchr (s + 1, '-');
+      /* If there is an extended language tag, use it. */
+      if (3 == (extlang_end ? extlang_end - s - 1 : strlen (s + 1)) &&
+          ISALPHA (s[1]))
+        lang_str = s + 1;
+    }
     lang_tag = (LangTag *) bsearch (lang_str, ot_languages,
                                     ARRAY_LENGTH (ot_languages), sizeof (LangTag),
                                     lang_compare_first_component);
     if (lang_tag)
-      return lang_tag->tag;
+    {
+      unsigned int i;
+      for (i = 0; i < *count && lang_tag->tags[i] != HB_TAG_NONE; i++)
+        tags[i] = lang_tag->tags[i];
+      *count = i;
+      return;
+    }
   }
 
-  /* Otherwise, check the Chinese ones */
-  if (0 == lang_compare_first_component (lang_str, "zh"))
-  {
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_LENGTH (ot_languages_zh); i++)
-    {
-      const LangTagLong *lang_tag;
-      lang_tag = &ot_languages_zh[i];
-      if (lang_matches (lang_str, lang_tag->language))
-        return lang_tag->tag;
-    }
-
-    /* Otherwise just return 'ZHS ' */
-    return HB_TAG('Z','H','S',' ');
-  }
-
-  s = strchr (lang_str, '-');
   if (!s)
     s = lang_str + strlen (lang_str);
   if (s - lang_str == 3) {
     /* Assume it's ISO-639-3 and upper-case and use it. */
-    return hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000u;
+    tags[0] = hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000u;
+    *count = 1;
+    return;
   }
 
-  return HB_OT_TAG_DEFAULT_LANGUAGE;
+  *count = 0;
+}
+
+static bool
+parse_private_use_subtag (const char     *private_use_subtag,
+                          unsigned int   *count,
+                          hb_tag_t       *tags,
+                          const char     *prefix,
+                          unsigned char (*normalize) (unsigned char))
+{
+  if (private_use_subtag && count && tags && *count)
+  {
+    const char *s = strstr (private_use_subtag, prefix);
+    if (s)
+    {
+      char tag[4];
+      int i;
+      s += strlen (prefix);
+      for (i = 0; i < 4 && ISALNUM (s[i]); i++)
+        tag[i] = normalize (s[i]);
+      if (i)
+      {
+        for (; i < 4; i++)
+          tag[i] = ' ';
+        tags[0] = HB_TAG (tag[0], tag[1], tag[2], tag[3]);
+        if ((tags[0] & 0xDFDFDFDF) == HB_OT_TAG_DEFAULT_SCRIPT)
+          tags[0] ^= ~0xDFDFDFDF;
+        *count = 1;
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+/**
+ * hb_ot_tags_from_script_and_language:
+ * @script: an #hb_script_t to convert.
+ * @language: an #hb_language_t to convert.
+ * @script_count: (allow-none): maximum number of script tags to retrieve (IN)
+ * and actual number of script tags retrieved (OUT)
+ * @script_tags: (out) (allow-none): array of size at least @script_count to store the
+ * script tag results
+ * @language_count: (allow-none): maximum number of language tags to retrieve
+ * (IN) and actual number of language tags retrieved (OUT)
+ * @language_tags: (out) (allow-none): array of size at least @language_count to store
+ * the language tag results
+ *
+ * Converts an #hb_script_t and an #hb_language_t to script and language tags.
+ *
+ * Since: 2.0.0
+ **/
+void
+hb_ot_tags_from_script_and_language (hb_script_t   script,
+                                     hb_language_t language,
+                                     unsigned int *script_count /* IN/OUT */,
+                                     hb_tag_t     *script_tags /* OUT */,
+                                     unsigned int *language_count /* IN/OUT */,
+                                     hb_tag_t     *language_tags /* OUT */)
+{
+  bool needs_script = true;
+
+  if (language == HB_LANGUAGE_INVALID)
+  {
+    if (language_count && language_tags && *language_count)
+      *language_count = 0;
+  }
+  else
+  {
+    const char *lang_str, *s, *limit, *private_use_subtag;
+    bool needs_language;
+
+    lang_str = hb_language_to_string (language);
+    limit = nullptr;
+    private_use_subtag = nullptr;
+    if (lang_str[0] == 'x' && lang_str[1] == '-')
+    {
+      private_use_subtag = lang_str;
+    } else {
+      for (s = lang_str + 1; *s; s++)
+      {
+        if (s[-1] == '-' && s[1] == '-')
+        {
+          if (s[0] == 'x')
+          {
+            private_use_subtag = s;
+            if (!limit)
+              limit = s - 1;
+            break;
+          } else if (!limit)
+          {
+            limit = s - 1;
+          }
+        }
+      }
+      if (!limit)
+        limit = s;
+    }
+
+    needs_script = parse_private_use_subtag (private_use_subtag, script_count, script_tags, "-hbsc", TOLOWER);
+    needs_language = parse_private_use_subtag (private_use_subtag, language_count, language_tags, "-hbot", TOUPPER);
+
+    if (needs_language && language_count && language_tags && *language_count)
+      hb_ot_tags_from_language (lang_str, limit, language_count, language_tags);
+  }
+
+  if (needs_script && script_count && script_tags && *script_count)
+    hb_ot_all_tags_from_script (script, script_count, script_tags);
 }
 
 /**
@@ -1023,36 +412,16 @@
   if (tag == HB_OT_TAG_DEFAULT_LANGUAGE)
     return nullptr;
 
-  /* struct LangTag has only room for 3-letter language tags. */
-  switch (tag) {
-  case HB_TAG('A','P','P','H'):  /* Phonetic transcription—Americanist conventions */
-    return hb_language_from_string ("und-fonnapa", -1);
-  case HB_TAG('I','P','P','H'):  /* Phonetic transcription—IPA conventions */
-    return hb_language_from_string ("und-fonipa", -1);
-  case HB_TAG('S','Y','R',' '):  /* Syriac [macrolanguage] */
-    return hb_language_from_string ("syr", -1);
-  case HB_TAG('S','Y','R','E'):  /* Estrangela Syriac */
-    return hb_language_from_string ("und-Syre", -1);
-  case HB_TAG('S','Y','R','J'):  /* Western Syriac */
-    return hb_language_from_string ("und-Syrj", -1);
-  case HB_TAG('S','Y','R','N'):  /* Eastern Syriac */
-    return hb_language_from_string ("und-Syrn", -1);
+  {
+    hb_language_t disambiguated_tag = hb_ot_ambiguous_tag_to_language (tag);
+    if (disambiguated_tag != HB_LANGUAGE_INVALID)
+      return disambiguated_tag;
   }
 
   for (i = 0; i < ARRAY_LENGTH (ot_languages); i++)
-    if (ot_languages[i].tag == tag)
+    if (ot_languages[i].tags[0] == tag)
       return hb_language_from_string (ot_languages[i].language, -1);
 
-  /* If tag starts with ZH, it's Chinese */
-  if ((tag & 0xFFFF0000u)  == 0x5A480000u) {
-    switch (tag) {
-      case HB_TAG('Z','H','H',' '): return hb_language_from_string ("zh-hk", -1); /* Hong Kong */
-      case HB_TAG('Z','H','S',' '): return hb_language_from_string ("zh-Hans", -1); /* Simplified */
-      case HB_TAG('Z','H','T',' '): return hb_language_from_string ("zh-Hant", -1); /* Traditional */
-      default: break; /* Fall through */
-    }
-  }
-
   /* Else return a custom language in the form of "x-hbotABCD" */
   {
     unsigned char buf[11] = "x-hbot";
@@ -1067,9 +436,74 @@
   }
 }
 
+/**
+ * hb_ot_tags_to_script_and_language:
+ * @script_tag: a script tag
+ * @language_tag: a language tag
+ * @script: (allow-none): the #hb_script_t corresponding to @script_tag (OUT).
+ * @language: (allow-none): the #hb_language_t corresponding to @script_tag and
+ * @language_tag (OUT).
+ *
+ * Converts a script tag and a language tag to an #hb_script_t and an
+ * #hb_language_t.
+ *
+ * Since: 2.0.0
+ **/
+void
+hb_ot_tags_to_script_and_language (hb_tag_t       script_tag,
+                                   hb_tag_t       language_tag,
+                                   hb_script_t   *script /* OUT */,
+                                   hb_language_t *language /* OUT */)
+{
+  hb_script_t script_out = hb_ot_tag_to_script (script_tag);
+  if (script)
+    *script = script_out;
+  if (language)
+  {
+    unsigned int script_count = 1;
+    hb_tag_t primary_script_tag[1];
+    hb_ot_tags_from_script_and_language (script_out,
+                                         HB_LANGUAGE_INVALID,
+                                         &script_count,
+                                         primary_script_tag,
+                                         nullptr, nullptr);
+    *language = hb_ot_tag_to_language (language_tag);
+    if (script_count == 0 || primary_script_tag[0] != script_tag)
+    {
+      unsigned char *buf;
+      const char *lang_str = hb_language_to_string (*language);
+      size_t len = strlen (lang_str);
+      buf = (unsigned char *) malloc (len + 11);
+      if (unlikely (!buf))
+      {
+        *language = nullptr;
+      }
+      else
+      {
+        memcpy (buf, lang_str, len);
+        if (lang_str[0] != 'x' || lang_str[1] != '-') {
+          buf[len++] = '-';
+          buf[len++] = 'x';
+        }
+        buf[len++] = '-';
+        buf[len++] = 'h';
+        buf[len++] = 'b';
+        buf[len++] = 's';
+        buf[len++] = 'c';
+        buf[len++] = script_tag >> 24;
+        buf[len++] = (script_tag >> 16) & 0xFF;
+        buf[len++] = (script_tag >> 8) & 0xFF;
+        buf[len++] = script_tag & 0xFF;
+        *language = hb_language_from_string ((char *) buf, len);
+        free (buf);
+      }
+    }
+  }
+}
+
 #ifdef MAIN
 static inline void
-test_langs_sorted (void)
+test_langs_sorted ()
 {
   for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++)
   {
@@ -1084,7 +518,7 @@
 }
 
 int
-main (void)
+main ()
 {
   test_langs_sorted ();
   return 0;
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-tag.h	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, 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
- */
-
-#ifndef HB_OT_H_IN
-#error "Include <hb-ot.h> instead."
-#endif
-
-#ifndef HB_OT_TAG_H
-#define HB_OT_TAG_H
-
-#include "hb.h"
-
-HB_BEGIN_DECLS
-
-
-#define HB_OT_TAG_DEFAULT_SCRIPT        HB_TAG ('D', 'F', 'L', 'T')
-#define HB_OT_TAG_DEFAULT_LANGUAGE      HB_TAG ('d', 'f', 'l', 't')
-
-HB_EXTERN void
-hb_ot_tags_from_script (hb_script_t  script,
-                        hb_tag_t    *script_tag_1,
-                        hb_tag_t    *script_tag_2);
-
-HB_EXTERN hb_script_t
-hb_ot_tag_to_script (hb_tag_t tag);
-
-HB_EXTERN hb_tag_t
-hb_ot_tag_from_language (hb_language_t language);
-
-HB_EXTERN hb_language_t
-hb_ot_tag_to_language (hb_tag_t tag);
-
-
-HB_END_DECLS
-
-#endif /* HB_OT_TAG_H */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-avar-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-avar-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,7 +27,7 @@
 #ifndef HB_OT_VAR_AVAR_TABLE_HH
 #define HB_OT_VAR_AVAR_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * avar -- Axis Variations
@@ -42,7 +42,7 @@
 
 struct AxisValueMap
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -59,7 +59,7 @@
 
 struct SegmentMaps : ArrayOf<AxisValueMap>
 {
-  inline int map (int value) const
+  int map (int value) const
   {
     /* The following special-cases are not part of OpenType, which requires
      * that at least -1, 0, and +1 must be mapped. But we include these as
@@ -93,14 +93,15 @@
             (value - arrayZ[i-1].fromCoord) + denom/2) / denom;
   }
 
-  DEFINE_SIZE_ARRAY (2, arrayZ);
+  public:
+  DEFINE_SIZE_ARRAY (2, *this);
 };
 
 struct avar
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_avar;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_avar;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!(version.sanitize (c) &&
@@ -108,7 +109,7 @@
                     c->check_struct (this))))
       return_trace (false);
 
-    const SegmentMaps *map = axisSegmentMapsZ;
+    const SegmentMaps *map = &firstAxisSegmentMaps;
     unsigned int count = axisCount;
     for (unsigned int i = 0; i < count; i++)
     {
@@ -120,11 +121,11 @@
     return_trace (true);
   }
 
-  inline void map_coords (int *coords, unsigned int coords_length) const
+  void map_coords (int *coords, unsigned int coords_length) const
   {
     unsigned int count = MIN<unsigned int> (coords_length, axisCount);
 
-    const SegmentMaps *map = axisSegmentMapsZ;
+    const SegmentMaps *map = &firstAxisSegmentMaps;
     for (unsigned int i = 0; i < count; i++)
     {
       coords[i] = map->map (coords[i]);
@@ -139,7 +140,7 @@
   HBUINT16      axisCount;      /* The number of variation axes in the font. This
                                  * must be the same number as axisCount in the
                                  * 'fvar' table. */
-  SegmentMaps   axisSegmentMapsZ[VAR];
+  SegmentMaps   firstAxisSegmentMaps;
 
   public:
   DEFINE_SIZE_MIN (8);
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-fvar-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-fvar-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,7 +27,7 @@
 #ifndef HB_OT_VAR_FVAR_TABLE_HH
 #define HB_OT_VAR_FVAR_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * fvar -- Font Variations
@@ -42,29 +42,40 @@
 
 struct InstanceRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
+  friend struct fvar;
+
+  hb_array_t<const Fixed> get_coordinates (unsigned int axis_count) const
+  { return coordinatesZ.as_array (axis_count); }
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  c->check_array (coordinates, coordinates[0].static_size, axis_count));
+                  c->check_array (coordinatesZ.arrayZ, axis_count));
   }
 
   protected:
   NameID        subfamilyNameID;/* The name ID for entries in the 'name' table
                                  * that provide subfamily names for this instance. */
-  HBUINT16      reserved;       /* Reserved for future use — set to 0. */
-  Fixed         coordinates[VAR];/* The coordinates array for this instance. */
+  HBUINT16      flags;          /* Reserved for future use — set to 0. */
+  UnsizedArrayOf<Fixed>
+                coordinatesZ;   /* The coordinates array for this instance. */
   //NameID      postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
   //                              * table that provide PostScript names for this
   //                              * instance. */
 
   public:
-  DEFINE_SIZE_ARRAY (4, coordinates);
+  DEFINE_SIZE_UNBOUNDED (4);
 };
 
 struct AxisRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  enum
+  {
+    AXIS_FLAG_HIDDEN    = 0x0001,
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -75,7 +86,7 @@
   Fixed         minValue;       /* The minimum coordinate value for the axis. */
   Fixed         defaultValue;   /* The default coordinate value for the axis. */
   Fixed         maxValue;       /* The maximum coordinate value for the axis. */
-  HBUINT16      reserved;       /* Reserved for future use — set to 0. */
+  HBUINT16      flags;          /* Axis flags. */
   NameID        axisNameID;     /* The name ID for entries in the 'name' table that
                                  * provide a display name for this axis. */
 
@@ -85,50 +96,80 @@
 
 struct fvar
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_fvar;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_fvar;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool has_data () const { return version.to_int (); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
                   likely (version.major == 1) &&
                   c->check_struct (this) &&
+                  axisSize == 20 && /* Assumed in our code. */
                   instanceSize >= axisCount * 4 + 4 &&
-                  axisSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */
-                  instanceSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */
-                  c->check_range (this, things) &&
-                  c->check_range (&StructAtOffset<char> (this, things),
-                                  axisCount * axisSize + instanceCount * instanceSize));
+                  get_axes ().sanitize (c) &&
+                  c->check_range (get_instance (0), instanceCount, instanceSize));
   }
 
-  inline unsigned int get_axis_count (void) const
-  { return axisCount; }
-
-  inline bool get_axis (unsigned int index, hb_ot_var_axis_t *info) const
-  {
-    if (unlikely (index >= axisCount))
-      return false;
+  unsigned int get_axis_count () const { return axisCount; }
 
-    if (info)
-    {
-      const AxisRecord &axis = get_axes ()[index];
-      info->tag = axis.axisTag;
-      info->name_id =  axis.axisNameID;
-      info->default_value = axis.defaultValue / 65536.;
-      /* Ensure order, to simplify client math. */
-      info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
-      info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
-    }
-
-    return true;
+  void get_axis_deprecated (unsigned int axis_index,
+                                   hb_ot_var_axis_t *info) const
+  {
+    const AxisRecord &axis = get_axes ()[axis_index];
+    info->tag = axis.axisTag;
+    info->name_id =  axis.axisNameID;
+    info->default_value = axis.defaultValue / 65536.;
+    /* Ensure order, to simplify client math. */
+    info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
+    info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
   }
 
-  inline unsigned int get_axis_infos (unsigned int      start_offset,
-                                      unsigned int     *axes_count /* IN/OUT */,
-                                      hb_ot_var_axis_t *axes_array /* OUT */) const
+  void get_axis_info (unsigned int axis_index,
+                      hb_ot_var_axis_info_t *info) const
+  {
+    const AxisRecord &axis = get_axes ()[axis_index];
+    info->axis_index = axis_index;
+    info->tag = axis.axisTag;
+    info->name_id =  axis.axisNameID;
+    info->flags = (hb_ot_var_axis_flags_t) (unsigned int) axis.flags;
+    info->default_value = axis.defaultValue / 65536.;
+    /* Ensure order, to simplify client math. */
+    info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
+    info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
+    info->reserved = 0;
+  }
+
+  unsigned int get_axes_deprecated (unsigned int      start_offset,
+                                    unsigned int     *axes_count /* IN/OUT */,
+                                    hb_ot_var_axis_t *axes_array /* OUT */) const
   {
     if (axes_count)
     {
+      /* TODO Rewrite as hb_array_t<>::sub-array() */
+      unsigned int count = axisCount;
+      start_offset = MIN (start_offset, count);
+
+      count -= start_offset;
+      axes_array += start_offset;
+
+      count = MIN (count, *axes_count);
+      *axes_count = count;
+
+      for (unsigned int i = 0; i < count; i++)
+        get_axis_deprecated (start_offset + i, axes_array + i);
+    }
+    return axisCount;
+  }
+
+  unsigned int get_axis_infos (unsigned int           start_offset,
+                               unsigned int          *axes_count /* IN/OUT */,
+                               hb_ot_var_axis_info_t *axes_array /* OUT */) const
+  {
+    if (axes_count)
+    {
+      /* TODO Rewrite as hb_array_t<>::sub-array() */
       unsigned int count = axisCount;
       start_offset = MIN (start_offset, count);
 
@@ -139,32 +180,48 @@
       *axes_count = count;
 
       for (unsigned int i = 0; i < count; i++)
-        get_axis (start_offset + i, axes_array + i);
+        get_axis_info (start_offset + i, axes_array + i);
     }
     return axisCount;
   }
 
-  inline bool find_axis (hb_tag_t tag, unsigned int *index, hb_ot_var_axis_t *info) const
+  bool find_axis_deprecated (hb_tag_t tag,
+                             unsigned int *axis_index,
+                             hb_ot_var_axis_t *info) const
   {
     const AxisRecord *axes = get_axes ();
     unsigned int count = get_axis_count ();
     for (unsigned int i = 0; i < count; i++)
       if (axes[i].axisTag == tag)
       {
-        if (index)
-          *index = i;
-        return get_axis (i, info);
+        if (axis_index)
+          *axis_index = i;
+        get_axis_deprecated (i, info);
+        return true;
       }
-    if (index)
-      *index = HB_OT_VAR_NO_AXIS_INDEX;
+    if (axis_index)
+      *axis_index = HB_OT_VAR_NO_AXIS_INDEX;
     return false;
   }
 
-  inline int normalize_axis_value (unsigned int axis_index, float v) const
+  bool find_axis_info (hb_tag_t tag,
+                       hb_ot_var_axis_info_t *info) const
   {
-    hb_ot_var_axis_t axis;
-    if (!get_axis (axis_index, &axis))
-      return 0;
+    const AxisRecord *axes = get_axes ();
+    unsigned int count = get_axis_count ();
+    for (unsigned int i = 0; i < count; i++)
+      if (axes[i].axisTag == tag)
+      {
+        get_axis_info (i, info);
+        return true;
+      }
+    return false;
+  }
+
+  int normalize_axis_value (unsigned int axis_index, float v) const
+  {
+    hb_ot_var_axis_info_t axis;
+    get_axis_info (axis_index, &axis);
 
     v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */
 
@@ -174,20 +231,65 @@
       v = (v - axis.default_value) / (axis.default_value - axis.min_value);
     else
       v = (v - axis.default_value) / (axis.max_value - axis.default_value);
-    return (int) (v * 16384. + (v >= 0. ? .5 : -.5));
+    return (int) (v * 16384.f + (v >= 0.f ? .5f : -.5f));
+  }
+
+  unsigned int get_instance_count () const { return instanceCount; }
+
+  hb_ot_name_id_t get_instance_subfamily_name_id (unsigned int instance_index) const
+  {
+    const InstanceRecord *instance = get_instance (instance_index);
+    if (unlikely (!instance)) return HB_OT_NAME_ID_INVALID;
+    return instance->subfamilyNameID;
+  }
+
+  hb_ot_name_id_t get_instance_postscript_name_id (unsigned int instance_index) const
+  {
+    const InstanceRecord *instance = get_instance (instance_index);
+    if (unlikely (!instance)) return HB_OT_NAME_ID_INVALID;
+    if (instanceSize >= axisCount * 4 + 6)
+      return StructAfter<NameID> (instance->get_coordinates (axisCount));
+    return HB_OT_NAME_ID_INVALID;
+  }
+
+  unsigned int get_instance_coords (unsigned int  instance_index,
+                                           unsigned int *coords_length, /* IN/OUT */
+                                           float        *coords         /* OUT */) const
+  {
+    const InstanceRecord *instance = get_instance (instance_index);
+    if (unlikely (!instance))
+    {
+      if (coords_length)
+        *coords_length = 0;
+      return 0;
+    }
+
+    if (coords_length && *coords_length)
+    {
+      hb_array_t<const Fixed> instanceCoords = instance->get_coordinates (axisCount)
+                                                         .sub_array (0, *coords_length);
+      for (unsigned int i = 0; i < instanceCoords.length; i++)
+        coords[i] = instanceCoords.arrayZ[i].to_float ();
+    }
+    return axisCount;
   }
 
   protected:
-  inline const AxisRecord * get_axes (void) const
-  { return &StructAtOffset<AxisRecord> (this, things); }
+  hb_array_t<const AxisRecord> get_axes () const
+  { return hb_array (&(this+firstAxis), axisCount); }
 
-  inline const InstanceRecord * get_instances (void) const
-  { return &StructAtOffset<InstanceRecord> (get_axes () + axisCount, 0); }
+  const InstanceRecord *get_instance (unsigned int i) const
+  {
+    if (unlikely (i >= instanceCount)) return nullptr;
+   return &StructAtOffset<InstanceRecord> (&StructAfter<InstanceRecord> (get_axes ()),
+                                           i * instanceSize);
+  }
 
   protected:
   FixedVersion<>version;        /* Version of the fvar table
                                  * initially set to 0x00010000u */
-  Offset16      things;         /* Offset in bytes from the beginning of the table
+  OffsetTo<AxisRecord>
+                firstAxis;      /* Offset in bytes from the beginning of the table
                                  * to the start of the AxisRecord array. */
   HBUINT16      reserved;       /* This field is permanently reserved. Set to 2. */
   HBUINT16      axisCount;      /* The number of variation axes in the font (the
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-hvar-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-hvar-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,7 +27,7 @@
 #ifndef HB_OT_VAR_HVAR_TABLE_HH
 #define HB_OT_VAR_HVAR_TABLE_HH
 
-#include "hb-ot-layout-common-private.hh"
+#include "hb-ot-layout-common.hh"
 
 
 namespace OT {
@@ -35,11 +35,13 @@
 
 struct DeltaSetIndexMap
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  c->check_array (mapData, get_width (), mapCount));
+                  c->check_range (mapDataZ.arrayZ,
+                                  mapCount,
+                                  get_width ()));
   }
 
   unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */
@@ -55,7 +57,7 @@
     unsigned int u = 0;
     { /* Fetch it. */
       unsigned int w = get_width ();
-      const HBUINT8 *p = mapData + w * v;
+      const HBUINT8 *p = mapDataZ.arrayZ + w * v;
       for (; w; w--)
         u = (u << 8) + *p++;
     }
@@ -71,20 +73,19 @@
   }
 
   protected:
-  inline unsigned int get_width (void) const
-  { return ((format >> 4) & 3) + 1; }
+  unsigned int get_width () const          { return ((format >> 4) & 3) + 1; }
 
-  inline unsigned int get_inner_bitcount (void) const
-  { return (format & 0xF) + 1; }
+  unsigned int get_inner_bitcount () const { return (format & 0xF) + 1; }
 
   protected:
   HBUINT16      format;         /* A packed field that describes the compressed
                                  * representation of delta-set indices. */
   HBUINT16      mapCount;       /* The number of mapping entries. */
-  HBUINT8               mapData[VAR];   /* The delta-set index mapping data. */
+  UnsizedArrayOf<HBUINT8>
+                mapDataZ;       /* The delta-set index mapping data. */
 
   public:
-  DEFINE_SIZE_ARRAY (4, mapData);
+  DEFINE_SIZE_ARRAY (4, mapDataZ);
 };
 
 
@@ -99,10 +100,10 @@
 
 struct HVARVVAR
 {
-  static const hb_tag_t HVARTag = HB_OT_TAG_HVAR;
-  static const hb_tag_t VVARTag = HB_OT_TAG_VVAR;
+  static constexpr hb_tag_t HVARTag = HB_OT_TAG_HVAR;
+  static constexpr hb_tag_t VVARTag = HB_OT_TAG_VVAR;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
@@ -113,15 +114,14 @@
                   rsbMap.sanitize (c, this));
   }
 
-  inline float get_advance_var (hb_codepoint_t glyph,
-                                int *coords, unsigned int coord_count) const
+  float get_advance_var (hb_codepoint_t glyph,
+                         const int *coords, unsigned int coord_count) const
   {
     unsigned int varidx = (this+advMap).map (glyph);
     return (this+varStore).get_delta (varidx, coords, coord_count);
   }
 
-  inline bool has_sidebearing_deltas (void) const
-  { return lsbMap && rsbMap; }
+  bool has_sidebearing_deltas () const { return lsbMap && rsbMap; }
 
   protected:
   FixedVersion<>version;        /* Version of the metrics variation table
@@ -140,12 +140,12 @@
 };
 
 struct HVAR : HVARVVAR {
-  static const hb_tag_t tableTag        = HB_OT_TAG_HVAR;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_HVAR;
 };
 struct VVAR : HVARVVAR {
-  static const hb_tag_t tableTag        = HB_OT_TAG_VVAR;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_VVAR;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (static_cast<const HVARVVAR *> (this)->sanitize (c) &&
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-mvar-table.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-mvar-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,7 +27,7 @@
 #ifndef HB_OT_VAR_MVAR_TABLE_HH
 #define HB_OT_VAR_MVAR_TABLE_HH
 
-#include "hb-ot-layout-common-private.hh"
+#include "hb-ot-layout-common.hh"
 
 
 namespace OT {
@@ -35,7 +35,7 @@
 
 struct VariationValueRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -58,9 +58,9 @@
 
 struct MVAR
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_MVAR;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_MVAR;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
@@ -68,14 +68,16 @@
                   c->check_struct (this) &&
                   valueRecordSize >= VariationValueRecord::static_size &&
                   varStore.sanitize (c, this) &&
-                  c->check_array (values, valueRecordSize, valueRecordCount));
+                  c->check_range (valuesZ.arrayZ,
+                                  valueRecordCount,
+                                  valueRecordSize));
   }
 
-  inline float get_var (hb_tag_t tag,
-                        int *coords, unsigned int coord_count) const
+  float get_var (hb_tag_t tag,
+                 const int *coords, unsigned int coord_count) const
   {
     const VariationValueRecord *record;
-    record = (VariationValueRecord *) bsearch (&tag, values,
+    record = (VariationValueRecord *) bsearch (&tag, valuesZ.arrayZ,
                                                valueRecordCount, valueRecordSize,
                                                tag_compare);
     if (!record)
@@ -85,7 +87,7 @@
   }
 
 protected:
-  static inline int tag_compare (const void *pa, const void *pb)
+  static int tag_compare (const void *pa, const void *pb)
   {
     const hb_tag_t *a = (const hb_tag_t *) pa;
     const Tag *b = (const Tag *) pb;
@@ -101,11 +103,12 @@
   HBUINT16      valueRecordCount;/* The number of value records — may be zero. */
   OffsetTo<VariationStore>
                 varStore;       /* Offset to item variation store table. */
-  HBUINT8               values[VAR];    /* Array of value records. The records must be
+  UnsizedArrayOf<HBUINT8>
+                valuesZ;        /* Array of value records. The records must be
                                  * in binary order of their valueTag field. */
 
   public:
-  DEFINE_SIZE_ARRAY (12, values);
+  DEFINE_SIZE_ARRAY (12, valuesZ);
 };
 
 } /* namespace OT */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,39 +24,35 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
-#include "hb-ot-layout-private.hh"
+#include "hb-ot-face.hh"
 #include "hb-ot-var-avar-table.hh"
 #include "hb-ot-var-fvar-table.hh"
 #include "hb-ot-var-mvar-table.hh"
 #include "hb-ot-var.h"
 
+
+/**
+ * SECTION:hb-ot-var
+ * @title: hb-ot-var
+ * @short_description: OpenType Font Variations
+ * @include: hb-ot.h
+ *
+ * Functions for fetching information about OpenType Variable Fonts.
+ **/
+
+
 /*
  * fvar/avar
  */
 
-static inline const OT::fvar&
-_get_fvar (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::fvar);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->fvar.get ());
-}
-static inline const OT::avar&
-_get_avar (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::avar);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->avar.get ());
-}
 
 /**
  * hb_ot_var_has_data:
  * @face: #hb_face_t to test
  *
  * This function allows to verify the presence of OpenType variation data on the face.
- * Alternatively, use hb_ot_var_get_axis_count().
  *
  * Return value: true if face has a `fvar' table and false otherwise
  *
@@ -65,7 +61,7 @@
 hb_bool_t
 hb_ot_var_has_data (hb_face_t *face)
 {
-  return &_get_fvar (face) != &Null(OT::fvar);
+  return face->table.fvar->has_data ();
 }
 
 /**
@@ -76,14 +72,14 @@
 unsigned int
 hb_ot_var_get_axis_count (hb_face_t *face)
 {
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.get_axis_count ();
+  return face->table.fvar->get_axis_count ();
 }
 
 /**
  * hb_ot_var_get_axes:
  *
  * Since: 1.4.2
+ * Deprecated: 2.2.0
  **/
 unsigned int
 hb_ot_var_get_axes (hb_face_t        *face,
@@ -91,14 +87,14 @@
                     unsigned int     *axes_count /* IN/OUT */,
                     hb_ot_var_axis_t *axes_array /* OUT */)
 {
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.get_axis_infos (start_offset, axes_count, axes_array);
+  return face->table.fvar->get_axes_deprecated (start_offset, axes_count, axes_array);
 }
 
 /**
  * hb_ot_var_find_axis:
  *
  * Since: 1.4.2
+ * Deprecated: 2.2.0
  **/
 hb_bool_t
 hb_ot_var_find_axis (hb_face_t        *face,
@@ -106,8 +102,68 @@
                      unsigned int     *axis_index,
                      hb_ot_var_axis_t *axis_info)
 {
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.find_axis (axis_tag, axis_index, axis_info);
+  return face->table.fvar->find_axis_deprecated (axis_tag, axis_index, axis_info);
+}
+
+/**
+ * hb_ot_var_get_axis_infos:
+ *
+ * Since: 2.2.0
+ **/
+HB_EXTERN unsigned int
+hb_ot_var_get_axis_infos (hb_face_t             *face,
+                          unsigned int           start_offset,
+                          unsigned int          *axes_count /* IN/OUT */,
+                          hb_ot_var_axis_info_t *axes_array /* OUT */)
+{
+  return face->table.fvar->get_axis_infos (start_offset, axes_count, axes_array);
+}
+
+/**
+ * hb_ot_var_find_axis_info:
+ *
+ * Since: 2.2.0
+ **/
+HB_EXTERN hb_bool_t
+hb_ot_var_find_axis_info (hb_face_t             *face,
+                          hb_tag_t               axis_tag,
+                          hb_ot_var_axis_info_t *axis_info)
+{
+  return face->table.fvar->find_axis_info (axis_tag, axis_info);
+}
+
+
+/*
+ * Named instances.
+ */
+
+unsigned int
+hb_ot_var_get_named_instance_count (hb_face_t *face)
+{
+  return face->table.fvar->get_instance_count ();
+}
+
+hb_ot_name_id_t
+hb_ot_var_named_instance_get_subfamily_name_id (hb_face_t   *face,
+                                                unsigned int instance_index)
+{
+  return face->table.fvar->get_instance_subfamily_name_id (instance_index);
+}
+
+hb_ot_name_id_t
+hb_ot_var_named_instance_get_postscript_name_id (hb_face_t  *face,
+                                                unsigned int instance_index)
+{
+  return face->table.fvar->get_instance_postscript_name_id (instance_index);
+}
+
+unsigned int
+hb_ot_var_named_instance_get_design_coords (hb_face_t    *face,
+                                            unsigned int  instance_index,
+                                            unsigned int *coords_length, /* IN/OUT */
+                                            float        *coords         /* OUT */)
+{
+  return face->table.fvar->get_instance_coords (instance_index, coords_length, coords);
 }
 
 
@@ -126,17 +182,16 @@
   for (unsigned int i = 0; i < coords_length; i++)
     coords[i] = 0;
 
-  const OT::fvar &fvar = _get_fvar (face);
+  const OT::fvar &fvar = *face->table.fvar;
   for (unsigned int i = 0; i < variations_length; i++)
   {
-    unsigned int axis_index;
-    if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, nullptr) &&
-        axis_index < coords_length)
-      coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value);
+    hb_ot_var_axis_info_t info;
+    if (hb_ot_var_find_axis_info (face, variations[i].tag, &info) &&
+        info.axis_index < coords_length)
+      coords[info.axis_index] = fvar.normalize_axis_value (info.axis_index, variations[i].value);
   }
 
-  const OT::avar &avar = _get_avar (face);
-  avar.map_coords (coords, coords_length);
+  face->table.avar->map_coords (coords, coords_length);
 }
 
 /**
@@ -150,10 +205,9 @@
                             const float *design_coords, /* IN */
                             int *normalized_coords /* OUT */)
 {
-  const OT::fvar &fvar = _get_fvar (face);
+  const OT::fvar &fvar = *face->table.fvar;
   for (unsigned int i = 0; i < coords_length; i++)
     normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]);
 
-  const OT::avar &avar = _get_avar (face);
-  avar.map_coords (normalized_coords, coords_length);
+  face->table.avar->map_coords (normalized_coords, coords_length);
 }
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var.h	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var.h	Fri Mar 01 16:59:19 2019 -0800
@@ -47,44 +47,85 @@
  * fvar / avar
  */
 
-/**
- * hb_ot_var_axis_t:
- *
- * Since: 1.4.2
- */
-typedef struct hb_ot_var_axis_t {
-  hb_tag_t tag;
-  unsigned int name_id;
-  float min_value;
-  float default_value;
-  float max_value;
-} hb_ot_var_axis_t;
-
 HB_EXTERN hb_bool_t
 hb_ot_var_has_data (hb_face_t *face);
 
-/**
- * HB_OT_VAR_NO_AXIS_INDEX:
- *
- * Since: 1.4.2
+
+/*
+ * Variation axes.
  */
-#define HB_OT_VAR_NO_AXIS_INDEX         0xFFFFFFFFu
+
 
 HB_EXTERN unsigned int
 hb_ot_var_get_axis_count (hb_face_t *face);
 
+/**
+ * hb_ot_var_axis_flags_t:
+ * @HB_OT_VAR_AXIS_FLAG_HIDDEN: The axis should not be exposed directly in user interfaces.
+ *
+ * Since: 2.2.0
+ */
+typedef enum { /*< flags >*/
+  HB_OT_VAR_AXIS_FLAG_HIDDEN    = 0x00000001u,
+
+  _HB_OT_VAR_AXIS_FLAG_MAX_VALUE= 0x7FFFFFFFu /*< skip >*/
+} hb_ot_var_axis_flags_t;
+
+/**
+ * hb_ot_var_axis_info_t:
+ *
+ * Since: 2.2.0
+ */
+typedef struct hb_ot_var_axis_info_t
+{
+  unsigned int                  axis_index;
+  hb_tag_t                      tag;
+  hb_ot_name_id_t               name_id;
+  hb_ot_var_axis_flags_t        flags;
+  float                         min_value;
+  float                         default_value;
+  float                         max_value;
+  /*< private >*/
+  unsigned int                  reserved;
+} hb_ot_var_axis_info_t;
+
 HB_EXTERN unsigned int
-hb_ot_var_get_axes (hb_face_t        *face,
-                    unsigned int      start_offset,
-                    unsigned int     *axes_count /* IN/OUT */,
-                    hb_ot_var_axis_t *axes_array /* OUT */);
+hb_ot_var_get_axis_infos (hb_face_t             *face,
+                          unsigned int           start_offset,
+                          unsigned int          *axes_count /* IN/OUT */,
+                          hb_ot_var_axis_info_t *axes_array /* OUT */);
 
 HB_EXTERN hb_bool_t
-hb_ot_var_find_axis (hb_face_t        *face,
-                     hb_tag_t          axis_tag,
-                     unsigned int     *axis_index,
-                     hb_ot_var_axis_t *axis_info);
+hb_ot_var_find_axis_info (hb_face_t             *face,
+                          hb_tag_t               axis_tag,
+                          hb_ot_var_axis_info_t *axis_info);
+
+
+/*
+ * Named instances.
+ */
+
+HB_EXTERN unsigned int
+hb_ot_var_get_named_instance_count (hb_face_t *face);
 
+HB_EXTERN hb_ot_name_id_t
+hb_ot_var_named_instance_get_subfamily_name_id (hb_face_t   *face,
+                                                unsigned int instance_index);
+
+HB_EXTERN hb_ot_name_id_t
+hb_ot_var_named_instance_get_postscript_name_id (hb_face_t  *face,
+                                                unsigned int instance_index);
+
+HB_EXTERN unsigned int
+hb_ot_var_named_instance_get_design_coords (hb_face_t    *face,
+                                            unsigned int  instance_index,
+                                            unsigned int *coords_length, /* IN/OUT */
+                                            float        *coords         /* OUT */);
+
+
+/*
+ * Conversions.
+ */
 
 HB_EXTERN void
 hb_ot_var_normalize_variations (hb_face_t            *face,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-vorg-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,181 @@
+/*
+ * 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_OT_VORG_TABLE_HH
+#define HB_OT_VORG_TABLE_HH
+
+#include "hb-open-type.hh"
+
+/*
+ * VORG -- Vertical Origin Table
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/vorg
+ */
+#define HB_OT_TAG_VORG HB_TAG('V','O','R','G')
+
+namespace OT {
+
+struct VertOriginMetric
+{
+  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));
+  }
+
+  public:
+  GlyphID       glyph;
+  FWORD         vertOriginY;
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct VORG
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_VORG;
+
+  bool has_data () const { return version.to_int (); }
+
+  int get_y_origin (hb_codepoint_t glyph) const
+  {
+    unsigned int i;
+    if (!vertYOrigins.bfind (glyph, &i))
+      return defaultVertOriginY;
+    return vertYOrigins[i].vertOriginY;
+  }
+
+  bool _subset (const hb_subset_plan_t *plan HB_UNUSED,
+                const VORG *vorg_table,
+                const hb_vector_t<VertOriginMetric> &subset_metrics,
+                unsigned int dest_sz,
+                void *dest) const
+  {
+    hb_serialize_context_t c (dest, dest_sz);
+
+    VORG *subset_table = c.start_serialize<VORG> ();
+    if (unlikely (!c.extend_min (*subset_table)))
+      return false;
+
+    subset_table->version.major.set (1);
+    subset_table->version.minor.set (0);
+
+    subset_table->defaultVertOriginY.set (vorg_table->defaultVertOriginY);
+    subset_table->vertYOrigins.len.set (subset_metrics.length);
+
+    bool success = true;
+    if (subset_metrics.length > 0)
+    {
+      unsigned int  size = VertOriginMetric::static_size * subset_metrics.length;
+      VertOriginMetric  *metrics = c.allocate_size<VertOriginMetric> (size);
+      if (likely (metrics != nullptr))
+        memcpy (metrics, &subset_metrics[0], size);
+      else
+        success = false;
+    }
+    c.end_serialize ();
+
+    return success;
+  }
+
+  bool subset (hb_subset_plan_t *plan) const
+  {
+    hb_blob_t *vorg_blob = hb_sanitize_context_t().reference_table<VORG> (plan->source);
+    const VORG *vorg_table = vorg_blob->as<VORG> ();
+
+    /* count the number of glyphs to be included in the subset table */
+    hb_vector_t<VertOriginMetric> subset_metrics;
+    subset_metrics.init ();
+    unsigned int glyph = 0;
+    unsigned int i = 0;
+    while ((glyph < plan->glyphs.length) && (i < vertYOrigins.len))
+    {
+      if (plan->glyphs[glyph] > vertYOrigins[i].glyph)
+        i++;
+      else if (plan->glyphs[glyph] < vertYOrigins[i].glyph)
+        glyph++;
+      else
+      {
+        VertOriginMetric *metrics = subset_metrics.push ();
+        metrics->glyph.set (glyph);
+        metrics->vertOriginY.set (vertYOrigins[i].vertOriginY);
+        glyph++;
+        i++;
+      }
+    }
+
+    /* alloc the new table */
+    unsigned int dest_sz = VORG::min_size + VertOriginMetric::static_size * subset_metrics.length;
+    void *dest = (void *) malloc (dest_sz);
+    if (unlikely (!dest))
+    {
+      subset_metrics.fini ();
+      hb_blob_destroy (vorg_blob);
+      return false;
+    }
+
+    /* serialize the new table */
+    if (!_subset (plan, vorg_table, subset_metrics, dest_sz, dest))
+    {
+      subset_metrics.fini ();
+      free (dest);
+      hb_blob_destroy (vorg_blob);
+      return false;
+    }
+
+    hb_blob_t *result = hb_blob_create ((const char *)dest,
+                                        dest_sz,
+                                        HB_MEMORY_MODE_READONLY,
+                                        dest,
+                                        free);
+    bool success = plan->add_table (HB_OT_TAG_VORG, result);
+    hb_blob_destroy (result);
+    subset_metrics.fini ();
+    hb_blob_destroy (vorg_blob);
+    return success;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  version.major == 1 &&
+                  vertYOrigins.sanitize (c));
+  }
+
+  protected:
+  FixedVersion<>        version;                /* Version of VORG table. Set to 0x00010000u. */
+  FWORD                 defaultVertOriginY;     /* The default vertical origin. */
+  SortedArrayOf<VertOriginMetric>
+                        vertYOrigins;           /* The array of vertical origins. */
+
+  public:
+  DEFINE_SIZE_ARRAY(8, vertYOrigins);
+};
+} /* namespace OT */
+
+#endif /* HB_OT_VORG_TABLE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot.h	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot.h	Fri Mar 01 16:59:19 2019 -0800
@@ -30,10 +30,12 @@
 
 #include "hb.h"
 
+#include "hb-ot-color.h"
+#include "hb-ot-deprecated.h"
 #include "hb-ot-font.h"
 #include "hb-ot-layout.h"
 #include "hb-ot-math.h"
-#include "hb-ot-tag.h"
+#include "hb-ot-name.h"
 #include "hb-ot-shape.h"
 #include "hb-ot-var.h"
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1242 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  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): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_PRIVATE_HH
-#define HB_PRIVATE_HH
-
-#define _GNU_SOURCE 1
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "hb.h"
-#define HB_H_IN
-#ifdef HAVE_OT
-#include "hb-ot.h"
-#define HB_OT_H_IN
-#endif
-
-#include <math.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
-#include <intrin.h>
-#endif
-
-#define HB_PASTE1(a,b) a##b
-#define HB_PASTE(a,b) HB_PASTE1(a,b)
-
-/* Compile-time custom allocator support. */
-
-#if defined(hb_malloc_impl) \
- && defined(hb_calloc_impl) \
- && defined(hb_realloc_impl) \
- && defined(hb_free_impl)
-extern "C" void* hb_malloc_impl(size_t size);
-extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
-extern "C" void* hb_realloc_impl(void *ptr, size_t size);
-extern "C" void  hb_free_impl(void *ptr);
-#define malloc hb_malloc_impl
-#define calloc hb_calloc_impl
-#define realloc hb_realloc_impl
-#define free hb_free_impl
-#endif
-
-
-/* Compiler attributes */
-
-
-#if __cplusplus < 201103L
-
-#ifndef nullptr
-#define nullptr NULL
-#endif
-
-// Static assertions
-#ifndef static_assert
-#define static_assert(e, msg) \
-        HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
-#endif // static_assert
-
-#ifdef __GNUC__
-#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
-#define thread_local __thread
-#endif
-#else
-#define thread_local
-#endif
-
-#endif // __cplusplus < 201103L
-
-#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
-#define likely(expr) (__builtin_expect (!!(expr), 1))
-#define unlikely(expr) (__builtin_expect (!!(expr), 0))
-#else
-#define likely(expr) (expr)
-#define unlikely(expr) (expr)
-#endif
-
-#if !defined(__GNUC__) && !defined(__clang__)
-#undef __attribute__
-#define __attribute__(x)
-#endif
-
-#if __GNUC__ >= 3
-#define HB_PURE_FUNC    __attribute__((pure))
-#define HB_CONST_FUNC   __attribute__((const))
-#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
-#else
-#define HB_PURE_FUNC
-#define HB_CONST_FUNC
-#define HB_PRINTF_FUNC(format_idx, arg_idx)
-#endif
-#if __GNUC__ >= 4
-#define HB_UNUSED       __attribute__((unused))
-#elif defined(_MSC_VER) /* https://github.com/harfbuzz/harfbuzz/issues/635 */
-#define HB_UNUSED __pragma(warning(suppress: 4100 4101))
-#else
-#define HB_UNUSED
-#endif
-
-#ifndef HB_INTERNAL
-# if !defined(HB_NO_VISIBILITY) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_MSC_VER) && !defined(__SUNPRO_CC)
-#  define HB_INTERNAL __attribute__((__visibility__("hidden")))
-# else
-#  define HB_INTERNAL
-#  define HB_NO_VISIBILITY 1
-# endif
-#endif
-
-#if __GNUC__ >= 3
-#define HB_FUNC __PRETTY_FUNCTION__
-#elif defined(_MSC_VER)
-#define HB_FUNC __FUNCSIG__
-#else
-#define HB_FUNC __func__
-#endif
-
-#if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5140)
-/* https://github.com/harfbuzz/harfbuzz/issues/630 */
-#define __restrict
-#endif
-
-/*
- * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
- * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
- * cases that fall through without a break or return statement. HB_FALLTHROUGH
- * is only needed on cases that have code:
- *
- * switch (foo) {
- *   case 1: // These cases have no code. No fallthrough annotations are needed.
- *   case 2:
- *   case 3:
- *     foo = 4; // This case has code, so a fallthrough annotation is needed:
- *     HB_FALLTHROUGH;
- *   default:
- *     return foo;
- * }
- */
-#if defined(__clang__) && __cplusplus >= 201103L
-   /* clang's fallthrough annotations are only available starting in C++11. */
-#  define HB_FALLTHROUGH [[clang::fallthrough]]
-#elif __GNUC__ >= 7
-   /* GNU fallthrough attribute is available from GCC7 */
-#  define HB_FALLTHROUGH __attribute__((fallthrough))
-#elif defined(_MSC_VER)
-   /*
-    * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
-    * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
-    */
-#  include <sal.h>
-#  define HB_FALLTHROUGH __fallthrough
-#else
-#  define HB_FALLTHROUGH /* FALLTHROUGH */
-#endif
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-   /* We need Windows Vista for both Uniscribe backend and for
-    * MemoryBarrier.  We don't support compiling on Windows XP,
-    * though we run on it fine. */
-#  if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
-#    undef _WIN32_WINNT
-#  endif
-#  ifndef _WIN32_WINNT
-#    define _WIN32_WINNT 0x0600
-#  endif
-#  ifndef WIN32_LEAN_AND_MEAN
-#    define WIN32_LEAN_AND_MEAN 1
-#  endif
-#  ifndef STRICT
-#    define STRICT 1
-#  endif
-
-#  if defined(_WIN32_WCE)
-     /* Some things not defined on Windows CE. */
-#    define vsnprintf _vsnprintf
-#    define getenv(Name) nullptr
-#    if _WIN32_WCE < 0x800
-#      define setlocale(Category, Locale) "C"
-static int errno = 0; /* Use something better? */
-#    endif
-#  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
-#    define getenv(Name) nullptr
-#  endif
-#  if defined(_MSC_VER) && _MSC_VER < 1900
-#    define snprintf _snprintf
-#  endif
-#endif
-
-#if HAVE_ATEXIT
-/* atexit() is only safe to be called from shared libraries on certain
- * platforms.  Whitelist.
- * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
-#  if defined(__linux) && defined(__GLIBC_PREREQ)
-#    if __GLIBC_PREREQ(2,3)
-/* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
-#      define HB_USE_ATEXIT 1
-#    endif
-#  elif defined(_MSC_VER) || defined(__MINGW32__)
-/* For MSVC:
- * https://msdn.microsoft.com/en-us/library/tze57ck3.aspx
- * https://msdn.microsoft.com/en-us/library/zk17ww08.aspx
- * mingw32 headers say atexit is safe to use in shared libraries.
- */
-#    define HB_USE_ATEXIT 1
-#  elif defined(__ANDROID__)
-/* This is available since Android NKD r8 or r8b:
- * https://issuetracker.google.com/code/p/android/issues/detail?id=6455
- */
-#    define HB_USE_ATEXIT 1
-#  elif defined(__APPLE__)
-/* For macOS and related platforms, the atexit man page indicates
- * that it will be invoked when the library is unloaded, not only
- * at application exit.
- */
-#    define HB_USE_ATEXIT 1
-#  endif
-#endif
-#ifdef HB_NO_ATEXIT
-#  undef HB_USE_ATEXIT
-#endif
-
-/* Basics */
-
-#undef MIN
-template <typename Type>
-static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
-
-#undef MAX
-template <typename Type>
-static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
-
-static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
-{ return (a + (b - 1)) / b; }
-
-
-#undef  ARRAY_LENGTH
-template <typename Type, unsigned int n>
-static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
-/* A const version, but does not detect erratically being called on pointers. */
-#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
-
-#define HB_STMT_START do
-#define HB_STMT_END   while (0)
-
-template <unsigned int cond> class hb_assert_constant_t;
-template <> class hb_assert_constant_t<1> {};
-
-#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
-
-/* Lets assert int types.  Saves trouble down the road. */
-
-static_assert ((sizeof (int8_t) == 1), "");
-static_assert ((sizeof (uint8_t) == 1), "");
-static_assert ((sizeof (int16_t) == 2), "");
-static_assert ((sizeof (uint16_t) == 2), "");
-static_assert ((sizeof (int32_t) == 4), "");
-static_assert ((sizeof (uint32_t) == 4), "");
-static_assert ((sizeof (int64_t) == 8), "");
-static_assert ((sizeof (uint64_t) == 8), "");
-
-static_assert ((sizeof (hb_codepoint_t) == 4), "");
-static_assert ((sizeof (hb_position_t) == 4), "");
-static_assert ((sizeof (hb_mask_t) == 4), "");
-static_assert ((sizeof (hb_var_int_t) == 4), "");
-
-
-/* We like our types POD */
-
-#define _ASSERT_TYPE_POD1(_line, _type) union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; }
-#define _ASSERT_TYPE_POD0(_line, _type) _ASSERT_TYPE_POD1 (_line, _type)
-#define ASSERT_TYPE_POD(_type)          _ASSERT_TYPE_POD0 (__LINE__, _type)
-
-#ifdef __GNUC__
-# define _ASSERT_INSTANCE_POD1(_line, _instance) \
-        HB_STMT_START { \
-                typedef __typeof__(_instance) _type_##_line; \
-                _ASSERT_TYPE_POD1 (_line, _type_##_line); \
-        } HB_STMT_END
-#else
-# define _ASSERT_INSTANCE_POD1(_line, _instance)        typedef int _assertion_on_line_##_line##_not_tested
-#endif
-# define _ASSERT_INSTANCE_POD0(_line, _instance)        _ASSERT_INSTANCE_POD1 (_line, _instance)
-# define ASSERT_INSTANCE_POD(_instance)                 _ASSERT_INSTANCE_POD0 (__LINE__, _instance)
-
-/* Check _assertion in a method environment */
-#define _ASSERT_POD1(_line) \
-        HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \
-        { _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ }
-# define _ASSERT_POD0(_line)    _ASSERT_POD1 (_line)
-# define ASSERT_POD()           _ASSERT_POD0 (__LINE__)
-
-
-
-/* Tiny functions */
-
-/*
- * Void!
- */
-typedef const struct _hb_void_t *hb_void_t;
-#define HB_VOID ((const _hb_void_t *) nullptr)
-
-/* Return the number of 1 bits in v. */
-template <typename T>
-static inline HB_CONST_FUNC unsigned int
-_hb_popcount (T v)
-{
-#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined(__OPTIMIZE__)
-  if (sizeof (T) <= sizeof (unsigned int))
-    return __builtin_popcount (v);
-
-  if (sizeof (T) <= sizeof (unsigned long))
-    return __builtin_popcountl (v);
-
-  if (sizeof (T) <= sizeof (unsigned long long))
-    return __builtin_popcountll (v);
-#endif
-
-  if (sizeof (T) <= 4)
-  {
-    /* "HACKMEM 169" */
-    uint32_t y;
-    y = (v >> 1) &033333333333;
-    y = v - y - ((y >>1) & 033333333333);
-    return (((y + (y >> 3)) & 030707070707) % 077);
-  }
-
-  if (sizeof (T) == 8)
-  {
-    unsigned int shift = 32;
-    return _hb_popcount<uint32_t> ((uint32_t) v) + _hb_popcount ((uint32_t) (v >> shift));
-  }
-
-  if (sizeof (T) == 16)
-  {
-    unsigned int shift = 64;
-    return _hb_popcount<uint64_t> ((uint64_t) v) + _hb_popcount ((uint64_t) (v >> shift));
-  }
-
-  assert (0);
-  return 0; /* Shut up stupid compiler. */
-}
-
-/* Returns the number of bits needed to store number */
-template <typename T>
-static inline HB_CONST_FUNC unsigned int
-_hb_bit_storage (T v)
-{
-  if (unlikely (!v)) return 0;
-
-#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
-  if (sizeof (T) <= sizeof (unsigned int))
-    return sizeof (unsigned int) * 8 - __builtin_clz (v);
-
-  if (sizeof (T) <= sizeof (unsigned long))
-    return sizeof (unsigned long) * 8 - __builtin_clzl (v);
-
-  if (sizeof (T) <= sizeof (unsigned long long))
-    return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
-#endif
-
-#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
-  if (sizeof (T) <= sizeof (unsigned int))
-  {
-    unsigned long where;
-    _BitScanReverse (&where, v);
-    return 1 + where;
-  }
-# if _WIN64
-  if (sizeof (T) <= 8)
-  {
-    unsigned long where;
-    _BitScanReverse64 (&where, v);
-    return 1 + where;
-  }
-# endif
-#endif
-
-  if (sizeof (T) <= 4)
-  {
-    /* "bithacks" */
-    const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
-    const unsigned int S[] = {1, 2, 4, 8, 16};
-    unsigned int r = 0;
-    for (int i = 4; i >= 0; i--)
-      if (v & b[i])
-      {
-        v >>= S[i];
-        r |= S[i];
-      }
-    return r + 1;
-  }
-  if (sizeof (T) <= 8)
-  {
-    /* "bithacks" */
-    const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
-    const unsigned int S[] = {1, 2, 4, 8, 16, 32};
-    unsigned int r = 0;
-    for (int i = 5; i >= 0; i--)
-      if (v & b[i])
-      {
-        v >>= S[i];
-        r |= S[i];
-      }
-    return r + 1;
-  }
-  if (sizeof (T) == 16)
-  {
-    unsigned int shift = 64;
-    return (v >> shift) ? _hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
-                          _hb_bit_storage<uint64_t> ((uint64_t) v);
-  }
-
-  assert (0);
-  return 0; /* Shut up stupid compiler. */
-}
-
-/* Returns the number of zero bits in the least significant side of v */
-template <typename T>
-static inline HB_CONST_FUNC unsigned int
-_hb_ctz (T v)
-{
-  if (unlikely (!v)) return 0;
-
-#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
-  if (sizeof (T) <= sizeof (unsigned int))
-    return __builtin_ctz (v);
-
-  if (sizeof (T) <= sizeof (unsigned long))
-    return __builtin_ctzl (v);
-
-  if (sizeof (T) <= sizeof (unsigned long long))
-    return __builtin_ctzll (v);
-#endif
-
-#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
-  if (sizeof (T) <= sizeof (unsigned int))
-  {
-    unsigned long where;
-    _BitScanForward (&where, v);
-    return where;
-  }
-# if _WIN64
-  if (sizeof (T) <= 8)
-  {
-    unsigned long where;
-    _BitScanForward64 (&where, v);
-    return where;
-  }
-# endif
-#endif
-
-  if (sizeof (T) <= 4)
-  {
-    /* "bithacks" */
-    unsigned int c = 32;
-    v &= - (int32_t) v;
-    if (v) c--;
-    if (v & 0x0000FFFF) c -= 16;
-    if (v & 0x00FF00FF) c -= 8;
-    if (v & 0x0F0F0F0F) c -= 4;
-    if (v & 0x33333333) c -= 2;
-    if (v & 0x55555555) c -= 1;
-    return c;
-  }
-  if (sizeof (T) <= 8)
-  {
-    /* "bithacks" */
-    unsigned int c = 64;
-    v &= - (int64_t) (v);
-    if (v) c--;
-    if (v & 0x00000000FFFFFFFFULL) c -= 32;
-    if (v & 0x0000FFFF0000FFFFULL) c -= 16;
-    if (v & 0x00FF00FF00FF00FFULL) c -= 8;
-    if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
-    if (v & 0x3333333333333333ULL) c -= 2;
-    if (v & 0x5555555555555555ULL) c -= 1;
-    return c;
-  }
-  if (sizeof (T) == 16)
-  {
-    unsigned int shift = 64;
-    return (uint64_t) v ? _hb_bit_storage<uint64_t> ((uint64_t) v) :
-                          _hb_bit_storage<uint64_t> ((uint64_t) v >> shift) + shift;
-  }
-
-  assert (0);
-  return 0; /* Shut up stupid compiler. */
-}
-
-static inline bool
-_hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
-{
-  return (size > 0) && (count >= ((unsigned int) -1) / size);
-}
-
-static inline unsigned int
-_hb_ceil_to_4 (unsigned int v)
-{
-  return ((v - 1) | 3) + 1;
-}
-
-
-
-/*
- *
- * Utility types
- *
- */
-
-#define HB_DISALLOW_COPY_AND_ASSIGN(TypeName) \
-  TypeName(const TypeName&); \
-  void operator=(const TypeName&)
-
-/*
- * Static pools
- */
-
-/* Global nul-content Null pool.  Enlarge as necessary. */
-
-#define HB_NULL_POOL_SIZE 264
-static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE.");
-
-#ifdef HB_NO_VISIBILITY
-static
-#else
-extern HB_INTERNAL
-#endif
-void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)]
-#ifdef HB_NO_VISIBILITY
-= {}
-#endif
-;
-/* Generic nul-content Null objects. */
-template <typename Type>
-static inline Type const & Null (void) {
-  static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
-  return *reinterpret_cast<Type const *> (_hb_NullPool);
-}
-#define Null(Type) Null<Type>()
-
-/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
-#define DEFINE_NULL_DATA(Namespace, Type, data) \
-} /* Close namespace. */ \
-static const char _Null##Type[sizeof (Namespace::Type) + 1] = data; /* +1 is for nul-termination in data */ \
-template <> \
-/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
-  return *reinterpret_cast<const Namespace::Type *> (_Null##Type); \
-} \
-namespace Namespace { \
-/* The following line really exists such that we end in a place needing semicolon */ \
-static_assert (Namespace::Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small.  Enlarge.")
-
-
-/* Global writable pool.  Enlarge as necessary. */
-
-/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
- * for correct operation. It only exist to catch and divert program logic bugs instead of
- * causing bad memory access. So, races there are not actually introducing incorrectness
- * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
-#ifdef HB_NO_VISIBILITY
-static
-#else
-extern HB_INTERNAL
-#endif
-/*thread_local*/ void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)]
-#ifdef HB_NO_VISIBILITY
-= {}
-#endif
-;
-/* CRAP pool: Common Region for Access Protection. */
-template <typename Type>
-static inline Type& Crap (void) {
-  static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
-  Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
-  *obj = Null(Type);
-  return *obj;
-}
-#define Crap(Type) Crap<Type>()
-
-template <typename Type>
-struct CrapOrNull {
-  static inline Type & get (void) { return Crap(Type); }
-};
-template <typename Type>
-struct CrapOrNull<const Type> {
-  static inline Type const & get (void) { return Null(Type); }
-};
-#define CrapOrNull(Type) CrapOrNull<Type>::get ()
-
-
-
-/* arrays and maps */
-
-
-#define HB_PREALLOCED_ARRAY_INIT {0, 0, nullptr}
-template <typename Type, unsigned int StaticSize=8>
-struct hb_vector_t
-{
-  unsigned int len;
-  unsigned int allocated;
-  bool successful;
-  Type *arrayZ;
-  Type static_array[StaticSize];
-
-  void init (void)
-  {
-    len = 0;
-    allocated = ARRAY_LENGTH (static_array);
-    successful = true;
-    arrayZ = static_array;
-  }
-
-  inline Type& operator [] (unsigned int i)
-  {
-    if (unlikely (i >= len))
-      return Crap (Type);
-    return arrayZ[i];
-  }
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len))
-      return Null(Type);
-    return arrayZ[i];
-  }
-
-  inline Type *push (void)
-  {
-    if (unlikely (!resize (len + 1)))
-      return &Crap(Type);
-    return &arrayZ[len - 1];
-  }
-  inline Type *push (const Type& v)
-  {
-    Type *p = push ();
-    *p = v;
-    return p;
-  }
-
-  /* Allocate for size but don't adjust len. */
-  inline bool alloc (unsigned int size)
-  {
-    if (unlikely (!successful))
-      return false;
-
-    if (likely (size <= allocated))
-      return true;
-
-    /* Reallocate */
-
-    unsigned int new_allocated = allocated;
-    while (size >= new_allocated)
-      new_allocated += (new_allocated >> 1) + 8;
-
-    Type *new_array = nullptr;
-
-    if (arrayZ == static_array)
-    {
-      new_array = (Type *) calloc (new_allocated, sizeof (Type));
-      if (new_array)
-        memcpy (new_array, arrayZ, len * sizeof (Type));
-    }
-    else
-    {
-      bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
-      if (likely (!overflows))
-        new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
-    }
-
-    if (unlikely (!new_array))
-    {
-      successful = false;
-      return false;
-    }
-
-    arrayZ = new_array;
-    allocated = new_allocated;
-
-    return true;
-  }
-
-  inline bool resize (int size_)
-  {
-    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
-    if (!alloc (size))
-      return false;
-
-    if (size > len)
-      memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ));
-
-    len = size;
-    return true;
-  }
-
-  inline void pop (void)
-  {
-    if (!len) return;
-    len--;
-  }
-
-  inline void remove (unsigned int i)
-  {
-     if (unlikely (i >= len))
-       return;
-     memmove (static_cast<void *> (&arrayZ[i]),
-              static_cast<void *> (&arrayZ[i + 1]),
-              (len - i - 1) * sizeof (Type));
-     len--;
-  }
-
-  inline void shrink (int size_)
-  {
-    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
-     if (size < len)
-       len = size;
-  }
-
-  template <typename T>
-  inline Type *find (T v) {
-    for (unsigned int i = 0; i < len; i++)
-      if (arrayZ[i] == v)
-        return &arrayZ[i];
-    return nullptr;
-  }
-  template <typename T>
-  inline const Type *find (T v) const {
-    for (unsigned int i = 0; i < len; i++)
-      if (arrayZ[i] == v)
-        return &arrayZ[i];
-    return nullptr;
-  }
-
-  inline void qsort (int (*cmp)(const void*, const void*))
-  {
-    ::qsort (arrayZ, len, sizeof (Type), cmp);
-  }
-
-  inline void qsort (void)
-  {
-    ::qsort (arrayZ, len, sizeof (Type), Type::cmp);
-  }
-
-  inline void qsort (unsigned int start, unsigned int end)
-  {
-    ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp);
-  }
-
-  template <typename T>
-  inline Type *lsearch (const T &x)
-  {
-    for (unsigned int i = 0; i < len; i++)
-      if (0 == this->arrayZ[i].cmp (&x))
-        return &arrayZ[i];
-    return nullptr;
-  }
-
-  template <typename T>
-  inline Type *bsearch (const T &x)
-  {
-    unsigned int i;
-    return bfind (x, &i) ? &arrayZ[i] : nullptr;
-  }
-  template <typename T>
-  inline const Type *bsearch (const T &x) const
-  {
-    unsigned int i;
-    return bfind (x, &i) ? &arrayZ[i] : nullptr;
-  }
-  template <typename T>
-  inline bool bfind (const T &x, unsigned int *i) const
-  {
-    int min = 0, max = (int) this->len - 1;
-    while (min <= max)
-    {
-      int mid = (min + max) / 2;
-      int c = this->arrayZ[mid].cmp (&x);
-      if (c < 0)
-        max = mid - 1;
-      else if (c > 0)
-        min = mid + 1;
-      else
-      {
-        *i = mid;
-        return true;
-      }
-    }
-    if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0))
-      max++;
-    *i = max;
-    return false;
-  }
-
-  inline void fini (void)
-  {
-    if (arrayZ != static_array)
-      free (arrayZ);
-    arrayZ = nullptr;
-    allocated = len = 0;
-  }
-};
-
-template <typename Type>
-struct hb_auto_t : Type
-{
-  hb_auto_t (void) { Type::init (); }
-  ~hb_auto_t (void) { Type::fini (); }
-  private: /* Hide */
-  void init (void) {}
-  void fini (void) {}
-};
-template <typename Type>
-struct hb_auto_array_t : hb_auto_t <hb_vector_t <Type> > {};
-
-
-#define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT}
-template <typename item_t, typename lock_t>
-struct hb_lockable_set_t
-{
-  hb_vector_t <item_t, 1> items;
-
-  inline void init (void) { items.init (); }
-
-  template <typename T>
-  inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item) {
-      if (replace) {
-        item_t old = *item;
-        *item = v;
-        l.unlock ();
-        old.fini ();
-      }
-      else {
-        item = nullptr;
-        l.unlock ();
-      }
-    } else {
-      item = items.push (v);
-      l.unlock ();
-    }
-    return item;
-  }
-
-  template <typename T>
-  inline void remove (T v, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item) {
-      item_t old = *item;
-      *item = items[items.len - 1];
-      items.pop ();
-      l.unlock ();
-      old.fini ();
-    } else {
-      l.unlock ();
-    }
-  }
-
-  template <typename T>
-  inline bool find (T v, item_t *i, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item)
-      *i = *item;
-    l.unlock ();
-    return !!item;
-  }
-
-  template <typename T>
-  inline item_t *find_or_insert (T v, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (!item) {
-      item = items.push (v);
-    }
-    l.unlock ();
-    return item;
-  }
-
-  inline void fini (lock_t &l)
-  {
-    if (!items.len) {
-      /* No need for locking. */
-      items.fini ();
-      return;
-    }
-    l.lock ();
-    while (items.len) {
-      item_t old = items[items.len - 1];
-        items.pop ();
-        l.unlock ();
-        old.fini ();
-        l.lock ();
-    }
-    items.fini ();
-    l.unlock ();
-  }
-
-};
-
-
-/* ASCII tag/character handling */
-
-static inline bool ISALPHA (unsigned char c)
-{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
-static inline bool ISALNUM (unsigned char c)
-{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
-static inline bool ISSPACE (unsigned char c)
-{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
-static inline unsigned char TOUPPER (unsigned char c)
-{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
-static inline unsigned char TOLOWER (unsigned char c)
-{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
-
-
-/* HB_NDEBUG disables some sanity checks that are very safe to disable and
- * should be disabled in production systems.  If NDEBUG is defined, enable
- * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
- * light-weight) to be enabled, then HB_DEBUG can be defined to disable
- * the costlier checks. */
-#ifdef NDEBUG
-#define HB_NDEBUG 1
-#endif
-
-
-/* Misc */
-
-template <typename T> class hb_assert_unsigned_t;
-template <> class hb_assert_unsigned_t<unsigned char> {};
-template <> class hb_assert_unsigned_t<unsigned short> {};
-template <> class hb_assert_unsigned_t<unsigned int> {};
-template <> class hb_assert_unsigned_t<unsigned long> {};
-
-template <typename T> static inline bool
-hb_in_range (T u, T lo, T hi)
-{
-  /* The sizeof() is here to force template instantiation.
-   * I'm sure there are better ways to do this but can't think of
-   * one right now.  Declaring a variable won't work as HB_UNUSED
-   * is unusable on some platforms and unused types are less likely
-   * to generate a warning than unused variables. */
-  static_assert ((sizeof (hb_assert_unsigned_t<T>) >= 0), "");
-
-  /* The casts below are important as if T is smaller than int,
-   * the subtract results will become a signed int! */
-  return (T)(u - lo) <= (T)(hi - lo);
-}
-
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
-{
-  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
-}
-
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
-{
-  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
-}
-
-
-/* Enable bitwise ops on enums marked as flags_t */
-/* To my surprise, looks like the function resolver is happy to silently cast
- * one enum to another...  So this doesn't provide the type-checking that I
- * originally had in mind... :(.
- *
- * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
- */
-#ifdef _MSC_VER
-# pragma warning(disable:4200)
-# pragma warning(disable:4800)
-#endif
-#define HB_MARK_AS_FLAG_T(T) \
-        extern "C++" { \
-          static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
-          static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
-          static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
-          static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
-          static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
-          static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
-          static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
-        }
-
-
-/* Useful for set-operations on small enums.
- * For example, for testing "x ∈ {x1, x2, x3}" use:
- * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
- */
-#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned int)(x) < 32) + (1U << (unsigned int)(x)))
-#define FLAG_UNSAFE(x) ((unsigned int)(x) < 32 ? (1U << (unsigned int)(x)) : 0)
-#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
-
-
-template <typename T, typename T2> static inline void
-hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
-{
-  for (unsigned int i = 1; i < len; i++)
-  {
-    unsigned int j = i;
-    while (j && compar (&array[j - 1], &array[i]) > 0)
-      j--;
-    if (i == j)
-      continue;
-    /* Move item i to occupy place for item j, shift what's in between. */
-    {
-      T t = array[i];
-      memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
-      array[j] = t;
-    }
-    if (array2)
-    {
-      T2 t = array2[i];
-      memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
-      array2[j] = t;
-    }
-  }
-}
-
-template <typename T> static inline void
-hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
-{
-  hb_stable_sort (array, len, compar, (int *) nullptr);
-}
-
-static inline hb_bool_t
-hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
-{
-  /* Pain because we don't know whether s is nul-terminated. */
-  char buf[64];
-  len = MIN (ARRAY_LENGTH (buf) - 1, len);
-  strncpy (buf, s, len);
-  buf[len] = '\0';
-
-  char *end;
-  errno = 0;
-  unsigned long v = strtoul (buf, &end, base);
-  if (errno) return false;
-  if (*end) return false;
-  *out = v;
-  return true;
-}
-
-
-/* Vectorization */
-
-struct HbOpOr
-{
-  static const bool passthru_left = true;
-  static const bool passthru_right = true;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
-};
-struct HbOpAnd
-{
-  static const bool passthru_left = false;
-  static const bool passthru_right = false;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
-};
-struct HbOpMinus
-{
-  static const bool passthru_left = true;
-  static const bool passthru_right = false;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
-};
-struct HbOpXor
-{
-  static const bool passthru_left = true;
-  static const bool passthru_right = true;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
-};
-
-
-/* Compiler-assisted vectorization. */
-
-/* The `vector_size' attribute was introduced in gcc 3.1. */
-#if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
-#define HB_VECTOR_SIZE 128
-#elif !defined(HB_VECTOR_SIZE)
-#define HB_VECTOR_SIZE 0
-#endif
-
-/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))). */
-template <typename elt_t, unsigned int byte_size>
-struct hb_vector_size_t
-{
-  elt_t& operator [] (unsigned int i) { return u.v[i]; }
-  const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
-
-  template <class Op>
-  inline hb_vector_size_t process (const hb_vector_size_t &o) const
-  {
-    hb_vector_size_t r;
-#if HB_VECTOR_SIZE
-    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
-      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
-        Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]);
-    else
-#endif
-      for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
-        Op::process (r.u.v[i], u.v[i], o.u.v[i]);
-    return r;
-  }
-  inline hb_vector_size_t operator | (const hb_vector_size_t &o) const
-  { return process<HbOpOr> (o); }
-  inline hb_vector_size_t operator & (const hb_vector_size_t &o) const
-  { return process<HbOpAnd> (o); }
-  inline hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
-  { return process<HbOpXor> (o); }
-  inline hb_vector_size_t operator ~ () const
-  {
-    hb_vector_size_t r;
-#if HB_VECTOR_SIZE && 0
-    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
-      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
-        r.u.vec[i] = ~u.vec[i];
-    else
-#endif
-    for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
-      r.u.v[i] = ~u.v[i];
-    return r;
-  }
-
-  private:
-  static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
-  union {
-    elt_t v[byte_size / sizeof (elt_t)];
-#if HB_VECTOR_SIZE
-    typedef unsigned long vec_t __attribute__((vector_size (HB_VECTOR_SIZE / 8)));
-    vec_t vec[byte_size / sizeof (vec_t)];
-#endif
-  } u;
-};
-
-
-/* Global runtime options. */
-
-struct hb_options_t
-{
-  unsigned int initialized : 1;
-  unsigned int uniscribe_bug_compatible : 1;
-};
-
-union hb_options_union_t {
-  unsigned int i;
-  hb_options_t opts;
-};
-static_assert ((sizeof (int) == sizeof (hb_options_union_t)), "");
-
-HB_INTERNAL void
-_hb_options_init (void);
-
-extern HB_INTERNAL hb_options_union_t _hb_options;
-
-static inline hb_options_t
-hb_options (void)
-{
-  if (unlikely (!_hb_options.i))
-    _hb_options_init ();
-
-  return _hb_options.opts;
-}
-
-/* Size signifying variable-sized array */
-#define VAR 1
-
-
-/* String type. */
-
-struct hb_bytes_t
-{
-  inline hb_bytes_t (void) : bytes (nullptr), len (0) {}
-  inline hb_bytes_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {}
-
-  inline int cmp (const hb_bytes_t &a) const
-  {
-    if (len != a.len)
-      return (int) a.len - (int) len;
-
-    return memcmp (a.bytes, bytes, len);
-  }
-  static inline int cmp (const void *pa, const void *pb)
-  {
-    hb_bytes_t *a = (hb_bytes_t *) pa;
-    hb_bytes_t *b = (hb_bytes_t *) pb;
-    return b->cmp (*a);
-  }
-
-  const char *bytes;
-  unsigned int len;
-};
-
-
-/* fallback for round() */
-#if !defined (HAVE_ROUND) && !defined (HAVE_DECL_ROUND)
-static inline double
-_hb_round (double x)
-{
-  if (x >= 0)
-    return floor (x + 0.5);
-  else
-    return ceil (x - 0.5);
-}
-#define round(x) _hb_round(x)
-#endif
-
-
-#endif /* HB_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set-digest-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-/*
- * Copyright © 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SET_DIGEST_PRIVATE_HH
-#define HB_SET_DIGEST_PRIVATE_HH
-
-#include "hb-private.hh"
-
-/*
- * The set digests here implement various "filters" that support
- * "approximate member query".  Conceptually these are like Bloom
- * Filter and Quotient Filter, however, much smaller, faster, and
- * designed to fit the requirements of our uses for glyph coverage
- * queries.
- *
- * Our filters are highly accurate if the lookup covers fairly local
- * set of glyphs, but fully flooded and ineffective if coverage is
- * all over the place.
- *
- * The frozen-set can be used instead of a digest, to trade more
- * memory for 100% accuracy, but in practice, that doesn't look like
- * an attractive trade-off.
- */
-
-template <typename mask_t, unsigned int shift>
-struct hb_set_digest_lowest_bits_t
-{
-  ASSERT_POD ();
-
-  static const unsigned int mask_bytes = sizeof (mask_t);
-  static const unsigned int mask_bits = sizeof (mask_t) * 8;
-  static const unsigned int num_bits = 0
-                                     + (mask_bytes >= 1 ? 3 : 0)
-                                     + (mask_bytes >= 2 ? 1 : 0)
-                                     + (mask_bytes >= 4 ? 1 : 0)
-                                     + (mask_bytes >= 8 ? 1 : 0)
-                                     + (mask_bytes >= 16? 1 : 0)
-                                     + 0;
-
-  static_assert ((shift < sizeof (hb_codepoint_t) * 8), "");
-  static_assert ((shift + num_bits <= sizeof (hb_codepoint_t) * 8), "");
-
-  inline void init (void) {
-    mask = 0;
-  }
-
-  inline void add (hb_codepoint_t g) {
-    mask |= mask_for (g);
-  }
-
-  inline bool add_range (hb_codepoint_t a, hb_codepoint_t b) {
-    if ((b >> shift) - (a >> shift) >= mask_bits - 1)
-      mask = (mask_t) -1;
-    else {
-      mask_t ma = mask_for (a);
-      mask_t mb = mask_for (b);
-      mask |= mb + (mb - ma) - (mb < ma);
-    }
-    return true;
-  }
-
-  template <typename T>
-  inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    for (unsigned int i = 0; i < count; i++)
-    {
-      add (*array);
-      array = (const T *) (stride + (const char *) array);
-    }
-  }
-  template <typename T>
-  inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    for (unsigned int i = 0; i < count; i++)
-    {
-      add (*array);
-      array = (const T *) (stride + (const char *) array);
-    }
-    return true;
-  }
-
-  inline bool may_have (hb_codepoint_t g) const {
-    return !!(mask & mask_for (g));
-  }
-
-  private:
-
-  static inline mask_t mask_for (hb_codepoint_t g) {
-    return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1));
-  }
-  mask_t mask;
-};
-
-template <typename head_t, typename tail_t>
-struct hb_set_digest_combiner_t
-{
-  ASSERT_POD ();
-
-  inline void init (void) {
-    head.init ();
-    tail.init ();
-  }
-
-  inline void add (hb_codepoint_t g) {
-    head.add (g);
-    tail.add (g);
-  }
-
-  inline bool add_range (hb_codepoint_t a, hb_codepoint_t b) {
-    head.add_range (a, b);
-    tail.add_range (a, b);
-    return true;
-  }
-  template <typename T>
-  inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    head.add_array (array, count, stride);
-    tail.add_array (array, count, stride);
-  }
-  template <typename T>
-  inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    head.add_sorted_array (array, count, stride);
-    tail.add_sorted_array (array, count, stride);
-    return true;
-  }
-
-  inline bool may_have (hb_codepoint_t g) const {
-    return head.may_have (g) && tail.may_have (g);
-  }
-
-  private:
-  head_t head;
-  tail_t tail;
-};
-
-
-/*
- * hb_set_digest_t
- *
- * This is a combination of digests that performs "best".
- * There is not much science to this: it's a result of intuition
- * and testing.
- */
-typedef hb_set_digest_combiner_t
-<
-  hb_set_digest_lowest_bits_t<unsigned long, 4>,
-  hb_set_digest_combiner_t
-  <
-    hb_set_digest_lowest_bits_t<unsigned long, 0>,
-    hb_set_digest_lowest_bits_t<unsigned long, 9>
-  >
-> hb_set_digest_t;
-
-
-#endif /* HB_SET_DIGEST_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set-digest.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,174 @@
+/*
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SET_DIGEST_HH
+#define HB_SET_DIGEST_HH
+
+#include "hb.hh"
+
+/*
+ * The set digests here implement various "filters" that support
+ * "approximate member query".  Conceptually these are like Bloom
+ * Filter and Quotient Filter, however, much smaller, faster, and
+ * designed to fit the requirements of our uses for glyph coverage
+ * queries.
+ *
+ * Our filters are highly accurate if the lookup covers fairly local
+ * set of glyphs, but fully flooded and ineffective if coverage is
+ * all over the place.
+ *
+ * The frozen-set can be used instead of a digest, to trade more
+ * memory for 100% accuracy, but in practice, that doesn't look like
+ * an attractive trade-off.
+ */
+
+template <typename mask_t, unsigned int shift>
+struct hb_set_digest_lowest_bits_t
+{
+  static constexpr unsigned mask_bytes = sizeof (mask_t);
+  static constexpr unsigned mask_bits = sizeof (mask_t) * 8;
+  static constexpr unsigned num_bits = 0
+                                     + (mask_bytes >= 1 ? 3 : 0)
+                                     + (mask_bytes >= 2 ? 1 : 0)
+                                     + (mask_bytes >= 4 ? 1 : 0)
+                                     + (mask_bytes >= 8 ? 1 : 0)
+                                     + (mask_bytes >= 16? 1 : 0)
+                                     + 0;
+
+  static_assert ((shift < sizeof (hb_codepoint_t) * 8), "");
+  static_assert ((shift + num_bits <= sizeof (hb_codepoint_t) * 8), "");
+
+  void init () { mask = 0; }
+
+  void add (hb_codepoint_t g) { mask |= mask_for (g); }
+
+  bool add_range (hb_codepoint_t a, hb_codepoint_t b)
+  {
+    if ((b >> shift) - (a >> shift) >= mask_bits - 1)
+      mask = (mask_t) -1;
+    else {
+      mask_t ma = mask_for (a);
+      mask_t mb = mask_for (b);
+      mask |= mb + (mb - ma) - (mb < ma);
+    }
+    return true;
+  }
+
+  template <typename T>
+  void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      add (*array);
+      array = (const T *) (stride + (const char *) array);
+    }
+  }
+  template <typename T>
+  bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      add (*array);
+      array = (const T *) (stride + (const char *) array);
+    }
+    return true;
+  }
+
+  bool may_have (hb_codepoint_t g) const
+  { return !!(mask & mask_for (g)); }
+
+  private:
+
+  static mask_t mask_for (hb_codepoint_t g)
+  { return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1)); }
+  mask_t mask;
+};
+
+template <typename head_t, typename tail_t>
+struct hb_set_digest_combiner_t
+{
+  void init ()
+  {
+    head.init ();
+    tail.init ();
+  }
+
+  void add (hb_codepoint_t g)
+  {
+    head.add (g);
+    tail.add (g);
+  }
+
+  bool add_range (hb_codepoint_t a, hb_codepoint_t b)
+  {
+    head.add_range (a, b);
+    tail.add_range (a, b);
+    return true;
+  }
+  template <typename T>
+  void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    head.add_array (array, count, stride);
+    tail.add_array (array, count, stride);
+  }
+  template <typename T>
+  bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    head.add_sorted_array (array, count, stride);
+    tail.add_sorted_array (array, count, stride);
+    return true;
+  }
+
+  bool may_have (hb_codepoint_t g) const
+  {
+    return head.may_have (g) && tail.may_have (g);
+  }
+
+  private:
+  head_t head;
+  tail_t tail;
+};
+
+
+/*
+ * hb_set_digest_t
+ *
+ * This is a combination of digests that performs "best".
+ * There is not much science to this: it's a result of intuition
+ * and testing.
+ */
+typedef hb_set_digest_combiner_t
+<
+  hb_set_digest_lowest_bits_t<unsigned long, 4>,
+  hb_set_digest_combiner_t
+  <
+    hb_set_digest_lowest_bits_t<unsigned long, 0>,
+    hb_set_digest_lowest_bits_t<unsigned long, 9>
+  >
+> hb_set_digest_t;
+
+
+#endif /* HB_SET_DIGEST_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,700 +0,0 @@
-/*
- * Copyright © 2012,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_SET_PRIVATE_HH
-#define HB_SET_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-
-
-/*
- * hb_set_t
- */
-
-/* TODO Keep a free-list so we can free pages that are completely zeroed.  At that
- * point maybe also use a sentinel value for "all-1" pages? */
-
-struct hb_set_t
-{
-  struct page_map_t
-  {
-    inline int cmp (const page_map_t *o) const { return (int) o->major - (int) major; }
-
-    uint32_t major;
-    uint32_t index;
-  };
-
-  struct page_t
-  {
-    inline void init0 (void) { memset (&v, 0, sizeof (v)); }
-    inline void init1 (void) { memset (&v, 0xff, sizeof (v)); }
-
-    inline unsigned int len (void) const
-    { return ARRAY_LENGTH_CONST (v); }
-
-    inline bool is_empty (void) const
-    {
-      for (unsigned int i = 0; i < len (); i++)
-        if (v[i])
-          return false;
-      return true;
-    }
-
-    inline void add (hb_codepoint_t g) { elt (g) |= mask (g); }
-    inline void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
-    inline bool has (hb_codepoint_t g) const { return !!(elt (g) & mask (g)); }
-
-    inline void add_range (hb_codepoint_t a, hb_codepoint_t b)
-    {
-      elt_t *la = &elt (a);
-      elt_t *lb = &elt (b);
-      if (la == lb)
-        *la |= (mask (b) << 1) - mask(a);
-      else
-      {
-        *la |= ~(mask (a) - 1);
-        la++;
-
-        memset (la, 0xff, (char *) lb - (char *) la);
-
-        *lb |= ((mask (b) << 1) - 1);
-      }
-    }
-
-    inline bool is_equal (const page_t *other) const
-    {
-      return 0 == memcmp (&v, &other->v, sizeof (v));
-    }
-
-    inline unsigned int get_population (void) const
-    {
-      unsigned int pop = 0;
-      for (unsigned int i = 0; i < len (); i++)
-        pop += _hb_popcount (v[i]);
-      return pop;
-    }
-
-    inline bool next (hb_codepoint_t *codepoint) const
-    {
-      unsigned int m = (*codepoint + 1) & MASK;
-      if (!m)
-      {
-        *codepoint = INVALID;
-        return false;
-      }
-      unsigned int i = m / ELT_BITS;
-      unsigned int j = m & ELT_MASK;
-
-      const elt_t vv = v[i] & ~((elt_t (1) << j) - 1);
-      for (const elt_t *p = &vv; i < len (); p = &v[++i])
-        if (*p)
-        {
-          *codepoint = i * ELT_BITS + elt_get_min (*p);
-          return true;
-        }
-
-      *codepoint = INVALID;
-      return false;
-    }
-    inline bool previous (hb_codepoint_t *codepoint) const
-    {
-      unsigned int m = (*codepoint - 1) & MASK;
-      if (m == MASK)
-      {
-        *codepoint = INVALID;
-        return false;
-      }
-      unsigned int i = m / ELT_BITS;
-      unsigned int j = m & ELT_MASK;
-
-      const elt_t vv = v[i] & ((elt_t (1) << (j + 1)) - 1);
-      for (const elt_t *p = &vv; (int) i >= 0; p = &v[--i])
-        if (*p)
-        {
-          *codepoint = i * ELT_BITS + elt_get_max (*p);
-          return true;
-        }
-
-      *codepoint = INVALID;
-      return false;
-    }
-    inline hb_codepoint_t get_min (void) const
-    {
-      for (unsigned int i = 0; i < len (); i++)
-        if (v[i])
-          return i * ELT_BITS + elt_get_min (v[i]);
-      return INVALID;
-    }
-    inline hb_codepoint_t get_max (void) const
-    {
-      for (int i = len () - 1; i >= 0; i--)
-        if (v[i])
-          return i * ELT_BITS + elt_get_max (v[i]);
-      return 0;
-    }
-
-    typedef unsigned long long elt_t;
-    static const unsigned int PAGE_BITS = 512;
-    static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
-
-    static inline unsigned int elt_get_min (const elt_t &elt) { return _hb_ctz (elt); }
-    static inline unsigned int elt_get_max (const elt_t &elt) { return _hb_bit_storage (elt) - 1; }
-
-    typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
-
-    static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
-    static const unsigned int ELT_MASK = ELT_BITS - 1;
-    static const unsigned int BITS = sizeof (vector_t) * 8;
-    static const unsigned int MASK = BITS - 1;
-    static_assert (PAGE_BITS == BITS, "");
-
-    elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; }
-    elt_t const &elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }
-    elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & ELT_MASK); }
-
-    vector_t v;
-  };
-  static_assert (page_t::PAGE_BITS == sizeof (page_t) * 8, "");
-
-  hb_object_header_t header;
-  bool successful; /* Allocations successful */
-  mutable unsigned int population;
-  hb_vector_t<page_map_t, 1> page_map;
-  hb_vector_t<page_t, 1> pages;
-
-  inline void init_shallow (void)
-  {
-    successful = true;
-    population = 0;
-    page_map.init ();
-    pages.init ();
-  }
-  inline void init (void)
-  {
-    hb_object_init (this);
-    init_shallow ();
-  }
-  inline void fini_shallow (void)
-  {
-    page_map.fini ();
-    pages.fini ();
-  }
-  inline void fini (void)
-  {
-    hb_object_fini (this);
-    fini_shallow ();
-  }
-
-  inline bool resize (unsigned int count)
-  {
-    if (unlikely (!successful)) return false;
-    if (!pages.resize (count) || !page_map.resize (count))
-    {
-      pages.resize (page_map.len);
-      successful = false;
-      return false;
-    }
-    return true;
-  }
-
-  inline void clear (void) {
-    if (unlikely (hb_object_is_inert (this)))
-      return;
-    successful = true;
-    population = 0;
-    page_map.resize (0);
-    pages.resize (0);
-  }
-  inline bool is_empty (void) const {
-    unsigned int count = pages.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!pages[i].is_empty ())
-        return false;
-    return true;
-  }
-
-  inline void dirty (void) { population = (unsigned int) -1; }
-
-  inline void add (hb_codepoint_t g)
-  {
-    if (unlikely (!successful)) return;
-    if (unlikely (g == INVALID)) return;
-    dirty ();
-    page_t *page = page_for_insert (g); if (unlikely (!page)) return;
-    page->add (g);
-  }
-  inline bool add_range (hb_codepoint_t a, hb_codepoint_t b)
-  {
-    if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
-    if (unlikely (a > b || a == INVALID || b == INVALID)) return false;
-    dirty ();
-    unsigned int ma = get_major (a);
-    unsigned int mb = get_major (b);
-    if (ma == mb)
-    {
-      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
-      page->add_range (a, b);
-    }
-    else
-    {
-      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
-      page->add_range (a, major_start (ma + 1) - 1);
-
-      for (unsigned int m = ma + 1; m < mb; m++)
-      {
-        page = page_for_insert (major_start (m)); if (unlikely (!page)) return false;
-        page->init1 ();
-      }
-
-      page = page_for_insert (b); if (unlikely (!page)) return false;
-      page->add_range (major_start (mb), b);
-    }
-    return true;
-  }
-
-  template <typename T>
-  inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    if (unlikely (!successful)) return;
-    if (!count) return;
-    dirty ();
-    hb_codepoint_t g = *array;
-    while (count)
-    {
-      unsigned int m = get_major (g);
-      page_t *page = page_for_insert (g); if (unlikely (!page)) return;
-      unsigned int start = major_start (m);
-      unsigned int end = major_start (m + 1);
-      do
-      {
-        page->add (g);
-
-        array = (const T *) ((const char *) array + stride);
-        count--;
-      }
-      while (count && (g = *array, start <= g && g < end));
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename T>
-  inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
-    if (!count) return true;
-    dirty ();
-    hb_codepoint_t g = *array;
-    hb_codepoint_t last_g = g;
-    while (count)
-    {
-      unsigned int m = get_major (g);
-      page_t *page = page_for_insert (g); if (unlikely (!page)) return false;
-      unsigned int end = major_start (m + 1);
-      do
-      {
-        /* If we try harder we can change the following comparison to <=;
-         * Not sure if it's worth it. */
-        if (g < last_g) return false;
-        last_g = g;
-        page->add (g);
-
-        array = (const T *) ((const char *) array + stride);
-        count--;
-      }
-      while (count && (g = *array, g < end));
-    }
-    return true;
-  }
-
-  inline void del (hb_codepoint_t g)
-  {
-    /* TODO perform op even if !successful. */
-    if (unlikely (!successful)) return;
-    page_t *p = page_for (g);
-    if (!p)
-      return;
-    dirty ();
-    p->del (g);
-  }
-  inline void del_range (hb_codepoint_t a, hb_codepoint_t b)
-  {
-    /* TODO perform op even if !successful. */
-    /* TODO Optimize, like add_range(). */
-    if (unlikely (!successful)) return;
-    for (unsigned int i = a; i < b + 1; i++)
-      del (i);
-  }
-  inline bool has (hb_codepoint_t g) const
-  {
-    const page_t *p = page_for (g);
-    if (!p)
-      return false;
-    return p->has (g);
-  }
-  inline bool intersects (hb_codepoint_t first,
-                          hb_codepoint_t last) const
-  {
-    hb_codepoint_t c = first - 1;
-    return next (&c) && c <= last;
-  }
-  inline void set (const hb_set_t *other)
-  {
-    if (unlikely (!successful)) return;
-    unsigned int count = other->pages.len;
-    if (!resize (count))
-      return;
-    population = other->population;
-    memcpy (pages.arrayZ, other->pages.arrayZ, count * sizeof (pages.arrayZ[0]));
-    memcpy (page_map.arrayZ, other->page_map.arrayZ, count * sizeof (page_map.arrayZ[0]));
-  }
-
-  inline bool is_equal (const hb_set_t *other) const
-  {
-    if (get_population () != other->get_population ())
-      return false;
-
-    unsigned int na = pages.len;
-    unsigned int nb = other->pages.len;
-
-    unsigned int a = 0, b = 0;
-    for (; a < na && b < nb; )
-    {
-      if (page_at (a).is_empty ()) { a++; continue; }
-      if (other->page_at (b).is_empty ()) { b++; continue; }
-      if (page_map[a].major != other->page_map[b].major ||
-          !page_at (a).is_equal (&other->page_at (b)))
-        return false;
-      a++;
-      b++;
-    }
-    for (; a < na; a++)
-      if (!page_at (a).is_empty ()) { return false; }
-    for (; b < nb; b++)
-      if (!other->page_at (b).is_empty ()) { return false; }
-
-    return true;
-  }
-
-  inline bool is_subset (const hb_set_t *larger_set) const
-  {
-    if (get_population () > larger_set->get_population ())
-      return false;
-
-    hb_codepoint_t c = INVALID;
-    while (next (&c))
-      if (!larger_set->has (c))
-        return false;
-
-    return true;
-  }
-
-  template <class Op>
-  inline void process (const hb_set_t *other)
-  {
-    if (unlikely (!successful)) return;
-
-    dirty ();
-
-    unsigned int na = pages.len;
-    unsigned int nb = other->pages.len;
-    unsigned int next_page = na;
-
-    unsigned int count = 0, newCount = 0;
-    unsigned int a = 0, b = 0;
-    for (; a < na && b < nb; )
-    {
-      if (page_map[a].major == other->page_map[b].major)
-      {
-        count++;
-        a++;
-        b++;
-      }
-      else if (page_map[a].major < other->page_map[b].major)
-      {
-        if (Op::passthru_left)
-          count++;
-        a++;
-      }
-      else
-      {
-        if (Op::passthru_right)
-          count++;
-        b++;
-      }
-    }
-    if (Op::passthru_left)
-      count += na - a;
-    if (Op::passthru_right)
-      count += nb - b;
-
-    if (count > pages.len)
-      if (!resize (count))
-        return;
-    newCount = count;
-
-    /* Process in-place backward. */
-    a = na;
-    b = nb;
-    for (; a && b; )
-    {
-      if (page_map[a - 1].major == other->page_map[b - 1].major)
-      {
-        a--;
-        b--;
-        count--;
-        page_map[count] = page_map[a];
-        Op::process (page_at (count).v, page_at (a).v, other->page_at (b).v);
-      }
-      else if (page_map[a - 1].major > other->page_map[b - 1].major)
-      {
-        a--;
-        if (Op::passthru_left)
-        {
-          count--;
-          page_map[count] = page_map[a];
-        }
-      }
-      else
-      {
-        b--;
-        if (Op::passthru_right)
-        {
-          count--;
-          page_map[count].major = other->page_map[b].major;
-          page_map[count].index = next_page++;
-          page_at (count).v = other->page_at (b).v;
-        }
-      }
-    }
-    if (Op::passthru_left)
-      while (a)
-      {
-        a--;
-        count--;
-        page_map[count] = page_map [a];
-      }
-    if (Op::passthru_right)
-      while (b)
-      {
-        b--;
-        count--;
-        page_map[count].major = other->page_map[b].major;
-        page_map[count].index = next_page++;
-        page_at (count).v = other->page_at (b).v;
-      }
-    assert (!count);
-    if (pages.len > newCount)
-      resize (newCount);
-  }
-
-  inline void union_ (const hb_set_t *other)
-  {
-    process<HbOpOr> (other);
-  }
-  inline void intersect (const hb_set_t *other)
-  {
-    process<HbOpAnd> (other);
-  }
-  inline void subtract (const hb_set_t *other)
-  {
-    process<HbOpMinus> (other);
-  }
-  inline void symmetric_difference (const hb_set_t *other)
-  {
-    process<HbOpXor> (other);
-  }
-  inline bool next (hb_codepoint_t *codepoint) const
-  {
-    if (unlikely (*codepoint == INVALID)) {
-      *codepoint = get_min ();
-      return *codepoint != INVALID;
-    }
-
-    page_map_t map = {get_major (*codepoint), 0};
-    unsigned int i;
-    page_map.bfind (map, &i);
-    if (i < page_map.len && page_map[i].major == map.major)
-    {
-      if (pages[page_map[i].index].next (codepoint))
-      {
-        *codepoint += page_map[i].major * page_t::PAGE_BITS;
-        return true;
-      }
-      i++;
-    }
-    for (; i < page_map.len; i++)
-    {
-      hb_codepoint_t m = pages[page_map[i].index].get_min ();
-      if (m != INVALID)
-      {
-        *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
-        return true;
-      }
-    }
-    *codepoint = INVALID;
-    return false;
-  }
-  inline bool previous (hb_codepoint_t *codepoint) const
-  {
-    if (unlikely (*codepoint == INVALID)) {
-      *codepoint = get_max ();
-      return *codepoint != INVALID;
-    }
-
-    page_map_t map = {get_major (*codepoint), 0};
-    unsigned int i;
-    page_map.bfind (map, &i);
-    if (i < page_map.len && page_map[i].major == map.major)
-    {
-      if (pages[page_map[i].index].previous (codepoint))
-      {
-        *codepoint += page_map[i].major * page_t::PAGE_BITS;
-        return true;
-      }
-    }
-    i--;
-    for (; (int) i >= 0; i--)
-    {
-      hb_codepoint_t m = pages[page_map[i].index].get_max ();
-      if (m != INVALID)
-      {
-        *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
-        return true;
-      }
-    }
-    *codepoint = INVALID;
-    return false;
-  }
-  inline bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
-  {
-    hb_codepoint_t i;
-
-    i = *last;
-    if (!next (&i))
-    {
-      *last = *first = INVALID;
-      return false;
-    }
-
-    /* TODO Speed up. */
-    *last = *first = i;
-    while (next (&i) && i == *last + 1)
-      (*last)++;
-
-    return true;
-  }
-  inline bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
-  {
-    hb_codepoint_t i;
-
-    i = *first;
-    if (!previous (&i))
-    {
-      *last = *first = INVALID;
-      return false;
-    }
-
-    /* TODO Speed up. */
-    *last = *first = i;
-    while (previous (&i) && i == *first - 1)
-      (*first)--;
-
-    return true;
-  }
-
-  inline unsigned int get_population (void) const
-  {
-    if (population != (unsigned int) -1)
-      return population;
-
-    unsigned int pop = 0;
-    unsigned int count = pages.len;
-    for (unsigned int i = 0; i < count; i++)
-      pop += pages[i].get_population ();
-
-    population = pop;
-    return pop;
-  }
-  inline hb_codepoint_t get_min (void) const
-  {
-    unsigned int count = pages.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!page_at (i).is_empty ())
-        return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_min ();
-    return INVALID;
-  }
-  inline hb_codepoint_t get_max (void) const
-  {
-    unsigned int count = pages.len;
-    for (int i = count - 1; i >= 0; i++)
-      if (!page_at (i).is_empty ())
-        return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_max ();
-    return INVALID;
-  }
-
-  static  const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
-
-  inline page_t *page_for_insert (hb_codepoint_t g)
-  {
-    page_map_t map = {get_major (g), pages.len};
-    unsigned int i;
-    if (!page_map.bfind (map, &i))
-    {
-      if (!resize (pages.len + 1))
-        return nullptr;
-
-      pages[map.index].init0 ();
-      memmove (&page_map[i + 1], &page_map[i], (page_map.len - 1 - i) * sizeof (page_map[0]));
-      page_map[i] = map;
-    }
-    return &pages[page_map[i].index];
-  }
-  inline page_t *page_for (hb_codepoint_t g)
-  {
-    page_map_t key = {get_major (g)};
-    const page_map_t *found = page_map.bsearch (key);
-    if (found)
-      return &pages[found->index];
-    return nullptr;
-  }
-  inline const page_t *page_for (hb_codepoint_t g) const
-  {
-    page_map_t key = {get_major (g)};
-    const page_map_t *found = page_map.bsearch (key);
-    if (found)
-      return &pages[found->index];
-    return nullptr;
-  }
-  inline page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
-  inline const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
-  inline unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
-  inline hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
-};
-
-
-#endif /* HB_SET_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,10 +24,19 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-set-private.hh"
+#include "hb-set.hh"
 
 
-/* Public API */
+/**
+ * SECTION:hb-set
+ * @title: hb-set
+ * @short_description: Object representing a set of integers
+ * @include: hb.h
+ *
+ * Set objects represent a mathematical set of integer values.  They are
+ * used in non-shaping API to query certain set of characters or glyphs,
+ * or other integer values.
+ **/
 
 
 /**
@@ -38,7 +47,7 @@
  * Since: 0.9.2
  **/
 hb_set_t *
-hb_set_create (void)
+hb_set_create ()
 {
   hb_set_t *set;
 
@@ -58,7 +67,7 @@
  * Since: 0.9.2
  **/
 hb_set_t *
-hb_set_get_empty (void)
+hb_set_get_empty ()
 {
   return const_cast<hb_set_t *> (&Null(hb_set_t));
 }
@@ -391,7 +400,7 @@
  * Deprecated: 1.6.1
  **/
 void
-hb_set_invert (hb_set_t *set)
+hb_set_invert (hb_set_t *set HB_UNUSED)
 {
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,738 @@
+/*
+ * Copyright © 2012,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_SET_HH
+#define HB_SET_HH
+
+#include "hb.hh"
+
+
+/*
+ * hb_set_t
+ */
+
+/* TODO Keep a free-list so we can free pages that are completely zeroed.  At that
+ * point maybe also use a sentinel value for "all-1" pages? */
+
+struct hb_set_t
+{
+  HB_NO_COPY_ASSIGN (hb_set_t);
+  hb_set_t ()  { init (); }
+  ~hb_set_t () { fini (); }
+
+  struct page_map_t
+  {
+    int cmp (const page_map_t &o) const { return (int) o.major - (int) major; }
+
+    uint32_t major;
+    uint32_t index;
+  };
+
+  struct page_t
+  {
+    void init0 () { v.clear (); }
+    void init1 () { v.clear (0xFF); }
+
+    unsigned int len () const
+    { return ARRAY_LENGTH_CONST (v); }
+
+    bool is_empty () const
+    {
+      for (unsigned int i = 0; i < len (); i++)
+        if (v[i])
+          return false;
+      return true;
+    }
+
+    void add (hb_codepoint_t g) { elt (g) |= mask (g); }
+    void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
+    bool has (hb_codepoint_t g) const { return !!(elt (g) & mask (g)); }
+
+    void add_range (hb_codepoint_t a, hb_codepoint_t b)
+    {
+      elt_t *la = &elt (a);
+      elt_t *lb = &elt (b);
+      if (la == lb)
+        *la |= (mask (b) << 1) - mask(a);
+      else
+      {
+        *la |= ~(mask (a) - 1);
+        la++;
+
+        memset (la, 0xff, (char *) lb - (char *) la);
+
+        *lb |= ((mask (b) << 1) - 1);
+      }
+    }
+
+    bool is_equal (const page_t *other) const
+    {
+      return 0 == hb_memcmp (&v, &other->v, sizeof (v));
+    }
+
+    unsigned int get_population () const
+    {
+      unsigned int pop = 0;
+      for (unsigned int i = 0; i < len (); i++)
+        pop += hb_popcount (v[i]);
+      return pop;
+    }
+
+    bool next (hb_codepoint_t *codepoint) const
+    {
+      unsigned int m = (*codepoint + 1) & MASK;
+      if (!m)
+      {
+        *codepoint = INVALID;
+        return false;
+      }
+      unsigned int i = m / ELT_BITS;
+      unsigned int j = m & ELT_MASK;
+
+      const elt_t vv = v[i] & ~((elt_t (1) << j) - 1);
+      for (const elt_t *p = &vv; i < len (); p = &v[++i])
+        if (*p)
+        {
+          *codepoint = i * ELT_BITS + elt_get_min (*p);
+          return true;
+        }
+
+      *codepoint = INVALID;
+      return false;
+    }
+    bool previous (hb_codepoint_t *codepoint) const
+    {
+      unsigned int m = (*codepoint - 1) & MASK;
+      if (m == MASK)
+      {
+        *codepoint = INVALID;
+        return false;
+      }
+      unsigned int i = m / ELT_BITS;
+      unsigned int j = m & ELT_MASK;
+
+      const elt_t vv = v[i] & ((elt_t (1) << (j + 1)) - 1);
+      for (const elt_t *p = &vv; (int) i >= 0; p = &v[--i])
+        if (*p)
+        {
+          *codepoint = i * ELT_BITS + elt_get_max (*p);
+          return true;
+        }
+
+      *codepoint = INVALID;
+      return false;
+    }
+    hb_codepoint_t get_min () const
+    {
+      for (unsigned int i = 0; i < len (); i++)
+        if (v[i])
+          return i * ELT_BITS + elt_get_min (v[i]);
+      return INVALID;
+    }
+    hb_codepoint_t get_max () const
+    {
+      for (int i = len () - 1; i >= 0; i--)
+        if (v[i])
+          return i * ELT_BITS + elt_get_max (v[i]);
+      return 0;
+    }
+
+    typedef unsigned long long elt_t;
+    static constexpr unsigned PAGE_BITS = 512;
+    static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
+
+    static unsigned int elt_get_min (const elt_t &elt) { return hb_ctz (elt); }
+    static unsigned int elt_get_max (const elt_t &elt) { return hb_bit_storage (elt) - 1; }
+
+    typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
+
+    static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8;
+    static constexpr unsigned ELT_MASK = ELT_BITS - 1;
+    static constexpr unsigned BITS = sizeof (vector_t) * 8;
+    static constexpr unsigned MASK = BITS - 1;
+    static_assert ((unsigned) PAGE_BITS == (unsigned) BITS, "");
+
+    elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; }
+    elt_t const &elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }
+    elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & ELT_MASK); }
+
+    vector_t v;
+  };
+  static_assert (page_t::PAGE_BITS == sizeof (page_t) * 8, "");
+
+  hb_object_header_t header;
+  bool successful; /* Allocations successful */
+  mutable unsigned int population;
+  hb_vector_t<page_map_t> page_map;
+  hb_vector_t<page_t> pages;
+
+  void init_shallow ()
+  {
+    successful = true;
+    population = 0;
+    page_map.init ();
+    pages.init ();
+  }
+  void init ()
+  {
+    hb_object_init (this);
+    init_shallow ();
+  }
+  void fini_shallow ()
+  {
+    population = 0;
+    page_map.fini ();
+    pages.fini ();
+  }
+  void fini ()
+  {
+    hb_object_fini (this);
+    fini_shallow ();
+  }
+
+  bool in_error () const { return !successful; }
+
+  bool resize (unsigned int count)
+  {
+    if (unlikely (!successful)) return false;
+    if (!pages.resize (count) || !page_map.resize (count))
+    {
+      pages.resize (page_map.length);
+      successful = false;
+      return false;
+    }
+    return true;
+  }
+
+  void clear ()
+  {
+    if (unlikely (hb_object_is_immutable (this)))
+      return;
+    successful = true;
+    population = 0;
+    page_map.resize (0);
+    pages.resize (0);
+  }
+  bool is_empty () const
+  {
+    unsigned int count = pages.length;
+    for (unsigned int i = 0; i < count; i++)
+      if (!pages[i].is_empty ())
+        return false;
+    return true;
+  }
+
+  void dirty () { population = (unsigned int) -1; }
+
+  void add (hb_codepoint_t g)
+  {
+    if (unlikely (!successful)) return;
+    if (unlikely (g == INVALID)) return;
+    dirty ();
+    page_t *page = page_for_insert (g); if (unlikely (!page)) return;
+    page->add (g);
+  }
+  bool add_range (hb_codepoint_t a, hb_codepoint_t b)
+  {
+    if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
+    if (unlikely (a > b || a == INVALID || b == INVALID)) return false;
+    dirty ();
+    unsigned int ma = get_major (a);
+    unsigned int mb = get_major (b);
+    if (ma == mb)
+    {
+      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
+      page->add_range (a, b);
+    }
+    else
+    {
+      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
+      page->add_range (a, major_start (ma + 1) - 1);
+
+      for (unsigned int m = ma + 1; m < mb; m++)
+      {
+        page = page_for_insert (major_start (m)); if (unlikely (!page)) return false;
+        page->init1 ();
+      }
+
+      page = page_for_insert (b); if (unlikely (!page)) return false;
+      page->add_range (major_start (mb), b);
+    }
+    return true;
+  }
+
+  template <typename T>
+  void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    if (unlikely (!successful)) return;
+    if (!count) return;
+    dirty ();
+    hb_codepoint_t g = *array;
+    while (count)
+    {
+      unsigned int m = get_major (g);
+      page_t *page = page_for_insert (g); if (unlikely (!page)) return;
+      unsigned int start = major_start (m);
+      unsigned int end = major_start (m + 1);
+      do
+      {
+        page->add (g);
+
+        array = (const T *) ((const char *) array + stride);
+        count--;
+      }
+      while (count && (g = *array, start <= g && g < end));
+    }
+  }
+
+  /* Might return false if array looks unsorted.
+   * Used for faster rejection of corrupt data. */
+  template <typename T>
+  bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
+    if (!count) return true;
+    dirty ();
+    hb_codepoint_t g = *array;
+    hb_codepoint_t last_g = g;
+    while (count)
+    {
+      unsigned int m = get_major (g);
+      page_t *page = page_for_insert (g); if (unlikely (!page)) return false;
+      unsigned int end = major_start (m + 1);
+      do
+      {
+        /* If we try harder we can change the following comparison to <=;
+         * Not sure if it's worth it. */
+        if (g < last_g) return false;
+        last_g = g;
+        page->add (g);
+
+        array = (const T *) ((const char *) array + stride);
+        count--;
+      }
+      while (count && (g = *array, g < end));
+    }
+    return true;
+  }
+
+  void del (hb_codepoint_t g)
+  {
+    /* TODO perform op even if !successful. */
+    if (unlikely (!successful)) return;
+    page_t *page = page_for (g);
+    if (!page)
+      return;
+    dirty ();
+    page->del (g);
+  }
+  void del_range (hb_codepoint_t a, hb_codepoint_t b)
+  {
+    /* TODO perform op even if !successful. */
+    /* TODO Optimize, like add_range(). */
+    if (unlikely (!successful)) return;
+    for (unsigned int i = a; i < b + 1; i++)
+      del (i);
+  }
+  bool has (hb_codepoint_t g) const
+  {
+    const page_t *page = page_for (g);
+    if (!page)
+      return false;
+    return page->has (g);
+  }
+  bool intersects (hb_codepoint_t first,
+                          hb_codepoint_t last) const
+  {
+    hb_codepoint_t c = first - 1;
+    return next (&c) && c <= last;
+  }
+  void set (const hb_set_t *other)
+  {
+    if (unlikely (!successful)) return;
+    unsigned int count = other->pages.length;
+    if (!resize (count))
+      return;
+    population = other->population;
+    memcpy ((void *) pages, (const void *) other->pages, count * pages.item_size);
+    memcpy ((void *) page_map, (const void *) other->page_map, count * page_map.item_size);
+  }
+
+  bool is_equal (const hb_set_t *other) const
+  {
+    if (get_population () != other->get_population ())
+      return false;
+
+    unsigned int na = pages.length;
+    unsigned int nb = other->pages.length;
+
+    unsigned int a = 0, b = 0;
+    for (; a < na && b < nb; )
+    {
+      if (page_at (a).is_empty ()) { a++; continue; }
+      if (other->page_at (b).is_empty ()) { b++; continue; }
+      if (page_map[a].major != other->page_map[b].major ||
+          !page_at (a).is_equal (&other->page_at (b)))
+        return false;
+      a++;
+      b++;
+    }
+    for (; a < na; a++)
+      if (!page_at (a).is_empty ()) { return false; }
+    for (; b < nb; b++)
+      if (!other->page_at (b).is_empty ()) { return false; }
+
+    return true;
+  }
+
+  bool is_subset (const hb_set_t *larger_set) const
+  {
+    if (get_population () > larger_set->get_population ())
+      return false;
+
+    /* TODO Optimize to use pages. */
+    hb_codepoint_t c = INVALID;
+    while (next (&c))
+      if (!larger_set->has (c))
+        return false;
+
+    return true;
+  }
+
+  template <class Op>
+  void process (const hb_set_t *other)
+  {
+    if (unlikely (!successful)) return;
+
+    dirty ();
+
+    unsigned int na = pages.length;
+    unsigned int nb = other->pages.length;
+    unsigned int next_page = na;
+
+    unsigned int count = 0, newCount = 0;
+    unsigned int a = 0, b = 0;
+    for (; a < na && b < nb; )
+    {
+      if (page_map[a].major == other->page_map[b].major)
+      {
+        count++;
+        a++;
+        b++;
+      }
+      else if (page_map[a].major < other->page_map[b].major)
+      {
+        if (Op::passthru_left)
+          count++;
+        a++;
+      }
+      else
+      {
+        if (Op::passthru_right)
+          count++;
+        b++;
+      }
+    }
+    if (Op::passthru_left)
+      count += na - a;
+    if (Op::passthru_right)
+      count += nb - b;
+
+    if (count > pages.length)
+      if (!resize (count))
+        return;
+    newCount = count;
+
+    /* Process in-place backward. */
+    a = na;
+    b = nb;
+    for (; a && b; )
+    {
+      if (page_map[a - 1].major == other->page_map[b - 1].major)
+      {
+        a--;
+        b--;
+        count--;
+        page_map[count] = page_map[a];
+        Op::process (page_at (count).v, page_at (a).v, other->page_at (b).v);
+      }
+      else if (page_map[a - 1].major > other->page_map[b - 1].major)
+      {
+        a--;
+        if (Op::passthru_left)
+        {
+          count--;
+          page_map[count] = page_map[a];
+        }
+      }
+      else
+      {
+        b--;
+        if (Op::passthru_right)
+        {
+          count--;
+          page_map[count].major = other->page_map[b].major;
+          page_map[count].index = next_page++;
+          page_at (count).v = other->page_at (b).v;
+        }
+      }
+    }
+    if (Op::passthru_left)
+      while (a)
+      {
+        a--;
+        count--;
+        page_map[count] = page_map [a];
+      }
+    if (Op::passthru_right)
+      while (b)
+      {
+        b--;
+        count--;
+        page_map[count].major = other->page_map[b].major;
+        page_map[count].index = next_page++;
+        page_at (count).v = other->page_at (b).v;
+      }
+    assert (!count);
+    if (pages.length > newCount)
+      resize (newCount);
+  }
+
+  void union_ (const hb_set_t *other)
+  {
+    process<HbOpOr> (other);
+  }
+  void intersect (const hb_set_t *other)
+  {
+    process<HbOpAnd> (other);
+  }
+  void subtract (const hb_set_t *other)
+  {
+    process<HbOpMinus> (other);
+  }
+  void symmetric_difference (const hb_set_t *other)
+  {
+    process<HbOpXor> (other);
+  }
+  bool next (hb_codepoint_t *codepoint) const
+  {
+    if (unlikely (*codepoint == INVALID)) {
+      *codepoint = get_min ();
+      return *codepoint != INVALID;
+    }
+
+    page_map_t map = {get_major (*codepoint), 0};
+    unsigned int i;
+    page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST);
+    if (i < page_map.length && page_map[i].major == map.major)
+    {
+      if (pages[page_map[i].index].next (codepoint))
+      {
+        *codepoint += page_map[i].major * page_t::PAGE_BITS;
+        return true;
+      }
+      i++;
+    }
+    for (; i < page_map.length; i++)
+    {
+      hb_codepoint_t m = pages[page_map[i].index].get_min ();
+      if (m != INVALID)
+      {
+        *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
+        return true;
+      }
+    }
+    *codepoint = INVALID;
+    return false;
+  }
+  bool previous (hb_codepoint_t *codepoint) const
+  {
+    if (unlikely (*codepoint == INVALID)) {
+      *codepoint = get_max ();
+      return *codepoint != INVALID;
+    }
+
+    page_map_t map = {get_major (*codepoint), 0};
+    unsigned int i;
+    page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST);
+    if (i < page_map.length && page_map[i].major == map.major)
+    {
+      if (pages[page_map[i].index].previous (codepoint))
+      {
+        *codepoint += page_map[i].major * page_t::PAGE_BITS;
+        return true;
+      }
+    }
+    i--;
+    for (; (int) i >= 0; i--)
+    {
+      hb_codepoint_t m = pages[page_map[i].index].get_max ();
+      if (m != INVALID)
+      {
+        *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
+        return true;
+      }
+    }
+    *codepoint = INVALID;
+    return false;
+  }
+  bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
+  {
+    hb_codepoint_t i;
+
+    i = *last;
+    if (!next (&i))
+    {
+      *last = *first = INVALID;
+      return false;
+    }
+
+    /* TODO Speed up. */
+    *last = *first = i;
+    while (next (&i) && i == *last + 1)
+      (*last)++;
+
+    return true;
+  }
+  bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
+  {
+    hb_codepoint_t i;
+
+    i = *first;
+    if (!previous (&i))
+    {
+      *last = *first = INVALID;
+      return false;
+    }
+
+    /* TODO Speed up. */
+    *last = *first = i;
+    while (previous (&i) && i == *first - 1)
+      (*first)--;
+
+    return true;
+  }
+
+  unsigned int get_population () const
+  {
+    if (population != (unsigned int) -1)
+      return population;
+
+    unsigned int pop = 0;
+    unsigned int count = pages.length;
+    for (unsigned int i = 0; i < count; i++)
+      pop += pages[i].get_population ();
+
+    population = pop;
+    return pop;
+  }
+  hb_codepoint_t get_min () const
+  {
+    unsigned int count = pages.length;
+    for (unsigned int i = 0; i < count; i++)
+      if (!page_at (i).is_empty ())
+        return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_min ();
+    return INVALID;
+  }
+  hb_codepoint_t get_max () const
+  {
+    unsigned int count = pages.length;
+    for (int i = count - 1; i >= 0; i++)
+      if (!page_at (i).is_empty ())
+        return page_map[(unsigned) i].major * page_t::PAGE_BITS + page_at (i).get_max ();
+    return INVALID;
+  }
+
+  static constexpr hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
+
+  /*
+   * Iterator implementation.
+   */
+  struct const_iter_t : hb_sorted_iter_t<const_iter_t, const hb_codepoint_t>
+  {
+    const_iter_t (const hb_set_t &s_) :
+      s (s_), v (INVALID), l (s.get_population () + 1) { __next__ (); }
+
+    typedef hb_codepoint_t __item_type__;
+    hb_codepoint_t __item__ () const { return v; }
+    bool __more__ () const { return v != INVALID; }
+    void __next__ () { s.next (&v); if (l) l--; }
+    void __prev__ () { s.previous (&v); }
+    unsigned __len__ () { return l; }
+
+    protected:
+    const hb_set_t &s;
+    hb_codepoint_t v;
+    unsigned l;
+  };
+  const_iter_t const_iter () const { return const_iter_t (*this); }
+  operator const_iter_t () const { return const_iter (); }
+  typedef const_iter_t iter_t;
+  iter_t iter () const { return const_iter (); }
+
+  protected:
+
+  page_t *page_for_insert (hb_codepoint_t g)
+  {
+    page_map_t map = {get_major (g), pages.length};
+    unsigned int i;
+    if (!page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST))
+    {
+      if (!resize (pages.length + 1))
+        return nullptr;
+
+      pages[map.index].init0 ();
+      memmove (page_map + i + 1,
+               page_map + i,
+               (page_map.length - 1 - i) * page_map.item_size);
+      page_map[i] = map;
+    }
+    return &pages[page_map[i].index];
+  }
+  page_t *page_for (hb_codepoint_t g)
+  {
+    page_map_t key = {get_major (g)};
+    const page_map_t *found = page_map.bsearch (key);
+    if (found)
+      return &pages[found->index];
+    return nullptr;
+  }
+  const page_t *page_for (hb_codepoint_t g) const
+  {
+    page_map_t key = {get_major (g)};
+    const page_map_t *found = page_map.bsearch (key);
+    if (found)
+      return &pages[found->index];
+    return nullptr;
+  }
+  page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
+  const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
+  unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
+  hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
+};
+
+
+#endif /* HB_SET_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape-plan-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright © 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SHAPE_PLAN_PRIVATE_HH
-#define HB_SHAPE_PLAN_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-#include "hb-shaper-private.hh"
-
-
-struct hb_shape_plan_t
-{
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t default_shaper_list;
-  hb_face_t *face_unsafe; /* We don't carry a reference to face. */
-  hb_segment_properties_t props;
-
-  hb_shape_func_t *shaper_func;
-  const char *shaper_name;
-
-  hb_feature_t *user_features;
-  unsigned int num_user_features;
-
-  int *coords;
-  unsigned int num_coords;
-
-  struct hb_shaper_data_t shaper_data;
-};
-
-#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \
-        , const hb_feature_t *user_features \
-        , unsigned int        num_user_features \
-        , const int          *coords \
-        , unsigned int        num_coords
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, shape_plan);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-
-
-#endif /* HB_SHAPE_PLAN_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape-plan.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape-plan.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,55 +24,81 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-shape-plan-private.hh"
-#include "hb-shaper-private.hh"
-#include "hb-font-private.hh"
-#include "hb-buffer-private.hh"
+#include "hb.hh"
+#include "hb-shape-plan.hh"
+#include "hb-shaper.hh"
+#include "hb-font.hh"
+#include "hb-buffer.hh"
+
+
+/**
+ * SECTION:hb-shape-plan
+ * @title: hb-shape-plan
+ * @short_description: Object representing a shaping plan
+ * @include: hb.h
+ *
+ * Shape plans are not used for shaping directly, but can be access to query
+ * certain information about how shaping will perform given a set of input
+ * parameters (script, language, direction, features, etc.)
+ * Most client would not need to deal with shape plans directly.
+ **/
 
 
-static void
-hb_shape_plan_plan (hb_shape_plan_t    *shape_plan,
-                    const hb_feature_t *user_features,
-                    unsigned int        num_user_features,
-                    const int          *coords,
-                    unsigned int        num_coords,
-                    const char * const *shaper_list)
+/*
+ * hb_shape_plan_key_t
+ */
+
+bool
+hb_shape_plan_key_t::init (bool                           copy,
+                           hb_face_t                     *face,
+                           const hb_segment_properties_t *props,
+                           const hb_feature_t            *user_features,
+                           unsigned int                   num_user_features,
+                           const int                     *coords,
+                           unsigned int                   num_coords,
+                           const char * const            *shaper_list)
 {
-  DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
-                  "num_features=%d num_coords=%d shaper_list=%p",
-                  num_user_features,
-                  num_coords,
-                  shaper_list);
+  hb_feature_t *features = nullptr;
+  if (copy && num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t))))
+    goto bail;
 
-  const hb_shaper_pair_t *shapers = _hb_shapers_get ();
+  this->props = *props;
+  this->num_user_features = num_user_features;
+  this->user_features = copy ? features : user_features;
+  if (copy && num_user_features)
+  {
+    memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
+    /* Make start/end uniform to easier catch bugs. */
+    for (unsigned int i = 0; i < num_user_features; i++)
+    {
+      if (features[0].start != HB_FEATURE_GLOBAL_START)
+        features[0].start = 1;
+      if (features[0].end   != HB_FEATURE_GLOBAL_END)
+        features[0].end   = 2;
+    }
+  }
+  this->shaper_func = nullptr;
+  this->shaper_name = nullptr;
+  this->ot.init (face, coords, num_coords);
+
+  /*
+   * Choose shaper.
+   */
 
 #define HB_SHAPER_PLAN(shaper) \
         HB_STMT_START { \
-          if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) { \
-            HB_SHAPER_DATA (shaper, shape_plan) = \
-              HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, \
-                                                               user_features, num_user_features, \
-                                                               coords, num_coords); \
-            shape_plan->shaper_func = _hb_##shaper##_shape; \
-            shape_plan->shaper_name = #shaper; \
-            return; \
+          if (face->data.shaper) \
+          { \
+            this->shaper_func = _hb_##shaper##_shape; \
+            this->shaper_name = #shaper; \
+            return true; \
           } \
         } HB_STMT_END
 
-  if (likely (!shaper_list)) {
-    for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
-      if (0)
-        ;
-#define HB_SHAPER_IMPLEMENT(shaper) \
-      else if (shapers[i].func == _hb_##shaper##_shape) \
-        HB_SHAPER_PLAN (shaper);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-  } else {
+  if (unlikely (shaper_list))
+  {
     for (; *shaper_list; shaper_list++)
-      if (0)
+      if (false)
         ;
 #define HB_SHAPER_IMPLEMENT(shaper) \
       else if (0 == strcmp (*shaper_list, #shaper)) \
@@ -80,8 +106,50 @@
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
   }
+  else
+  {
+    const hb_shaper_entry_t *shapers = _hb_shapers_get ();
+    for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
+      if (false)
+        ;
+#define HB_SHAPER_IMPLEMENT(shaper) \
+      else if (shapers[i].func == _hb_##shaper##_shape) \
+        HB_SHAPER_PLAN (shaper);
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  }
+#undef HB_SHAPER_PLAN
 
-#undef HB_SHAPER_PLAN
+bail:
+  ::free (features);
+  return false;
+}
+
+bool
+hb_shape_plan_key_t::user_features_match (const hb_shape_plan_key_t *other)
+{
+  if (this->num_user_features != other->num_user_features)
+    return false;
+  for (unsigned int i = 0; i < num_user_features; i++)
+  {
+    if (this->user_features[i].tag   != other->user_features[i].tag   ||
+        this->user_features[i].value != other->user_features[i].value ||
+        (this->user_features[i].start == HB_FEATURE_GLOBAL_START &&
+         this->user_features[i].end   == HB_FEATURE_GLOBAL_END) !=
+        (other->user_features[i].start == HB_FEATURE_GLOBAL_START &&
+         other->user_features[i].end   == HB_FEATURE_GLOBAL_END))
+      return false;
+  }
+  return true;
+}
+
+bool
+hb_shape_plan_key_t::equal (const hb_shape_plan_key_t *other)
+{
+  return hb_segment_properties_equal (&this->props, &other->props) &&
+         this->user_features_match (other) &&
+         this->ot.equal (&other->ot) &&
+         this->shaper_func == other->shaper_func;
 }
 
 
@@ -89,6 +157,7 @@
  * hb_shape_plan_t
  */
 
+
 /**
  * hb_shape_plan_create: (Xconstructor)
  * @face:
@@ -121,7 +190,7 @@
                        const hb_segment_properties_t *props,
                        const hb_feature_t            *user_features,
                        unsigned int                   num_user_features,
-                       const int                     *orig_coords,
+                       const int                     *coords,
                        unsigned int                   num_coords,
                        const char * const            *shaper_list)
 {
@@ -132,49 +201,40 @@
                   num_coords,
                   shaper_list);
 
+  assert (props->direction != HB_DIRECTION_INVALID);
+
   hb_shape_plan_t *shape_plan;
-  hb_feature_t *features = nullptr;
-  int *coords = nullptr;
+
+  if (unlikely (!props))
+    goto bail;
+  if (!(shape_plan = hb_object_create<hb_shape_plan_t> ()))
+    goto bail;
 
   if (unlikely (!face))
     face = hb_face_get_empty ();
-  if (unlikely (!props))
-    return hb_shape_plan_get_empty ();
-  if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t))))
-    return hb_shape_plan_get_empty ();
-  if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int))))
-  {
-    free (features);
-    return hb_shape_plan_get_empty ();
-  }
-  if (!(shape_plan = hb_object_create<hb_shape_plan_t> ()))
-  {
-    free (coords);
-    free (features);
-    return hb_shape_plan_get_empty ();
-  }
-
-  assert (props->direction != HB_DIRECTION_INVALID);
+  hb_face_make_immutable (face);
+  shape_plan->face_unsafe = face;
 
-  hb_face_make_immutable (face);
-  shape_plan->default_shaper_list = !shaper_list;
-  shape_plan->face_unsafe = face;
-  shape_plan->props = *props;
-  shape_plan->num_user_features = num_user_features;
-  shape_plan->user_features = features;
-  if (num_user_features)
-    memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
-  shape_plan->num_coords = num_coords;
-  shape_plan->coords = coords;
-  if (num_coords)
-    memcpy (coords, orig_coords, num_coords * sizeof (int));
-
-  hb_shape_plan_plan (shape_plan,
-                      user_features, num_user_features,
-                      coords, num_coords,
-                      shaper_list);
+  if (unlikely (!shape_plan->key.init (true,
+                                       face,
+                                       props,
+                                       user_features,
+                                       num_user_features,
+                                       coords,
+                                       num_coords,
+                                       shaper_list)))
+    goto bail2;
+  if (unlikely (!shape_plan->ot.init0 (face, &shape_plan->key)))
+    goto bail3;
 
   return shape_plan;
+
+bail3:
+  shape_plan->key.free ();
+bail2:
+  free (shape_plan);
+bail:
+  return hb_shape_plan_get_empty ();
 }
 
 /**
@@ -187,32 +247,9 @@
  * Since: 0.9.7
  **/
 hb_shape_plan_t *
-hb_shape_plan_get_empty (void)
+hb_shape_plan_get_empty ()
 {
-  static const hb_shape_plan_t _hb_shape_plan_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* default_shaper_list */
-    nullptr, /* face */
-    HB_SEGMENT_PROPERTIES_DEFAULT, /* props */
-
-    nullptr, /* shaper_func */
-    nullptr, /* shaper_name */
-
-    nullptr, /* user_features */
-    0,    /* num_user_featurs */
-
-    nullptr, /* coords */
-    0,    /* num_coords */
-
-    {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-    }
-  };
-
-  return const_cast<hb_shape_plan_t *> (&_hb_shape_plan_nil);
+  return const_cast<hb_shape_plan_t *> (&Null(hb_shape_plan_t));
 }
 
 /**
@@ -244,13 +281,8 @@
 {
   if (!hb_object_destroy (shape_plan)) return;
 
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, shape_plan);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-  free (shape_plan->user_features);
-  free (shape_plan->coords);
-
+  shape_plan->ot.fini ();
+  shape_plan->key.free ();
   free (shape_plan);
 }
 
@@ -296,6 +328,22 @@
   return hb_object_get_user_data (shape_plan, key);
 }
 
+/**
+ * hb_shape_plan_get_shaper:
+ * @shape_plan: a shape plan.
+ *
+ *
+ *
+ * Return value: (transfer none):
+ *
+ * Since: 0.9.7
+ **/
+const char *
+hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan)
+{
+  return shape_plan->key.shaper_name;
+}
+
 
 /**
  * hb_shape_plan_execute:
@@ -321,32 +369,31 @@
   DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
                   "num_features=%d shaper_func=%p, shaper_name=%s",
                   num_features,
-                  shape_plan->shaper_func,
-                  shape_plan->shaper_name);
+                  shape_plan->key.shaper_func,
+                  shape_plan->key.shaper_name);
 
   if (unlikely (!buffer->len))
     return true;
 
-  assert (!hb_object_is_inert (buffer));
+  assert (!hb_object_is_immutable (buffer));
   assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
 
   if (unlikely (hb_object_is_inert (shape_plan)))
     return false;
 
   assert (shape_plan->face_unsafe == font->face);
-  assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props));
+  assert (hb_segment_properties_equal (&shape_plan->key.props, &buffer->props));
 
 #define HB_SHAPER_EXECUTE(shaper) \
         HB_STMT_START { \
-          return HB_SHAPER_DATA (shaper, shape_plan) && \
-                 hb_##shaper##_shaper_font_data_ensure (font) && \
+          return font->data.shaper && \
                  _hb_##shaper##_shape (shape_plan, font, buffer, features, num_features); \
         } HB_STMT_END
 
-  if (0)
+  if (false)
     ;
 #define HB_SHAPER_IMPLEMENT(shaper) \
-  else if (shape_plan->shaper_func == _hb_##shaper##_shape) \
+  else if (shape_plan->key.shaper_func == _hb_##shaper##_shape) \
     HB_SHAPER_EXECUTE (shaper);
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
@@ -358,91 +405,8 @@
 
 
 /*
- * caching
- */
-
-#if 0
-static unsigned int
-hb_shape_plan_hash (const hb_shape_plan_t *shape_plan)
-{
-  return hb_segment_properties_hash (&shape_plan->props) +
-         shape_plan->default_shaper_list ? 0 : (intptr_t) shape_plan->shaper_func;
-}
-#endif
-
-/* User-feature caching is currently somewhat dumb:
- * it only finds matches where the feature array is identical,
- * not cases where the feature lists would be compatible for plan purposes
- * but have different ranges, for example.
+ * Caching
  */
-struct hb_shape_plan_proposal_t
-{
-  const hb_segment_properties_t  props;
-  const char * const            *shaper_list;
-  const hb_feature_t            *user_features;
-  unsigned int                   num_user_features;
-  const int                     *coords;
-  unsigned int                   num_coords;
-  hb_shape_func_t               *shaper_func;
-};
-
-static inline hb_bool_t
-hb_shape_plan_user_features_match (const hb_shape_plan_t          *shape_plan,
-                                   const hb_shape_plan_proposal_t *proposal)
-{
-  if (proposal->num_user_features != shape_plan->num_user_features)
-    return false;
-  for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++)
-    if (proposal->user_features[i].tag   != shape_plan->user_features[i].tag   ||
-        proposal->user_features[i].value != shape_plan->user_features[i].value ||
-        proposal->user_features[i].start != shape_plan->user_features[i].start ||
-        proposal->user_features[i].end   != shape_plan->user_features[i].end)
-      return false;
-  return true;
-}
-
-static inline hb_bool_t
-hb_shape_plan_coords_match (const hb_shape_plan_t          *shape_plan,
-                            const hb_shape_plan_proposal_t *proposal)
-{
-  if (proposal->num_coords != shape_plan->num_coords)
-    return false;
-  for (unsigned int i = 0, n = proposal->num_coords; i < n; i++)
-    if (proposal->coords[i] != shape_plan->coords[i])
-      return false;
-  return true;
-}
-
-static hb_bool_t
-hb_shape_plan_matches (const hb_shape_plan_t          *shape_plan,
-                       const hb_shape_plan_proposal_t *proposal)
-{
-  return hb_segment_properties_equal (&shape_plan->props, &proposal->props) &&
-         hb_shape_plan_user_features_match (shape_plan, proposal) &&
-         hb_shape_plan_coords_match (shape_plan, proposal) &&
-         ((shape_plan->default_shaper_list && !proposal->shaper_list) ||
-          (shape_plan->shaper_func == proposal->shaper_func));
-}
-
-static inline hb_bool_t
-hb_non_global_user_features_present (const hb_feature_t *user_features,
-                                     unsigned int        num_user_features)
-{
-  while (num_user_features) {
-    if (user_features->start != 0 || user_features->end != (unsigned int) -1)
-      return true;
-    num_user_features--;
-    user_features++;
-  }
-  return false;
-}
-
-static inline hb_bool_t
-hb_coords_present (const int *coords,
-                   unsigned int num_coords)
-{
-  return num_coords != 0;
-}
 
 /**
  * hb_shape_plan_create_cached:
@@ -486,62 +450,38 @@
                   num_user_features,
                   shaper_list);
 
-  hb_shape_plan_proposal_t proposal = {
-    *props,
-    shaper_list,
-    user_features,
-    num_user_features,
-    nullptr
-  };
+retry:
+  hb_face_t::plan_node_t *cached_plan_nodes = face->shape_plans;
+
+  bool dont_cache = hb_object_is_inert (face);
 
-  if (shaper_list) {
-    /* Choose shaper.  Adapted from hb_shape_plan_plan().
-     * Must choose shaper exactly the same way as that function. */
-    for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_item++)
-      if (0)
-        ;
-#define HB_SHAPER_IMPLEMENT(shaper) \
-      else if (0 == strcmp (*shaper_item, #shaper) && \
-               hb_##shaper##_shaper_face_data_ensure (face)) \
-      { \
-        proposal.shaper_func = _hb_##shaper##_shape; \
-        break; \
-      }
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
+  if (likely (!dont_cache))
+  {
+    hb_shape_plan_key_t key;
+    if (!key.init (false,
+                   face,
+                   props,
+                   user_features,
+                   num_user_features,
+                   coords,
+                   num_coords,
+                   shaper_list))
+      return hb_shape_plan_get_empty ();
 
-    if (unlikely (!proposal.shaper_func))
-      return hb_shape_plan_get_empty ();
-  }
-
-
-retry:
-  hb_face_t::plan_node_t *cached_plan_nodes = (hb_face_t::plan_node_t *) hb_atomic_ptr_get (&face->shape_plans);
-
-  /* Don't look for plan in the cache if there were variation coordinates XXX Fix me. */
-  if (!hb_coords_present (coords, num_coords))
     for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next)
-      if (hb_shape_plan_matches (node->shape_plan, &proposal))
+      if (node->shape_plan->key.equal (&key))
       {
         DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache");
         return hb_shape_plan_reference (node->shape_plan);
       }
+  }
 
-  /* Not found. */
   hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props,
                                                        user_features, num_user_features,
                                                        coords, num_coords,
                                                        shaper_list);
 
-  /* Don't add to the cache if face is inert. */
-  if (unlikely (hb_object_is_inert (face)))
-    return shape_plan;
-
-  /* Don't add the plan to the cache if there were user features with non-global ranges */
-  if (hb_non_global_user_features_present (user_features, num_user_features))
-    return shape_plan;
-  /* Don't add the plan to the cache if there were variation coordinates XXX Fix me. */
-  if (hb_coords_present (coords, num_coords))
+  if (unlikely (dont_cache))
     return shape_plan;
 
   hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t));
@@ -551,7 +491,8 @@
   node->shape_plan = shape_plan;
   node->next = cached_plan_nodes;
 
-  if (!hb_atomic_ptr_cmpexch (&face->shape_plans, cached_plan_nodes, node)) {
+  if (unlikely (!face->shape_plans.cmpexch (cached_plan_nodes, node)))
+  {
     hb_shape_plan_destroy (shape_plan);
     free (node);
     goto retry;
@@ -560,19 +501,3 @@
 
   return hb_shape_plan_reference (shape_plan);
 }
-
-/**
- * hb_shape_plan_get_shaper:
- * @shape_plan: a shape plan.
- *
- *
- *
- * Return value: (transfer none):
- *
- * Since: 0.9.7
- **/
-const char *
-hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan)
-{
-  return shape_plan->shaper_name;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape-plan.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,72 @@
+/*
+ * Copyright © 2012,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_SHAPE_PLAN_HH
+#define HB_SHAPE_PLAN_HH
+
+#include "hb.hh"
+#include "hb-shaper.hh"
+#include "hb-ot-shape.hh"
+
+
+struct hb_shape_plan_key_t
+{
+  hb_segment_properties_t  props;
+
+  const hb_feature_t      *user_features;
+  unsigned int             num_user_features;
+
+  hb_ot_shape_plan_key_t   ot;
+
+  hb_shape_func_t         *shaper_func;
+  const char              *shaper_name;
+
+  HB_INTERNAL inline bool init (bool                           copy,
+                                hb_face_t                     *face,
+                                const hb_segment_properties_t *props,
+                                const hb_feature_t            *user_features,
+                                unsigned int                   num_user_features,
+                                const int                     *coords,
+                                unsigned int                   num_coords,
+                                const char * const            *shaper_list);
+
+  HB_INTERNAL inline void free () { ::free ((void *) user_features); }
+
+  HB_INTERNAL bool user_features_match (const hb_shape_plan_key_t *other);
+
+  HB_INTERNAL bool equal (const hb_shape_plan_key_t *other);
+};
+
+struct hb_shape_plan_t
+{
+  hb_object_header_t header;
+  hb_face_t *face_unsafe; /* We don't carry a reference to face. */
+  hb_shape_plan_key_t key;
+  hb_ot_shape_plan_t ot;
+};
+
+
+#endif /* HB_SHAPE_PLAN_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -26,40 +26,70 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-shaper-private.hh"
-#include "hb-shape-plan-private.hh"
-#include "hb-buffer-private.hh"
-#include "hb-font-private.hh"
+#include "hb-shaper.hh"
+#include "hb-shape-plan.hh"
+#include "hb-buffer.hh"
+#include "hb-font.hh"
+#include "hb-machinery.hh"
+
 
 /**
  * SECTION:hb-shape
- * @title: Shaping
+ * @title: hb-shape
  * @short_description: Conversion of text strings into positioned glyphs
  * @include: hb.h
  *
  * Shaping is the central operation of HarfBuzz. Shaping operates on buffers,
  * which are sequences of Unicode characters that use the same font and have
- * the same text direction, script and language. After shaping the buffer
+ * the same text direction, script, and language. After shaping the buffer
  * contains the output glyphs and their positions.
  **/
 
-static const char **static_shaper_list;
+
+#if HB_USE_ATEXIT
+static void free_static_shaper_list ();
+#endif
 
-#ifdef HB_USE_ATEXIT
-static
-void free_static_shaper_list (void)
+static const char *nil_shaper_list[] = {nullptr};
+
+static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
+                                                              hb_shaper_list_lazy_loader_t>
 {
-retry:
-  const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
-  if (!hb_atomic_ptr_cmpexch (&static_shaper_list, shaper_list, nullptr))
-    goto retry;
+  static const char ** create ()
+  {
+    const char **shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
+    if (unlikely (!shaper_list))
+      return nullptr;
+
+    const hb_shaper_entry_t *shapers = _hb_shapers_get ();
+    unsigned int i;
+    for (i = 0; i < HB_SHAPERS_COUNT; i++)
+      shaper_list[i] = shapers[i].name;
+    shaper_list[i] = nullptr;
 
-  free (shaper_list);
+#if HB_USE_ATEXIT
+    atexit (free_static_shaper_list);
+#endif
+
+    return shaper_list;
+  }
+  static void destroy (const char **l)
+  { free (l); }
+  static const char ** get_null ()
+  { return nil_shaper_list; }
+} static_shaper_list;
+
+#if HB_USE_ATEXIT
+static
+void free_static_shaper_list ()
+{
+  static_shaper_list.free_instance ();
 }
 #endif
 
+
 /**
  * hb_shape_list_shapers:
  *
@@ -71,37 +101,9 @@
  * Since: 0.9.2
  **/
 const char **
-hb_shape_list_shapers (void)
+hb_shape_list_shapers ()
 {
-retry:
-  const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
-
-  if (unlikely (!shaper_list))
-  {
-    /* Not found; allocate one. */
-    shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
-    if (unlikely (!shaper_list)) {
-      static const char *nil_shaper_list[] = {nullptr};
-      return nil_shaper_list;
-    }
-
-    const hb_shaper_pair_t *shapers = _hb_shapers_get ();
-    unsigned int i;
-    for (i = 0; i < HB_SHAPERS_COUNT; i++)
-      shaper_list[i] = shapers[i].name;
-    shaper_list[i] = nullptr;
-
-    if (!hb_atomic_ptr_cmpexch (&static_shaper_list, nullptr, shaper_list)) {
-      free (shaper_list);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_shaper_list); /* First person registers atexit() callback. */
-#endif
-  }
-
-  return shaper_list;
+  return static_shaper_list.get_unconst ();
 }
 
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-impl-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright © 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SHAPER_IMPL_PRIVATE_HH
-#define HB_SHAPER_IMPL_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-shaper-private.hh"
-#include "hb-shape-plan-private.hh"
-#include "hb-font-private.hh"
-#include "hb-buffer-private.hh"
-
-
-#ifdef HB_SHAPER
-#define HB_SHAPER_DATA_GET(object) HB_SHAPER_DATA (HB_SHAPER, object)
-#endif
-
-
-#endif /* HB_SHAPER_IMPL_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-impl.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SHAPER_IMPL_HH
+#define HB_SHAPER_IMPL_HH
+
+#include "hb.hh"
+
+#include "hb-shaper.hh"
+#include "hb-face.hh"
+#include "hb-font.hh"
+#include "hb-shape-plan.hh"
+#include "hb-buffer.hh"
+
+#endif /* HB_SHAPER_IMPL_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-list.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-list.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -34,14 +34,8 @@
 /* Only picks up fonts that have a "Silf" table. */
 HB_SHAPER_IMPLEMENT (graphite2)
 #endif
-#ifdef HAVE_CORETEXT
-/* Only picks up fonts that have a "mort" or "morx" table. */
-HB_SHAPER_IMPLEMENT (coretext_aat)
-#endif
 
-#ifdef HAVE_OT
 HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */
-#endif
 
 #ifdef HAVE_UNISCRIBE
 HB_SHAPER_IMPLEMENT (uniscribe)
@@ -51,6 +45,10 @@
 #endif
 #ifdef HAVE_CORETEXT
 HB_SHAPER_IMPLEMENT (coretext)
+
+/* Only picks up fonts that have a "mort" or "morx" table.
+   Probably going to be removed https://github.com/harfbuzz/harfbuzz/issues/1478 */
+HB_SHAPER_IMPLEMENT (coretext_aat)
 #endif
 
 #ifdef HAVE_FALLBACK
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright © 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SHAPER_PRIVATE_HH
-#define HB_SHAPER_PRIVATE_HH
-
-#include "hb-private.hh"
-
-typedef hb_bool_t hb_shape_func_t (hb_shape_plan_t    *shape_plan,
-                                   hb_font_t          *font,
-                                   hb_buffer_t        *buffer,
-                                   const hb_feature_t *features,
-                                   unsigned int        num_features);
-
-#define HB_SHAPER_IMPLEMENT(name) \
-        extern "C" HB_INTERNAL hb_shape_func_t _hb_##name##_shape;
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-struct hb_shaper_pair_t {
-  char name[16];
-  hb_shape_func_t *func;
-};
-
-HB_INTERNAL const hb_shaper_pair_t *
-_hb_shapers_get (void);
-
-
-/* For embedding in face / font / ... */
-struct hb_shaper_data_t {
-#define HB_SHAPER_IMPLEMENT(shaper) void *shaper;
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-};
-
-#define HB_SHAPERS_COUNT (sizeof (hb_shaper_data_t) / sizeof (void *))
-
-/* Means: succeeded, but don't need to keep any data. */
-#define HB_SHAPER_DATA_SUCCEEDED ((void *) +1)
-
-/* Means: tried but failed to create. */
-#define HB_SHAPER_DATA_INVALID ((void *) -1)
-#define HB_SHAPER_DATA_IS_INVALID(data) ((void *) (data) == HB_SHAPER_DATA_INVALID)
-
-#define HB_SHAPER_DATA_TYPE_NAME(shaper, object)        hb_##shaper##_shaper_##object##_data_t
-#define HB_SHAPER_DATA_TYPE(shaper, object)             struct HB_SHAPER_DATA_TYPE_NAME(shaper, object)
-#define HB_SHAPER_DATA_INSTANCE(shaper, object, instance)       (* (HB_SHAPER_DATA_TYPE(shaper, object) **) &(instance)->shaper_data.shaper)
-#define HB_SHAPER_DATA(shaper, object)                  HB_SHAPER_DATA_INSTANCE(shaper, object, object)
-#define HB_SHAPER_DATA_CREATE_FUNC(shaper, object)      _hb_##shaper##_shaper_##object##_data_create
-#define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object)     _hb_##shaper##_shaper_##object##_data_destroy
-#define HB_SHAPER_DATA_ENSURE_FUNC(shaper, object)      hb_##shaper##_shaper_##object##_data_ensure
-
-#define HB_SHAPER_DATA_PROTOTYPE(shaper, object) \
-        HB_SHAPER_DATA_TYPE (shaper, object); /* Type forward declaration. */ \
-        extern "C" HB_INTERNAL HB_SHAPER_DATA_TYPE (shaper, object) * \
-        HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (hb_##object##_t *object HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS); \
-        extern "C" HB_INTERNAL void \
-        HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data); \
-        extern "C" HB_INTERNAL bool \
-        HB_SHAPER_DATA_ENSURE_FUNC (shaper, object) (hb_##object##_t *object)
-
-#define HB_SHAPER_DATA_DESTROY(shaper, object) \
-    if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object)) \
-      if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \
-        HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data);
-
-#define HB_SHAPER_DATA_ENSURE_DEFINE(shaper, object) \
-        HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, true)
-
-#define HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, condition) \
-bool \
-HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \
-{\
-  retry: \
-  HB_SHAPER_DATA_TYPE (shaper, object) *data = (HB_SHAPER_DATA_TYPE (shaper, object) *) hb_atomic_ptr_get (&HB_SHAPER_DATA (shaper, object)); \
-  if (likely (data) && !(condition)) { \
-    /* Drop and recreate. */ \
-    /* If someone dropped it in the mean time, throw it away and don't touch it. \
-     * Otherwise, destruct it. */ \
-    if (hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), data, nullptr)) { \
-      HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \
-    } \
-    goto retry; \
-  } \
-  if (unlikely (!data)) { \
-    data = HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (object); \
-    if (unlikely (!data)) \
-      data = (HB_SHAPER_DATA_TYPE (shaper, object) *) HB_SHAPER_DATA_INVALID; \
-    if (!hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), nullptr, data)) { \
-      if (data && \
-          data != HB_SHAPER_DATA_INVALID && \
-          data != HB_SHAPER_DATA_SUCCEEDED) \
-        HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \
-      goto retry; \
-    } \
-  } \
-  return data != nullptr && !HB_SHAPER_DATA_IS_INVALID (data); \
-}
-
-
-#endif /* HB_SHAPER_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,63 +24,41 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-#include "hb-shaper-private.hh"
-#include "hb-atomic-private.hh"
+#include "hb.hh"
+#include "hb-shaper.hh"
+#include "hb-machinery.hh"
 
 
-static const hb_shaper_pair_t all_shapers[] = {
+static const hb_shaper_entry_t all_shapers[] = {
 #define HB_SHAPER_IMPLEMENT(name) {#name, _hb_##name##_shape},
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
 };
 
-
-/* Thread-safe, lock-free, shapers */
-
-static const hb_shaper_pair_t *static_shapers;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_shapers (void)
-{
-retry:
-  hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) hb_atomic_ptr_get (&static_shapers);
-  if (!hb_atomic_ptr_cmpexch (&static_shapers, shapers, nullptr))
-    goto retry;
-
-  if (unlikely (shapers != all_shapers))
-    free ((void *) shapers);
-}
+#if HB_USE_ATEXIT
+static void free_static_shapers ();
 #endif
 
-const hb_shaper_pair_t *
-_hb_shapers_get (void)
+static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_t,
+                                                          hb_shapers_lazy_loader_t>
 {
-retry:
-  hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) hb_atomic_ptr_get (&static_shapers);
-
-  if (unlikely (!shapers))
+  static hb_shaper_entry_t *create ()
   {
     char *env = getenv ("HB_SHAPER_LIST");
-    if (!env || !*env) {
-      (void) hb_atomic_ptr_cmpexch (&static_shapers, nullptr, &all_shapers[0]);
-      return (const hb_shaper_pair_t *) all_shapers;
-    }
+    if (!env || !*env)
+      return nullptr;
 
-    /* Not found; allocate one. */
-    shapers = (hb_shaper_pair_t *) calloc (1, sizeof (all_shapers));
-    if (unlikely (!shapers)) {
-      (void) hb_atomic_ptr_cmpexch (&static_shapers, nullptr, &all_shapers[0]);
-      return (const hb_shaper_pair_t *) all_shapers;
-    }
+    hb_shaper_entry_t *shapers = (hb_shaper_entry_t *) calloc (1, sizeof (all_shapers));
+    if (unlikely (!shapers))
+      return nullptr;
 
     memcpy (shapers, all_shapers, sizeof (all_shapers));
 
      /* Reorder shaper list to prefer requested shapers. */
     unsigned int i = 0;
     char *end, *p = env;
-    for (;;) {
+    for (;;)
+    {
       end = strchr (p, ',');
       if (!end)
         end = p + strlen (p);
@@ -90,7 +68,7 @@
             0 == strncmp (shapers[j].name, p, end - p))
         {
           /* Reorder this shaper to position i */
-         struct hb_shaper_pair_t t = shapers[j];
+         struct hb_shaper_entry_t t = shapers[j];
          memmove (&shapers[i + 1], &shapers[i], sizeof (shapers[i]) * (j - i));
          shapers[i] = t;
          i++;
@@ -102,15 +80,26 @@
         p = end + 1;
     }
 
-    if (!hb_atomic_ptr_cmpexch (&static_shapers, nullptr, shapers)) {
-      free (shapers);
-      goto retry;
-    }
+#if HB_USE_ATEXIT
+    atexit (free_static_shapers);
+#endif
+
+    return shapers;
+  }
+  static void destroy (const hb_shaper_entry_t *p) { free ((void *) p); }
+  static const hb_shaper_entry_t *get_null ()      { return all_shapers; }
+} static_shapers;
 
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_shapers); /* First person registers atexit() callback. */
+#if HB_USE_ATEXIT
+static
+void free_static_shapers ()
+{
+  static_shapers.free_instance ();
+}
 #endif
-  }
 
-  return shapers;
+const hb_shaper_entry_t *
+_hb_shapers_get ()
+{
+  return static_shapers.get_unconst ();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SHAPER_HH
+#define HB_SHAPER_HH
+
+#include "hb.hh"
+#include "hb-machinery.hh"
+
+typedef hb_bool_t hb_shape_func_t (hb_shape_plan_t    *shape_plan,
+                                   hb_font_t          *font,
+                                   hb_buffer_t        *buffer,
+                                   const hb_feature_t *features,
+                                   unsigned int        num_features);
+
+#define HB_SHAPER_IMPLEMENT(name) \
+        extern "C" HB_INTERNAL hb_shape_func_t _hb_##name##_shape;
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+
+struct hb_shaper_entry_t {
+  char name[16];
+  hb_shape_func_t *func;
+};
+
+HB_INTERNAL const hb_shaper_entry_t *
+_hb_shapers_get ();
+
+
+template <typename Data, unsigned int WheresData, typename T>
+struct hb_shaper_lazy_loader_t;
+
+#define HB_SHAPER_ORDER(Shaper) \
+  HB_PASTE (HB_SHAPER_ORDER_, Shaper)
+enum hb_shaper_order_t
+{
+  _HB_SHAPER_ORDER_ORDER_ZERO,
+#define HB_SHAPER_IMPLEMENT(Shaper) \
+      HB_SHAPER_ORDER (Shaper),
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  _HB_SHAPERS_COUNT_PLUS_ONE,
+  HB_SHAPERS_COUNT = _HB_SHAPERS_COUNT_PLUS_ONE - 1,
+};
+
+template <enum hb_shaper_order_t order, typename Object> struct hb_shaper_object_data_type_t;
+
+#define HB_SHAPER_DATA_SUCCEEDED ((void *) +1)
+#define HB_SHAPER_DATA_TYPE(shaper, object)             hb_##shaper##_##object##_data_t
+#define HB_SHAPER_DATA_CREATE_FUNC(shaper, object)      _hb_##shaper##_shaper_##object##_data_create
+#define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object)     _hb_##shaper##_shaper_##object##_data_destroy
+
+#define HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, object) \
+        \
+        struct HB_SHAPER_DATA_TYPE (shaper, object); /* Type forward declaration. */ \
+        extern "C" HB_INTERNAL HB_SHAPER_DATA_TYPE (shaper, object) * \
+        HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (hb_##object##_t *object); \
+        extern "C" HB_INTERNAL void \
+        HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *shaper##_##object); \
+        \
+        template <> \
+        struct hb_shaper_object_data_type_t<HB_SHAPER_ORDER (shaper), hb_##object##_t> \
+        { \
+          typedef HB_SHAPER_DATA_TYPE(shaper, object) value; \
+        }; \
+        \
+        template <unsigned int WheresData> \
+        struct hb_shaper_lazy_loader_t<hb_##object##_t, WheresData, HB_SHAPER_DATA_TYPE(shaper, object)> \
+                : hb_lazy_loader_t<HB_SHAPER_DATA_TYPE(shaper, object), \
+                                   hb_shaper_lazy_loader_t<hb_##object##_t, \
+                                                           WheresData, \
+                                                           HB_SHAPER_DATA_TYPE(shaper, object)>, \
+                                   hb_##object##_t, WheresData> \
+        { \
+          typedef HB_SHAPER_DATA_TYPE(shaper, object) Type; \
+          static Type* create (hb_##object##_t *data) \
+          { return HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (data); } \
+          static Type *get_null () { return nullptr; } \
+          static void destroy (Type *p) { HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (p); } \
+        }; \
+        \
+        static_assert (true, "") /* Require semicolon. */
+
+
+template <typename Object>
+struct hb_shaper_object_dataset_t
+{
+  void init0 (Object *parent_data)
+  {
+    this->parent_data = parent_data;
+#define HB_SHAPER_IMPLEMENT(shaper) shaper.init0 ();
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  }
+  void fini ()
+  {
+#define HB_SHAPER_IMPLEMENT(shaper) shaper.fini ();
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  }
+
+  Object *parent_data; /* MUST be JUST before the lazy loaders. */
+#define HB_SHAPER_IMPLEMENT(shaper) \
+        hb_shaper_lazy_loader_t<Object, HB_SHAPER_ORDER(shaper), \
+                                typename hb_shaper_object_data_type_t<HB_SHAPER_ORDER(shaper), Object>::value \
+                               > shaper;
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+};
+
+#endif /* HB_SHAPER_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-static.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-static.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,9 +24,52 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
+
+#include "hb-open-type.hh"
+#include "hb-face.hh"
+
+#include "hb-aat-layout-common.hh"
+#include "hb-aat-layout-feat-table.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-ot-cmap-table.hh"
+#include "hb-ot-head-table.hh"
+#include "hb-ot-maxp-table.hh"
 
 #ifndef HB_NO_VISIBILITY
-void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
-/*thread_local*/ void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
+
+hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
+/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
+
+DEFINE_NULL_NAMESPACE_BYTES (OT, Index) =  {0xFF,0xFF};
+DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
+DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00};
+DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00};
+DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF};
+/* Hand-coded because Lookup is a template.  Sad. */
+const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
+
+
+unsigned int
+hb_face_t::load_num_glyphs () const
+{
+  hb_sanitize_context_t c = hb_sanitize_context_t ();
+  c.set_num_glyphs (0); /* So we don't recurse ad infinitum. */
+  hb_blob_t *maxp_blob = c.reference_table<OT::maxp> (this);
+  const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
+
+  unsigned int ret = maxp_table->get_num_glyphs ();
+  num_glyphs.set_relaxed (ret);
+  hb_blob_destroy (maxp_blob);
+  return ret;
+}
+
+unsigned int
+hb_face_t::load_upem () const
+{
+  unsigned int ret = table.head->get_upem ();
+  upem.set_relaxed (ret);
+  return ret;
+}
+
 #endif
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-string-array.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-string-array.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -29,7 +29,7 @@
 #define HB_STRING_ARRAY_HH
 #endif
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 /* Based on Bruno Haible's code in Appendix B of Ulrich Drepper's dsohowto.pdf:
  * https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff-common.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,226 @@
+/*
+ * 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
+ */
+
+#include "hb-ot-cff-common.hh"
+#include "hb-ot-cff2-table.hh"
+#include "hb-subset-cff-common.hh"
+
+/* Disable FDSelect format 0 for compatibility with fonttools which doesn't seem choose it.
+ * Rarely any/much smaller than format 3 anyway. */
+#define CFF_SERIALIZE_FDSELECT_0  0
+
+using namespace CFF;
+
+/**
+ * hb_plan_subset_cff_fdselect
+ * Determine an optimal FDSelect format according to a provided plan.
+ *
+ * Return value: FDSelect format, size, and ranges for the most compact subset FDSelect
+ * along with a font index remapping table
+ **/
+
+bool
+hb_plan_subset_cff_fdselect (const hb_vector_t<hb_codepoint_t> &glyphs,
+                            unsigned int fdCount,
+                            const FDSelect &src, /* IN */
+                            unsigned int &subset_fd_count /* OUT */,
+                            unsigned int &subset_fdselect_size /* OUT */,
+                            unsigned int &subset_fdselect_format /* OUT */,
+                            hb_vector_t<code_pair_t> &fdselect_ranges /* OUT */,
+                            remap_t &fdmap /* OUT */)
+{
+  subset_fd_count = 0;
+  subset_fdselect_size = 0;
+  subset_fdselect_format = 0;
+  unsigned int  num_ranges = 0;
+
+  unsigned int subset_num_glyphs = glyphs.length;
+  if (subset_num_glyphs == 0)
+    return true;
+
+  {
+    /* use hb_set to determine the subset of font dicts */
+    hb_set_t  *set = hb_set_create ();
+    if (set == &Null (hb_set_t))
+      return false;
+    hb_codepoint_t  prev_fd = CFF_UNDEF_CODE;
+    for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++)
+    {
+      hb_codepoint_t  fd = src.get_fd (glyphs[i]);
+      set->add (fd);
+
+      if (fd != prev_fd)
+      {
+        num_ranges++;
+        prev_fd = fd;
+        code_pair_t pair = { fd, i };
+        fdselect_ranges.push (pair);
+      }
+    }
+
+    subset_fd_count = set->get_population ();
+    if (subset_fd_count == fdCount)
+    {
+      /* all font dicts belong to the subset. no need to subset FDSelect & FDArray */
+      fdmap.identity (fdCount);
+      hb_set_destroy (set);
+    }
+    else
+    {
+      /* create a fdmap */
+      if (!fdmap.reset (fdCount))
+      {
+        hb_set_destroy (set);
+        return false;
+      }
+
+      hb_codepoint_t  fd = CFF_UNDEF_CODE;
+      while (set->next (&fd))
+        fdmap.add (fd);
+      hb_set_destroy (set);
+      if (unlikely (fdmap.get_count () != subset_fd_count))
+        return false;
+    }
+
+    /* update each font dict index stored as "code" in fdselect_ranges */
+    for (unsigned int i = 0; i < fdselect_ranges.length; i++)
+      fdselect_ranges[i].code = fdmap[fdselect_ranges[i].code];
+  }
+
+  /* determine which FDSelect format is most compact */
+  if (subset_fd_count > 0xFF)
+  {
+    if (unlikely (src.format != 4))
+      return false;
+    subset_fdselect_format = 4;
+    subset_fdselect_size = FDSelect::min_size + FDSelect4::min_size + FDSelect4_Range::static_size * num_ranges + HBUINT32::static_size;
+  }
+  else
+  {
+#if CFF_SERIALIZE_FDSELECT_0
+    unsigned int format0_size = FDSelect::min_size + FDSelect0::min_size + HBUINT8::static_size * subset_num_glyphs;
+#endif
+    unsigned int format3_size = FDSelect::min_size + FDSelect3::min_size + FDSelect3_Range::static_size * num_ranges + HBUINT16::static_size;
+
+#if CFF_SERIALIZE_FDSELECT_0
+    if (format0_size <= format3_size)
+    {
+      // subset_fdselect_format = 0;
+      subset_fdselect_size = format0_size;
+    }
+    else
+#endif
+    {
+      subset_fdselect_format = 3;
+      subset_fdselect_size = format3_size;
+    }
+  }
+
+  return true;
+}
+
+template <typename FDSELECT3_4>
+static inline bool
+serialize_fdselect_3_4 (hb_serialize_context_t *c,
+                          const unsigned int num_glyphs,
+                          const FDSelect &src,
+                          unsigned int size,
+                          const hb_vector_t<code_pair_t> &fdselect_ranges)
+{
+  TRACE_SERIALIZE (this);
+  FDSELECT3_4 *p = c->allocate_size<FDSELECT3_4> (size);
+  if (unlikely (p == nullptr)) return_trace (false);
+  p->nRanges ().set (fdselect_ranges.length);
+  for (unsigned int i = 0; i < fdselect_ranges.length; i++)
+  {
+    p->ranges[i].first.set (fdselect_ranges[i].glyph);
+    p->ranges[i].fd.set (fdselect_ranges[i].code);
+  }
+  p->sentinel().set (num_glyphs);
+  return_trace (true);
+}
+
+/**
+ * hb_serialize_cff_fdselect
+ * Serialize a subset FDSelect format planned above.
+ **/
+bool
+hb_serialize_cff_fdselect (hb_serialize_context_t *c,
+                          const unsigned int num_glyphs,
+                          const FDSelect &src,
+                          unsigned int fd_count,
+                          unsigned int fdselect_format,
+                          unsigned int size,
+                          const hb_vector_t<code_pair_t> &fdselect_ranges)
+{
+  TRACE_SERIALIZE (this);
+  FDSelect  *p = c->allocate_min<FDSelect> ();
+  if (unlikely (p == nullptr)) return_trace (false);
+  p->format.set (fdselect_format);
+  size -= FDSelect::min_size;
+
+  switch (fdselect_format)
+  {
+#if CFF_SERIALIZE_FDSELECT_0
+    case 0:
+    {
+      FDSelect0 *p = c->allocate_size<FDSelect0> (size);
+      if (unlikely (p == nullptr)) return_trace (false);
+      unsigned int range_index = 0;
+      unsigned int  fd = fdselect_ranges[range_index++].code;
+      for (unsigned int i = 0; i < num_glyphs; i++)
+      {
+        if ((range_index < fdselect_ranges.len) &&
+            (i >= fdselect_ranges[range_index].glyph))
+        {
+          fd = fdselect_ranges[range_index++].code;
+        }
+        p->fds[i].set (fd);
+      }
+      break;
+    }
+#endif /* CFF_SERIALIZE_FDSELECT_0 */
+
+    case 3:
+      return serialize_fdselect_3_4<FDSelect3> (c,
+                                                num_glyphs,
+                                                src,
+                                                size,
+                                                fdselect_ranges);
+
+    case 4:
+      return serialize_fdselect_3_4<FDSelect4> (c,
+                                                num_glyphs,
+                                                src,
+                                                size,
+                                                fdselect_ranges);
+
+    default:
+      assert(false);
+  }
+
+  return_trace (true);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff-common.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,990 @@
+/*
+ * 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_SUBSET_CFF_COMMON_HH
+#define HB_SUBSET_CFF_COMMON_HH
+
+#include "hb.hh"
+
+#include "hb-subset-plan.hh"
+#include "hb-cff-interp-cs-common.hh"
+
+namespace CFF {
+
+/* Used for writing a temporary charstring */
+struct str_encoder_t
+{
+  str_encoder_t (str_buff_t &buff_)
+    : buff (buff_), error (false) {}
+
+  void reset () { buff.resize (0); }
+
+  void encode_byte (unsigned char b)
+  {
+    if (unlikely (buff.push (b) == &Crap(unsigned char)))
+      set_error ();
+  }
+
+  void encode_int (int v)
+  {
+    if ((-1131 <= v) && (v <= 1131))
+    {
+      if ((-107 <= v) && (v <= 107))
+        encode_byte (v + 139);
+      else if (v > 0)
+      {
+        v -= 108;
+        encode_byte ((v >> 8) + OpCode_TwoBytePosInt0);
+        encode_byte (v & 0xFF);
+      }
+      else
+      {
+        v = -v - 108;
+        encode_byte ((v >> 8) + OpCode_TwoByteNegInt0);
+        encode_byte (v & 0xFF);
+      }
+    }
+    else
+    {
+      if (unlikely (v < -32768))
+        v = -32768;
+      else if (unlikely (v > 32767))
+        v = 32767;
+      encode_byte (OpCode_shortint);
+      encode_byte ((v >> 8) & 0xFF);
+      encode_byte (v & 0xFF);
+    }
+  }
+
+  void encode_num (const number_t& n)
+  {
+    if (n.in_int_range ())
+    {
+      encode_int (n.to_int ());
+    }
+    else
+    {
+      int32_t v = n.to_fixed ();
+      encode_byte (OpCode_fixedcs);
+      encode_byte ((v >> 24) & 0xFF);
+      encode_byte ((v >> 16) & 0xFF);
+      encode_byte ((v >> 8) & 0xFF);
+      encode_byte (v & 0xFF);
+    }
+  }
+
+  void encode_op (op_code_t op)
+  {
+    if (Is_OpCode_ESC (op))
+    {
+      encode_byte (OpCode_escape);
+      encode_byte (Unmake_OpCode_ESC (op));
+    }
+    else
+      encode_byte (op);
+  }
+
+  void copy_str (const byte_str_t &str)
+  {
+    unsigned int  offset = buff.length;
+    buff.resize (offset + str.length);
+    if (unlikely (buff.length < offset + str.length))
+    {
+      set_error ();
+      return;
+    }
+    memcpy (&buff[offset], &str[0], str.length);
+  }
+
+  bool is_error () const { return error; }
+
+  protected:
+  void set_error () { error = true; }
+
+  str_buff_t &buff;
+  bool    error;
+};
+
+struct cff_sub_table_offsets_t {
+  cff_sub_table_offsets_t () : privateDictsOffset (0)
+  {
+    topDictInfo.init ();
+    FDSelectInfo.init ();
+    FDArrayInfo.init ();
+    charStringsInfo.init ();
+    globalSubrsInfo.init ();
+    localSubrsInfos.init ();
+  }
+
+  ~cff_sub_table_offsets_t () { localSubrsInfos.fini (); }
+
+  table_info_t     topDictInfo;
+  table_info_t     FDSelectInfo;
+  table_info_t     FDArrayInfo;
+  table_info_t     charStringsInfo;
+  unsigned int  privateDictsOffset;
+  table_info_t     globalSubrsInfo;
+  hb_vector_t<table_info_t>  localSubrsInfos;
+};
+
+template <typename OPSTR=op_str_t>
+struct cff_top_dict_op_serializer_t : op_serializer_t
+{
+  bool serialize (hb_serialize_context_t *c,
+                  const OPSTR &opstr,
+                  const cff_sub_table_offsets_t &offsets) const
+  {
+    TRACE_SERIALIZE (this);
+
+    switch (opstr.op)
+    {
+      case OpCode_CharStrings:
+        return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.charStringsInfo.offset));
+
+      case OpCode_FDArray:
+        return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.FDArrayInfo.offset));
+
+      case OpCode_FDSelect:
+        return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.FDSelectInfo.offset));
+
+      default:
+        return_trace (copy_opstr (c, opstr));
+    }
+    return_trace (true);
+  }
+
+  unsigned int calculate_serialized_size (const OPSTR &opstr) const
+  {
+    switch (opstr.op)
+    {
+      case OpCode_CharStrings:
+      case OpCode_FDArray:
+      case OpCode_FDSelect:
+        return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
+
+      default:
+        return opstr.str.length;
+    }
+  }
+};
+
+struct cff_font_dict_op_serializer_t : op_serializer_t
+{
+  bool serialize (hb_serialize_context_t *c,
+                  const op_str_t &opstr,
+                  const table_info_t &privateDictInfo) const
+  {
+    TRACE_SERIALIZE (this);
+
+    if (opstr.op == OpCode_Private)
+    {
+      /* serialize the private dict size & offset as 2-byte & 4-byte integers */
+      if (unlikely (!UnsizedByteStr::serialize_int2 (c, privateDictInfo.size) ||
+                    !UnsizedByteStr::serialize_int4 (c, privateDictInfo.offset)))
+        return_trace (false);
+
+      /* serialize the opcode */
+      HBUINT8 *p = c->allocate_size<HBUINT8> (1);
+      if (unlikely (p == nullptr)) return_trace (false);
+      p->set (OpCode_Private);
+
+      return_trace (true);
+    }
+    else
+    {
+      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);
+  }
+
+  unsigned int calculate_serialized_size (const op_str_t &opstr) const
+  {
+    if (opstr.op == OpCode_Private)
+      return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Private);
+    else
+      return opstr.str.length;
+  }
+};
+
+struct cff_private_dict_op_serializer_t : op_serializer_t
+{
+  cff_private_dict_op_serializer_t (bool desubroutinize_, bool drop_hints_)
+    : desubroutinize (desubroutinize_), drop_hints (drop_hints_) {}
+
+  bool serialize (hb_serialize_context_t *c,
+                  const op_str_t &opstr,
+                  const unsigned int subrsOffset) const
+  {
+    TRACE_SERIALIZE (this);
+
+    if (drop_hints && dict_opset_t::is_hint_op (opstr.op))
+      return true;
+    if (opstr.op == OpCode_Subrs)
+    {
+      if (desubroutinize || (subrsOffset == 0))
+        return_trace (true);
+      else
+        return_trace (FontDict::serialize_offset2_op (c, opstr.op, subrsOffset));
+    }
+    else
+      return_trace (copy_opstr (c, opstr));
+  }
+
+  unsigned int calculate_serialized_size (const op_str_t &opstr,
+                                          bool has_localsubr=true) const
+  {
+    if (drop_hints && dict_opset_t::is_hint_op (opstr.op))
+      return 0;
+    if (opstr.op == OpCode_Subrs)
+    {
+      if (desubroutinize || !has_localsubr)
+        return 0;
+      else
+        return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (opstr.op);
+    }
+    else
+      return opstr.str.length;
+  }
+
+  protected:
+  const bool  desubroutinize;
+  const bool  drop_hints;
+};
+
+struct flatten_param_t
+{
+  str_buff_t     &flatStr;
+  bool  drop_hints;
+};
+
+template <typename ACC, typename ENV, typename OPSET>
+struct subr_flattener_t
+{
+  subr_flattener_t (const ACC &acc_,
+                    const hb_vector_t<hb_codepoint_t> &glyphs_,
+                    bool drop_hints_) : acc (acc_), glyphs (glyphs_),
+                                        drop_hints (drop_hints_) {}
+
+  bool flatten (str_buff_vec_t &flat_charstrings)
+  {
+    if (!flat_charstrings.resize (glyphs.length))
+      return false;
+    for (unsigned int i = 0; i < glyphs.length; i++)
+      flat_charstrings[i].init ();
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      hb_codepoint_t  glyph = glyphs[i];
+      const byte_str_t str = (*acc.charStrings)[glyph];
+      unsigned int fd = acc.fdSelect->get_fd (glyph);
+      if (unlikely (fd >= acc.fdCount))
+        return false;
+      cs_interpreter_t<ENV, OPSET, flatten_param_t> interp;
+      interp.env.init (str, acc, fd);
+      flatten_param_t  param = { flat_charstrings[i], drop_hints };
+      if (unlikely (!interp.interpret (param)))
+        return false;
+    }
+    return true;
+  }
+
+  const ACC &acc;
+  const hb_vector_t<hb_codepoint_t> &glyphs;
+  bool  drop_hints;
+};
+
+struct subr_closures_t
+{
+  subr_closures_t () : valid (false), global_closure (nullptr)
+  { local_closures.init (); }
+
+  void init (unsigned int fd_count)
+  {
+    valid = true;
+    global_closure = hb_set_create ();
+    if (global_closure == hb_set_get_empty ())
+      valid = false;
+    if (!local_closures.resize (fd_count))
+      valid = false;
+
+    for (unsigned int i = 0; i < local_closures.length; i++)
+    {
+      local_closures[i] = hb_set_create ();
+      if (local_closures[i] == hb_set_get_empty ())
+        valid = false;
+    }
+  }
+
+  void fini ()
+  {
+    hb_set_destroy (global_closure);
+    for (unsigned int i = 0; i < local_closures.length; i++)
+      hb_set_destroy (local_closures[i]);
+    local_closures.fini ();
+  }
+
+  void reset ()
+  {
+    hb_set_clear (global_closure);
+    for (unsigned int i = 0; i < local_closures.length; i++)
+      hb_set_clear (local_closures[i]);
+  }
+
+  bool is_valid () const { return valid; }
+  bool  valid;
+  hb_set_t  *global_closure;
+  hb_vector_t<hb_set_t *> local_closures;
+};
+
+struct parsed_cs_op_t : op_str_t
+{
+  void init (unsigned int subr_num_ = 0)
+  {
+    op_str_t::init ();
+    subr_num = subr_num_;
+    drop_flag = false;
+    keep_flag = false;
+    skip_flag = false;
+  }
+
+  void fini () { op_str_t::fini (); }
+
+  bool for_drop () const { return drop_flag; }
+  void set_drop ()       { if (!for_keep ()) drop_flag = true; }
+
+  bool for_keep () const { return keep_flag; }
+  void set_keep ()       { keep_flag = true; }
+
+  bool for_skip () const { return skip_flag; }
+  void set_skip ()       { skip_flag = true; }
+
+  unsigned int  subr_num;
+
+  protected:
+  bool    drop_flag : 1;
+  bool    keep_flag : 1;
+  bool    skip_flag : 1;
+};
+
+struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
+{
+  void init ()
+  {
+    SUPER::init ();
+    parsed = false;
+    hint_dropped = false;
+    has_prefix_ = false;
+  }
+
+  void add_op (op_code_t op, const byte_str_ref_t& str_ref)
+  {
+    if (!is_parsed ())
+      SUPER::add_op (op, str_ref);
+  }
+
+  void add_call_op (op_code_t op, const byte_str_ref_t& str_ref, unsigned int subr_num)
+  {
+    if (!is_parsed ())
+    {
+      unsigned int parsed_len = get_count ();
+      if (likely (parsed_len > 0))
+        values[parsed_len-1].set_skip ();
+
+      parsed_cs_op_t val;
+      val.init (subr_num);
+      SUPER::add_op (op, str_ref, val);
+    }
+  }
+
+  void set_prefix (const number_t &num, op_code_t op = OpCode_Invalid)
+  {
+    has_prefix_ = true;
+    prefix_op_ = op;
+    prefix_num_ = num;
+  }
+
+  bool at_end (unsigned int pos) const
+  {
+    return ((pos + 1 >= values.length) /* CFF2 */
+        || (values[pos + 1].op == OpCode_return));
+  }
+
+  bool is_parsed () const { return parsed; }
+  void set_parsed ()      { parsed = true; }
+
+  bool is_hint_dropped () const { return hint_dropped; }
+  void set_hint_dropped ()      { hint_dropped = true; }
+
+  bool is_vsindex_dropped () const { return vsindex_dropped; }
+  void set_vsindex_dropped ()      { vsindex_dropped = true; }
+
+  bool has_prefix () const          { return has_prefix_; }
+  op_code_t prefix_op () const         { return prefix_op_; }
+  const number_t &prefix_num () const { return prefix_num_; }
+
+  protected:
+  bool    parsed;
+  bool    hint_dropped;
+  bool    vsindex_dropped;
+  bool    has_prefix_;
+  op_code_t     prefix_op_;
+  number_t      prefix_num_;
+
+  private:
+  typedef parsed_values_t<parsed_cs_op_t> SUPER;
+};
+
+struct parsed_cs_str_vec_t : hb_vector_t<parsed_cs_str_t>
+{
+  void init (unsigned int len_ = 0)
+  {
+    SUPER::init ();
+    resize (len_);
+    for (unsigned int i = 0; i < length; i++)
+      (*this)[i].init ();
+  }
+  void fini () { SUPER::fini_deep (); }
+
+  private:
+  typedef hb_vector_t<parsed_cs_str_t> SUPER;
+};
+
+struct subr_subset_param_t
+{
+  void init (parsed_cs_str_t *parsed_charstring_,
+             parsed_cs_str_vec_t *parsed_global_subrs_, parsed_cs_str_vec_t *parsed_local_subrs_,
+             hb_set_t *global_closure_, hb_set_t *local_closure_,
+             bool drop_hints_)
+  {
+    parsed_charstring = parsed_charstring_;
+    current_parsed_str = parsed_charstring;
+    parsed_global_subrs = parsed_global_subrs_;
+    parsed_local_subrs = parsed_local_subrs_;
+    global_closure = global_closure_;
+    local_closure = local_closure_;
+    drop_hints = drop_hints_;
+  }
+
+  parsed_cs_str_t *get_parsed_str_for_context (call_context_t &context)
+  {
+    switch (context.type)
+    {
+      case CSType_CharString:
+        return parsed_charstring;
+
+      case CSType_LocalSubr:
+        if (likely (context.subr_num < parsed_local_subrs->length))
+          return &(*parsed_local_subrs)[context.subr_num];
+        break;
+
+      case CSType_GlobalSubr:
+        if (likely (context.subr_num < parsed_global_subrs->length))
+          return &(*parsed_global_subrs)[context.subr_num];
+        break;
+    }
+    return nullptr;
+  }
+
+  template <typename ENV>
+  void set_current_str (ENV &env, bool calling)
+  {
+    parsed_cs_str_t  *parsed_str = get_parsed_str_for_context (env.context);
+    if (likely (parsed_str != nullptr))
+    {
+      /* If the called subroutine is parsed partially but not completely yet,
+       * it must be because we are calling it recursively.
+       * Handle it as an error. */
+      if (unlikely (calling && !parsed_str->is_parsed () && (parsed_str->values.length > 0)))
+        env.set_error ();
+      else
+        current_parsed_str = parsed_str;
+    }
+    else
+      env.set_error ();
+  }
+
+  parsed_cs_str_t       *current_parsed_str;
+
+  parsed_cs_str_t       *parsed_charstring;
+  parsed_cs_str_vec_t   *parsed_global_subrs;
+  parsed_cs_str_vec_t   *parsed_local_subrs;
+  hb_set_t      *global_closure;
+  hb_set_t      *local_closure;
+  bool    drop_hints;
+};
+
+struct subr_remap_t : remap_t
+{
+  void create (hb_set_t *closure)
+  {
+    /* create a remapping of subroutine numbers from old to new.
+     * no optimization based on usage counts. fonttools doesn't appear doing that either.
+     */
+    reset (closure->get_max () + 1);
+    for (hb_codepoint_t old_num = 0; old_num < length; old_num++)
+    {
+      if (hb_set_has (closure, old_num))
+        add (old_num);
+    }
+
+    if (get_count () < 1240)
+      bias = 107;
+    else if (get_count () < 33900)
+      bias = 1131;
+    else
+      bias = 32768;
+  }
+
+  hb_codepoint_t operator[] (unsigned int old_num) const
+  {
+    if (old_num >= length)
+      return CFF_UNDEF_CODE;
+    else
+      return remap_t::operator[] (old_num);
+  }
+
+  int biased_num (unsigned int old_num) const
+  {
+    hb_codepoint_t new_num = (*this)[old_num];
+    return (int)new_num - bias;
+  }
+
+  protected:
+  int bias;
+};
+
+struct subr_remap_ts
+{
+  subr_remap_ts ()
+  {
+    global_remap.init ();
+    local_remaps.init ();
+  }
+
+  ~subr_remap_ts () { fini (); }
+
+  void init (unsigned int fdCount)
+  {
+    local_remaps.resize (fdCount);
+    for (unsigned int i = 0; i < fdCount; i++)
+      local_remaps[i].init ();
+  }
+
+  void create (subr_closures_t& closures)
+  {
+    global_remap.create (closures.global_closure);
+    for (unsigned int i = 0; i < local_remaps.length; i++)
+      local_remaps[i].create (closures.local_closures[i]);
+  }
+
+  void fini ()
+  {
+    global_remap.fini ();
+    local_remaps.fini_deep ();
+  }
+
+  subr_remap_t         global_remap;
+  hb_vector_t<subr_remap_t>  local_remaps;
+};
+
+template <typename SUBSETTER, typename SUBRS, typename ACC, typename ENV, typename OPSET>
+struct subr_subsetter_t
+{
+  subr_subsetter_t ()
+  {
+    parsed_charstrings.init ();
+    parsed_global_subrs.init ();
+    parsed_local_subrs.init ();
+  }
+
+  ~subr_subsetter_t ()
+  {
+    closures.fini ();
+    remaps.fini ();
+    parsed_charstrings.fini_deep ();
+    parsed_global_subrs.fini_deep ();
+    parsed_local_subrs.fini_deep ();
+  }
+
+  /* Subroutine subsetting with --no-desubroutinize runs in phases:
+   *
+   * 1. execute charstrings/subroutines to determine subroutine closures
+   * 2. parse out all operators and numbers
+   * 3. mark hint operators and operands for removal if --no-hinting
+   * 4. re-encode all charstrings and subroutines with new subroutine numbers
+   *
+   * Phases #1 and #2 are done at the same time in collect_subrs ().
+   * Phase #3 walks charstrings/subroutines forward then backward (hence parsing required),
+   * because we can't tell if a number belongs to a hint op until we see the first moveto.
+   *
+   * Assumption: a callsubr/callgsubr operator must immediately follow a (biased) subroutine number
+   * within the same charstring/subroutine, e.g., not split across a charstring and a subroutine.
+   */
+  bool subset (ACC &acc, const hb_vector_t<hb_codepoint_t> &glyphs, bool drop_hints)
+  {
+    closures.init (acc.fdCount);
+    remaps.init (acc.fdCount);
+
+    parsed_charstrings.init (glyphs.length);
+    parsed_global_subrs.init (acc.globalSubrs->count);
+    parsed_local_subrs.resize (acc.fdCount);
+    for (unsigned int i = 0; i < acc.fdCount; i++)
+    {
+      parsed_local_subrs[i].init (acc.privateDicts[i].localSubrs->count);
+    }
+    if (unlikely (!closures.valid))
+      return false;
+
+    /* phase 1 & 2 */
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      hb_codepoint_t  glyph = glyphs[i];
+      const byte_str_t str = (*acc.charStrings)[glyph];
+      unsigned int fd = acc.fdSelect->get_fd (glyph);
+      if (unlikely (fd >= acc.fdCount))
+        return false;
+
+      cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp;
+      interp.env.init (str, acc, fd);
+
+      subr_subset_param_t  param;
+      param.init (&parsed_charstrings[i],
+                  &parsed_global_subrs,  &parsed_local_subrs[fd],
+                  closures.global_closure, closures.local_closures[fd],
+                  drop_hints);
+
+      if (unlikely (!interp.interpret (param)))
+        return false;
+
+      /* finalize parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
+      SUBSETTER::finalize_parsed_str (interp.env, param, parsed_charstrings[i]);
+    }
+
+    if (drop_hints)
+    {
+      /* mark hint ops and arguments for drop */
+      for (unsigned int i = 0; i < glyphs.length; i++)
+      {
+        unsigned int fd = acc.fdSelect->get_fd (glyphs[i]);
+        if (unlikely (fd >= acc.fdCount))
+          return false;
+        subr_subset_param_t  param;
+        param.init (&parsed_charstrings[i],
+                    &parsed_global_subrs,  &parsed_local_subrs[fd],
+                    closures.global_closure, closures.local_closures[fd],
+                    drop_hints);
+
+        drop_hints_param_t  drop;
+        if (drop_hints_in_str (parsed_charstrings[i], param, drop))
+        {
+          parsed_charstrings[i].set_hint_dropped ();
+          if (drop.vsindex_dropped)
+            parsed_charstrings[i].set_vsindex_dropped ();
+        }
+      }
+
+      /* after dropping hints recreate closures of actually used subrs */
+      closures.reset ();
+      for (unsigned int i = 0; i < glyphs.length; i++)
+      {
+        unsigned int fd = acc.fdSelect->get_fd (glyphs[i]);
+        if (unlikely (fd >= acc.fdCount))
+          return false;
+        subr_subset_param_t  param;
+        param.init (&parsed_charstrings[i],
+                    &parsed_global_subrs,  &parsed_local_subrs[fd],
+                    closures.global_closure, closures.local_closures[fd],
+                    drop_hints);
+        collect_subr_refs_in_str (parsed_charstrings[i], param);
+      }
+    }
+
+    remaps.create (closures);
+
+    return true;
+  }
+
+  bool encode_charstrings (ACC &acc, const hb_vector_t<hb_codepoint_t> &glyphs, str_buff_vec_t &buffArray) const
+  {
+    if (unlikely (!buffArray.resize (glyphs.length)))
+      return false;
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      unsigned int  fd = acc.fdSelect->get_fd (glyphs[i]);
+      if (unlikely (fd >= acc.fdCount))
+        return false;
+      if (unlikely (!encode_str (parsed_charstrings[i], fd, buffArray[i])))
+        return false;
+    }
+    return true;
+  }
+
+  bool encode_subrs (const parsed_cs_str_vec_t &subrs, const subr_remap_t& remap, unsigned int fd, str_buff_vec_t &buffArray) const
+  {
+    unsigned int  count = remap.get_count ();
+
+    if (unlikely (!buffArray.resize (count)))
+      return false;
+    for (unsigned int old_num = 0; old_num < subrs.length; old_num++)
+    {
+      hb_codepoint_t new_num = remap[old_num];
+      if (new_num != CFF_UNDEF_CODE)
+      {
+        if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num])))
+          return false;
+      }
+    }
+    return true;
+  }
+
+  bool encode_globalsubrs (str_buff_vec_t &buffArray)
+  {
+    return encode_subrs (parsed_global_subrs, remaps.global_remap, 0, buffArray);
+  }
+
+  bool encode_localsubrs (unsigned int fd, str_buff_vec_t &buffArray) const
+  {
+    return encode_subrs (parsed_local_subrs[fd], remaps.local_remaps[fd], fd, buffArray);
+  }
+
+  protected:
+  struct drop_hints_param_t
+  {
+    drop_hints_param_t ()
+      : seen_moveto (false),
+        ends_in_hint (false),
+        vsindex_dropped (false) {}
+
+    bool  seen_moveto;
+    bool  ends_in_hint;
+    bool  vsindex_dropped;
+  };
+
+  bool drop_hints_in_subr (parsed_cs_str_t &str, unsigned int pos,
+                           parsed_cs_str_vec_t &subrs, unsigned int subr_num,
+                           const subr_subset_param_t &param, drop_hints_param_t &drop)
+  {
+    drop.ends_in_hint = false;
+    bool has_hint = drop_hints_in_str (subrs[subr_num], param, drop);
+
+    /* if this subr ends with a stem hint (i.e., not a number a potential argument for moveto),
+     * then this entire subroutine must be a hint. drop its call. */
+    if (drop.ends_in_hint)
+    {
+      str.values[pos].set_drop ();
+      /* if this subr call is at the end of the parent subr, propagate the flag
+       * otherwise reset the flag */
+      if (!str.at_end (pos))
+        drop.ends_in_hint = false;
+    }
+
+    return has_hint;
+  }
+
+  /* returns true if it sees a hint op before the first moveto */
+  bool drop_hints_in_str (parsed_cs_str_t &str, const subr_subset_param_t &param, drop_hints_param_t &drop)
+  {
+    bool  seen_hint = false;
+
+    for (unsigned int pos = 0; pos < str.values.length; pos++)
+    {
+      bool  has_hint = false;
+      switch (str.values[pos].op)
+      {
+        case OpCode_callsubr:
+          has_hint = drop_hints_in_subr (str, pos,
+                                        *param.parsed_local_subrs, str.values[pos].subr_num,
+                                        param, drop);
+
+          break;
+
+        case OpCode_callgsubr:
+          has_hint = drop_hints_in_subr (str, pos,
+                                        *param.parsed_global_subrs, str.values[pos].subr_num,
+                                        param, drop);
+          break;
+
+        case OpCode_rmoveto:
+        case OpCode_hmoveto:
+        case OpCode_vmoveto:
+          drop.seen_moveto = true;
+          break;
+
+        case OpCode_hintmask:
+        case OpCode_cntrmask:
+          if (drop.seen_moveto)
+          {
+            str.values[pos].set_drop ();
+            break;
+          }
+          HB_FALLTHROUGH;
+
+        case OpCode_hstemhm:
+        case OpCode_vstemhm:
+        case OpCode_hstem:
+        case OpCode_vstem:
+          has_hint = true;
+          str.values[pos].set_drop ();
+          if (str.at_end (pos))
+            drop.ends_in_hint = true;
+          break;
+
+        case OpCode_dotsection:
+          str.values[pos].set_drop ();
+          break;
+
+        default:
+          /* NONE */
+          break;
+      }
+      if (has_hint)
+      {
+        for (int i = pos - 1; i >= 0; i--)
+        {
+          parsed_cs_op_t  &csop = str.values[(unsigned)i];
+          if (csop.for_drop ())
+            break;
+          csop.set_drop ();
+          if (csop.op == OpCode_vsindexcs)
+            drop.vsindex_dropped = true;
+        }
+        seen_hint |= has_hint;
+      }
+    }
+
+    return seen_hint;
+  }
+
+  void collect_subr_refs_in_subr (parsed_cs_str_t &str, unsigned int pos,
+                                  unsigned int subr_num, parsed_cs_str_vec_t &subrs,
+                                  hb_set_t *closure,
+                                  const subr_subset_param_t &param)
+  {
+    hb_set_add (closure, subr_num);
+    collect_subr_refs_in_str (subrs[subr_num], param);
+  }
+
+  void collect_subr_refs_in_str (parsed_cs_str_t &str, const subr_subset_param_t &param)
+  {
+    for (unsigned int pos = 0; pos < str.values.length; pos++)
+    {
+      if (!str.values[pos].for_drop ())
+      {
+        switch (str.values[pos].op)
+        {
+          case OpCode_callsubr:
+            collect_subr_refs_in_subr (str, pos,
+                                       str.values[pos].subr_num, *param.parsed_local_subrs,
+                                       param.local_closure, param);
+            break;
+
+          case OpCode_callgsubr:
+            collect_subr_refs_in_subr (str, pos,
+                                       str.values[pos].subr_num, *param.parsed_global_subrs,
+                                       param.global_closure, param);
+            break;
+
+          default: break;
+        }
+      }
+    }
+  }
+
+  bool encode_str (const parsed_cs_str_t &str, const unsigned int fd, str_buff_t &buff) const
+  {
+    buff.init ();
+    str_encoder_t  encoder (buff);
+    encoder.reset ();
+    /* if a prefix (CFF1 width or CFF2 vsindex) has been removed along with hints,
+     * re-insert it at the beginning of charstreing */
+    if (str.has_prefix () && str.is_hint_dropped ())
+    {
+      encoder.encode_num (str.prefix_num ());
+      if (str.prefix_op () != OpCode_Invalid)
+        encoder.encode_op (str.prefix_op ());
+    }
+    for (unsigned int i = 0; i < str.get_count(); i++)
+    {
+      const parsed_cs_op_t  &opstr = str.values[i];
+      if (!opstr.for_drop () && !opstr.for_skip ())
+      {
+        switch (opstr.op)
+        {
+          case OpCode_callsubr:
+            encoder.encode_int (remaps.local_remaps[fd].biased_num (opstr.subr_num));
+            encoder.encode_op (OpCode_callsubr);
+            break;
+
+          case OpCode_callgsubr:
+            encoder.encode_int (remaps.global_remap.biased_num (opstr.subr_num));
+            encoder.encode_op (OpCode_callgsubr);
+            break;
+
+          default:
+            encoder.copy_str (opstr.str);
+            break;
+        }
+      }
+    }
+    return !encoder.is_error ();
+  }
+
+  protected:
+  subr_closures_t             closures;
+
+  parsed_cs_str_vec_t          parsed_charstrings;
+  parsed_cs_str_vec_t          parsed_global_subrs;
+  hb_vector_t<parsed_cs_str_vec_t>  parsed_local_subrs;
+
+  subr_remap_ts         remaps;
+
+  private:
+  typedef typename SUBRS::count_type subr_count_type;
+};
+
+} /* namespace CFF */
+
+HB_INTERNAL bool
+hb_plan_subset_cff_fdselect (const hb_vector_t<hb_codepoint_t> &glyphs,
+                            unsigned int fdCount,
+                            const CFF::FDSelect &src, /* IN */
+                            unsigned int &subset_fd_count /* OUT */,
+                            unsigned int &subset_fdselect_size /* OUT */,
+                            unsigned int &subset_fdselect_format /* OUT */,
+                            hb_vector_t<CFF::code_pair_t> &fdselect_ranges /* OUT */,
+                            CFF::remap_t &fdmap /* OUT */);
+
+HB_INTERNAL bool
+hb_serialize_cff_fdselect (hb_serialize_context_t *c,
+                          unsigned int num_glyphs,
+                          const CFF::FDSelect &src,
+                          unsigned int fd_count,
+                          unsigned int fdselect_format,
+                          unsigned int size,
+                          const hb_vector_t<CFF::code_pair_t> &fdselect_ranges);
+
+#endif /* HB_SUBSET_CFF_COMMON_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff1.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,1103 @@
+/*
+ * 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
+ */
+
+#include "hb-open-type.hh"
+#include "hb-ot-cff1-table.hh"
+#include "hb-set.h"
+#include "hb-subset-cff1.hh"
+#include "hb-subset-plan.hh"
+#include "hb-subset-cff-common.hh"
+#include "hb-cff1-interp-cs.hh"
+
+using namespace CFF;
+
+struct remap_sid_t : remap_t
+{
+  unsigned int add (unsigned int sid)
+  {
+    if ((sid != CFF_UNDEF_SID) && !is_std_std (sid))
+      return offset_sid (remap_t::add (unoffset_sid (sid)));
+    else
+      return sid;
+  }
+
+  unsigned int operator[] (unsigned int sid) const
+  {
+    if (is_std_std (sid) || (sid == CFF_UNDEF_SID))
+      return sid;
+    else
+      return offset_sid (remap_t::operator [] (unoffset_sid (sid)));
+  }
+
+  static const unsigned int num_std_strings = 391;
+
+  static bool is_std_std (unsigned int sid) { return sid < num_std_strings; }
+  static unsigned int offset_sid (unsigned int sid) { return sid + num_std_strings; }
+  static unsigned int unoffset_sid (unsigned int sid) { return sid - num_std_strings; }
+};
+
+struct cff1_sub_table_offsets_t : cff_sub_table_offsets_t
+{
+  cff1_sub_table_offsets_t ()
+    : cff_sub_table_offsets_t (),
+      nameIndexOffset (0),
+      encodingOffset (0)
+  {
+    stringIndexInfo.init ();
+    charsetInfo.init ();
+    privateDictInfo.init ();
+  }
+
+  unsigned int  nameIndexOffset;
+  table_info_t  stringIndexInfo;
+  unsigned int  encodingOffset;
+  table_info_t  charsetInfo;
+  table_info_t  privateDictInfo;
+};
+
+/* a copy of a parsed out cff1_top_dict_values_t augmented with additional operators */
+struct cff1_top_dict_values_mod_t : cff1_top_dict_values_t
+{
+  void init (const cff1_top_dict_values_t *base_= &Null(cff1_top_dict_values_t))
+  {
+    SUPER::init ();
+    base = base_;
+  }
+
+  void fini () { SUPER::fini (); }
+
+  unsigned get_count () const { return base->get_count () + SUPER::get_count (); }
+  const cff1_top_dict_val_t &get_value (unsigned int i) const
+  {
+    if (i < base->get_count ())
+      return (*base)[i];
+    else
+      return SUPER::values[i - base->get_count ()];
+  }
+  const cff1_top_dict_val_t &operator [] (unsigned int i) const { return get_value (i); }
+
+  void reassignSIDs (const remap_sid_t& sidmap)
+  {
+    for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
+      nameSIDs[i] = sidmap[base->nameSIDs[i]];
+  }
+
+  protected:
+  typedef cff1_top_dict_values_t SUPER;
+  const cff1_top_dict_values_t *base;
+};
+
+struct top_dict_modifiers_t
+{
+  top_dict_modifiers_t (const cff1_sub_table_offsets_t &offsets_,
+                           const unsigned int (&nameSIDs_)[name_dict_values_t::ValCount])
+    : offsets (offsets_),
+      nameSIDs (nameSIDs_)
+  {}
+
+  const cff1_sub_table_offsets_t &offsets;
+  const unsigned int    (&nameSIDs)[name_dict_values_t::ValCount];
+};
+
+struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dict_val_t>
+{
+  bool serialize (hb_serialize_context_t *c,
+                  const cff1_top_dict_val_t &opstr,
+                  const top_dict_modifiers_t &mod) const
+  {
+    TRACE_SERIALIZE (this);
+
+    op_code_t op = opstr.op;
+    switch (op)
+    {
+      case OpCode_charset:
+        return_trace (FontDict::serialize_offset4_op(c, op, mod.offsets.charsetInfo.offset));
+
+      case OpCode_Encoding:
+        return_trace (FontDict::serialize_offset4_op(c, op, mod.offsets.encodingOffset));
+
+      case OpCode_Private:
+        {
+          if (unlikely (!UnsizedByteStr::serialize_int2 (c, mod.offsets.privateDictInfo.size)))
+            return_trace (false);
+          if (unlikely (!UnsizedByteStr::serialize_int4 (c, mod.offsets.privateDictInfo.offset)))
+            return_trace (false);
+          HBUINT8 *p = c->allocate_size<HBUINT8> (1);
+          if (unlikely (p == nullptr)) return_trace (false);
+          p->set (OpCode_Private);
+        }
+        break;
+
+      case OpCode_version:
+      case OpCode_Notice:
+      case OpCode_Copyright:
+      case OpCode_FullName:
+      case OpCode_FamilyName:
+      case OpCode_Weight:
+      case OpCode_PostScript:
+      case OpCode_BaseFontName:
+      case OpCode_FontName:
+        return_trace (FontDict::serialize_offset2_op(c, op, mod.nameSIDs[name_dict_values_t::name_op_to_index (op)]));
+
+      case OpCode_ROS:
+        {
+          /* for registry & ordering, reassigned SIDs are serialized
+           * for supplement, the original byte string is copied along with the op code */
+          op_str_t supp_op;
+          supp_op.op = op;
+          if ( unlikely (!(opstr.str.length >= opstr.last_arg_offset + 3)))
+            return_trace (false);
+          supp_op.str = byte_str_t (&opstr.str + opstr.last_arg_offset, opstr.str.length - opstr.last_arg_offset);
+          return_trace (UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::registry]) &&
+                        UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::ordering]) &&
+                        copy_opstr (c, supp_op));
+        }
+      default:
+        return_trace (cff_top_dict_op_serializer_t<cff1_top_dict_val_t>::serialize (c, opstr, mod.offsets));
+    }
+    return_trace (true);
+  }
+
+  unsigned int calculate_serialized_size (const cff1_top_dict_val_t &opstr) const
+  {
+    op_code_t op = opstr.op;
+    switch (op)
+    {
+      case OpCode_charset:
+      case OpCode_Encoding:
+        return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
+
+      case OpCode_Private:
+        return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Private);
+
+      case OpCode_version:
+      case OpCode_Notice:
+      case OpCode_Copyright:
+      case OpCode_FullName:
+      case OpCode_FamilyName:
+      case OpCode_Weight:
+      case OpCode_PostScript:
+      case OpCode_BaseFontName:
+      case OpCode_FontName:
+        return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (op);
+
+      case OpCode_ROS:
+        return ((OpCode_Size (OpCode_shortint) + 2) * 2) + (opstr.str.length - opstr.last_arg_offset)/* supplement + op */;
+
+      default:
+        return cff_top_dict_op_serializer_t<cff1_top_dict_val_t>::calculate_serialized_size (opstr);
+    }
+  }
+};
+
+struct font_dict_values_mod_t
+{
+  void init (const cff1_font_dict_values_t *base_,
+             unsigned int fontName_,
+             const table_info_t &privateDictInfo_)
+  {
+    base = base_;
+    fontName = fontName_;
+    privateDictInfo = privateDictInfo_;
+  }
+
+  unsigned get_count () const { return base->get_count (); }
+
+  const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
+
+  const cff1_font_dict_values_t    *base;
+  table_info_t             privateDictInfo;
+  unsigned int          fontName;
+};
+
+struct cff1_font_dict_op_serializer_t : cff_font_dict_op_serializer_t
+{
+  bool serialize (hb_serialize_context_t *c,
+                  const op_str_t &opstr,
+                  const font_dict_values_mod_t &mod) const
+  {
+    TRACE_SERIALIZE (this);
+
+    if (opstr.op == OpCode_FontName)
+      return_trace (FontDict::serialize_uint2_op (c, opstr.op, mod.fontName));
+    else
+      return_trace (SUPER::serialize (c, opstr, mod.privateDictInfo));
+  }
+
+  unsigned int calculate_serialized_size (const op_str_t &opstr) const
+  {
+    if (opstr.op == OpCode_FontName)
+      return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_FontName);
+    else
+      return SUPER::calculate_serialized_size (opstr);
+  }
+
+  private:
+  typedef cff_font_dict_op_serializer_t SUPER;
+};
+
+struct cff1_cs_opset_flatten_t : cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatten_param_t>
+{
+  static void flush_args_and_op (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    if (env.arg_start > 0)
+      flush_width (env, param);
+
+    switch (op)
+    {
+      case OpCode_hstem:
+      case OpCode_hstemhm:
+      case OpCode_vstem:
+      case OpCode_vstemhm:
+      case OpCode_hintmask:
+      case OpCode_cntrmask:
+      case OpCode_dotsection:
+        if (param.drop_hints)
+        {
+          env.clear_args ();
+          return;
+        }
+        HB_FALLTHROUGH;
+
+      default:
+        SUPER::flush_args_and_op (op, env, param);
+        break;
+    }
+  }
+  static void flush_args (cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    str_encoder_t  encoder (param.flatStr);
+    for (unsigned int i = env.arg_start; i < env.argStack.get_count (); i++)
+      encoder.encode_num (env.eval_arg (i));
+    SUPER::flush_args (env, param);
+  }
+
+  static void flush_op (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    str_encoder_t  encoder (param.flatStr);
+    encoder.encode_op (op);
+  }
+
+  static void flush_width (cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    assert (env.has_width);
+    str_encoder_t  encoder (param.flatStr);
+    encoder.encode_num (env.width);
+  }
+
+  static void flush_hintmask (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    SUPER::flush_hintmask (op, env, param);
+    if (!param.drop_hints)
+    {
+      str_encoder_t  encoder (param.flatStr);
+      for (unsigned int i = 0; i < env.hintmask_size; i++)
+        encoder.encode_byte (env.str_ref[i]);
+    }
+  }
+
+  private:
+  typedef cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatten_param_t> SUPER;
+};
+
+struct range_list_t : hb_vector_t<code_pair_t>
+{
+  /* replace the first glyph ID in the "glyph" field each range with a nLeft value */
+  bool finalize (unsigned int last_glyph)
+  {
+    bool  two_byte = false;
+    for (unsigned int i = (*this).length; i > 0; i--)
+    {
+      code_pair_t &pair = (*this)[i - 1];
+      unsigned int  nLeft = last_glyph - pair.glyph - 1;
+      if (nLeft >= 0x100)
+        two_byte = true;
+      last_glyph = pair.glyph;
+      pair.glyph = nLeft;
+    }
+    return two_byte;
+  }
+};
+
+struct cff1_cs_opset_subr_subset_t : cff1_cs_opset_t<cff1_cs_opset_subr_subset_t, subr_subset_param_t>
+{
+  static void process_op (op_code_t op, cff1_cs_interp_env_t &env, subr_subset_param_t& param)
+  {
+    switch (op) {
+
+      case OpCode_return:
+        param.current_parsed_str->add_op (op, env.str_ref);
+        param.current_parsed_str->set_parsed ();
+        env.returnFromSubr ();
+        param.set_current_str (env, false);
+        break;
+
+      case OpCode_endchar:
+        param.current_parsed_str->add_op (op, env.str_ref);
+        param.current_parsed_str->set_parsed ();
+        SUPER::process_op (op, env, param);
+        break;
+
+      case OpCode_callsubr:
+        process_call_subr (op, CSType_LocalSubr, env, param, env.localSubrs, param.local_closure);
+        break;
+
+      case OpCode_callgsubr:
+        process_call_subr (op, CSType_GlobalSubr, env, param, env.globalSubrs, param.global_closure);
+        break;
+
+      default:
+        SUPER::process_op (op, env, param);
+        param.current_parsed_str->add_op (op, env.str_ref);
+        break;
+    }
+  }
+
+  protected:
+  static void process_call_subr (op_code_t op, cs_type_t type,
+                                 cff1_cs_interp_env_t &env, subr_subset_param_t& param,
+                                 cff1_biased_subrs_t& subrs, hb_set_t *closure)
+  {
+    byte_str_ref_t    str_ref = env.str_ref;
+    env.callSubr (subrs, type);
+    param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num);
+    hb_set_add (closure, env.context.subr_num);
+    param.set_current_str (env, true);
+  }
+
+  private:
+  typedef cff1_cs_opset_t<cff1_cs_opset_subr_subset_t, subr_subset_param_t> SUPER;
+};
+
+struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs, const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_subr_subset_t>
+{
+  static void finalize_parsed_str (cff1_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
+  {
+    /* insert width at the beginning of the charstring as necessary */
+    if (env.has_width)
+      charstring.set_prefix (env.width);
+
+    /* subroutines/charstring left on the call stack are legally left unmarked
+     * unmarked when a subroutine terminates with endchar. mark them.
+     */
+    param.current_parsed_str->set_parsed ();
+    for (unsigned int i = 0; i < env.callStack.get_count (); i++)
+    {
+      parsed_cs_str_t  *parsed_str = param.get_parsed_str_for_context (env.callStack[i]);
+      if (likely (parsed_str != nullptr))
+        parsed_str->set_parsed ();
+      else
+        env.set_error ();
+    }
+  }
+};
+
+struct cff_subset_plan {
+  cff_subset_plan ()
+    : final_size (0),
+      offsets (),
+      orig_fdcount (0),
+      subset_fdcount (1),
+      subset_fdselect_format (0),
+      drop_hints (false),
+      desubroutinize(false)
+  {
+    topdict_sizes.init ();
+    topdict_sizes.resize (1);
+    topdict_mod.init ();
+    subset_fdselect_ranges.init ();
+    fdmap.init ();
+    subset_charstrings.init ();
+    subset_globalsubrs.init ();
+    subset_localsubrs.init ();
+    fontdicts_mod.init ();
+    subset_enc_code_ranges.init ();
+    subset_enc_supp_codes.init ();
+    subset_charset_ranges.init ();
+    sidmap.init ();
+    for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
+      topDictModSIDs[i] = CFF_UNDEF_SID;
+  }
+
+  ~cff_subset_plan ()
+  {
+    topdict_sizes.fini ();
+    topdict_mod.fini ();
+    subset_fdselect_ranges.fini ();
+    fdmap.fini ();
+    subset_charstrings.fini_deep ();
+    subset_globalsubrs.fini_deep ();
+    subset_localsubrs.fini_deep ();
+    fontdicts_mod.fini ();
+    subset_enc_code_ranges.fini ();
+    subset_enc_supp_codes.fini ();
+    subset_charset_ranges.fini ();
+    sidmap.fini ();
+  }
+
+  unsigned int plan_subset_encoding (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
+  {
+    const Encoding *encoding = acc.encoding;
+    unsigned int  size0, size1, supp_size;
+    hb_codepoint_t  code, last_code = CFF_UNDEF_CODE;
+    hb_vector_t<hb_codepoint_t> supp_codes;
+
+    subset_enc_code_ranges.resize (0);
+    supp_size = 0;
+    supp_codes.init ();
+
+    subset_enc_num_codes = plan->glyphs.length - 1;
+    unsigned int glyph;
+    for (glyph = 1; glyph < plan->glyphs.length; glyph++)
+    {
+      hb_codepoint_t  orig_glyph = plan->glyphs[glyph];
+      code = acc.glyph_to_code (orig_glyph);
+      if (code == CFF_UNDEF_CODE)
+      {
+        subset_enc_num_codes = glyph - 1;
+        break;
+      }
+
+      if (code != last_code + 1)
+      {
+        code_pair_t pair = { code, glyph };
+        subset_enc_code_ranges.push (pair);
+      }
+      last_code = code;
+
+      if (encoding != &Null(Encoding))
+      {
+        hb_codepoint_t  sid = acc.glyph_to_sid (orig_glyph);
+        encoding->get_supplement_codes (sid, supp_codes);
+        for (unsigned int i = 0; i < supp_codes.length; i++)
+        {
+          code_pair_t pair = { supp_codes[i], sid };
+          subset_enc_supp_codes.push (pair);
+        }
+        supp_size += SuppEncoding::static_size * supp_codes.length;
+      }
+    }
+    supp_codes.fini ();
+
+    subset_enc_code_ranges.finalize (glyph);
+
+    assert (subset_enc_num_codes <= 0xFF);
+    size0 = Encoding0::min_size + HBUINT8::static_size * subset_enc_num_codes;
+    size1 = Encoding1::min_size + Encoding1_Range::static_size * subset_enc_code_ranges.length;
+
+    if (size0 < size1)
+      subset_enc_format = 0;
+    else
+      subset_enc_format = 1;
+
+    return Encoding::calculate_serialized_size (
+                        subset_enc_format,
+                        subset_enc_format? subset_enc_code_ranges.length: subset_enc_num_codes,
+                        subset_enc_supp_codes.length);
+  }
+
+  unsigned int plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
+  {
+    unsigned int  size0, size_ranges;
+    hb_codepoint_t  sid, last_sid = CFF_UNDEF_CODE;
+
+    subset_charset_ranges.resize (0);
+    unsigned int glyph;
+    for (glyph = 1; glyph < plan->glyphs.length; glyph++)
+    {
+      hb_codepoint_t  orig_glyph = plan->glyphs[glyph];
+      sid = acc.glyph_to_sid (orig_glyph);
+
+      if (!acc.is_CID ())
+        sid = sidmap.add (sid);
+
+      if (sid != last_sid + 1)
+      {
+        code_pair_t pair = { sid, glyph };
+        subset_charset_ranges.push (pair);
+      }
+      last_sid = sid;
+    }
+
+    bool two_byte = subset_charset_ranges.finalize (glyph);
+
+    size0 = Charset0::min_size + HBUINT16::static_size * (plan->glyphs.length - 1);
+    if (!two_byte)
+      size_ranges = Charset1::min_size + Charset1_Range::static_size * subset_charset_ranges.length;
+    else
+      size_ranges = Charset2::min_size + Charset2_Range::static_size * subset_charset_ranges.length;
+
+    if (size0 < size_ranges)
+      subset_charset_format = 0;
+    else if (!two_byte)
+      subset_charset_format = 1;
+    else
+      subset_charset_format = 2;
+
+    return Charset::calculate_serialized_size (
+                        subset_charset_format,
+                        subset_charset_format? subset_charset_ranges.length: plan->glyphs.length);
+  }
+
+  bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc)
+  {
+    if (unlikely (!sidmap.reset (acc.stringIndex->count)))
+      return false;
+
+    for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
+    {
+      unsigned int sid = acc.topDict.nameSIDs[i];
+      if (sid != CFF_UNDEF_SID)
+      {
+        (void)sidmap.add (sid);
+        topDictModSIDs[i] = sidmap[sid];
+      }
+    }
+
+    if (acc.fdArray != &Null(CFF1FDArray))
+      for (unsigned int i = 0; i < orig_fdcount; i++)
+        if (fdmap.includes (i))
+          (void)sidmap.add (acc.fontDicts[i].fontName);
+
+    return true;
+  }
+
+  bool create (const OT::cff1::accelerator_subset_t &acc,
+                      hb_subset_plan_t *plan)
+  {
+     /* make sure notdef is first */
+    if ((plan->glyphs.length == 0) || (plan->glyphs[0] != 0)) return false;
+
+    final_size = 0;
+    num_glyphs = plan->glyphs.length;
+    orig_fdcount = acc.fdCount;
+    drop_hints = plan->drop_hints;
+    desubroutinize = plan->desubroutinize;
+
+    /* check whether the subset renumbers any glyph IDs */
+    gid_renum = false;
+    for (unsigned int glyph = 0; glyph < plan->glyphs.length; glyph++)
+    {
+      if (plan->glyphs[glyph] != glyph) {
+        gid_renum = true;
+        break;
+      }
+    }
+
+    subset_charset = gid_renum || !acc.is_predef_charset ();
+    subset_encoding = !acc.is_CID() && !acc.is_predef_encoding ();
+
+    /* CFF header */
+    final_size += OT::cff1::static_size;
+
+    /* Name INDEX */
+    offsets.nameIndexOffset = final_size;
+    final_size += acc.nameIndex->get_size ();
+
+    /* top dict INDEX */
+    {
+      /* Add encoding/charset to a (copy of) top dict as necessary */
+      topdict_mod.init (&acc.topDict);
+      bool need_to_add_enc = (subset_encoding && !acc.topDict.has_op (OpCode_Encoding));
+      bool need_to_add_set = (subset_charset && !acc.topDict.has_op (OpCode_charset));
+      if (need_to_add_enc || need_to_add_set)
+      {
+        if (need_to_add_enc)
+          topdict_mod.add_op (OpCode_Encoding);
+        if (need_to_add_set)
+          topdict_mod.add_op (OpCode_charset);
+      }
+      offsets.topDictInfo.offset = final_size;
+      cff1_top_dict_op_serializer_t topSzr;
+      unsigned int topDictSize = TopDict::calculate_serialized_size (topdict_mod, topSzr);
+      offsets.topDictInfo.offSize = calcOffSize(topDictSize);
+      if (unlikely (offsets.topDictInfo.offSize > 4))
+        return false;
+      final_size += CFF1IndexOf<TopDict>::calculate_serialized_size<cff1_top_dict_values_mod_t>
+                                                (offsets.topDictInfo.offSize,
+                                                 &topdict_mod, 1, topdict_sizes, topSzr);
+    }
+
+    /* Determine re-mapping of font index as fdmap among other info */
+    if (acc.fdSelect != &Null(CFF1FDSelect))
+    {
+        if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs,
+                                  orig_fdcount,
+                                  *acc.fdSelect,
+                                  subset_fdcount,
+                                  offsets.FDSelectInfo.size,
+                                  subset_fdselect_format,
+                                  subset_fdselect_ranges,
+                                  fdmap)))
+        return false;
+    }
+    else
+      fdmap.identity (1);
+
+    /* remove unused SIDs & reassign SIDs */
+    {
+      /* SIDs for name strings in dicts are added before glyph names so they fit in 16-bit int range */
+      if (unlikely (!collect_sids_in_dicts (acc)))
+        return false;
+      if (unlikely (sidmap.get_count () > 0x8000))      /* assumption: a dict won't reference that many strings */
+        return false;
+      if (subset_charset)
+        offsets.charsetInfo.size = plan_subset_charset (acc, plan);
+
+      topdict_mod.reassignSIDs (sidmap);
+    }
+
+    /* String INDEX */
+    {
+      offsets.stringIndexInfo.offset = final_size;
+      offsets.stringIndexInfo.size = acc.stringIndex->calculate_serialized_size (offsets.stringIndexInfo.offSize, sidmap);
+      final_size += offsets.stringIndexInfo.size;
+    }
+
+    if (desubroutinize)
+    {
+      /* Flatten global & local subrs */
+      subr_flattener_t<const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_flatten_t>
+                    flattener(acc, plan->glyphs, plan->drop_hints);
+      if (!flattener.flatten (subset_charstrings))
+        return false;
+
+      /* no global/local subroutines */
+      offsets.globalSubrsInfo.size = CFF1Subrs::calculate_serialized_size (1, 0, 0);
+    }
+    else
+    {
+      /* Subset subrs: collect used subroutines, leaving all unused ones behind */
+      if (!subr_subsetter.subset (acc, plan->glyphs, plan->drop_hints))
+        return false;
+
+      /* encode charstrings, global subrs, local subrs with new subroutine numbers */
+      if (!subr_subsetter.encode_charstrings (acc, plan->glyphs, subset_charstrings))
+        return false;
+
+      if (!subr_subsetter.encode_globalsubrs (subset_globalsubrs))
+        return false;
+
+      /* global subrs */
+      unsigned int dataSize = subset_globalsubrs.total_size ();
+      offsets.globalSubrsInfo.offSize = calcOffSize (dataSize);
+      if (unlikely (offsets.globalSubrsInfo.offSize > 4))
+        return false;
+      offsets.globalSubrsInfo.size = CFF1Subrs::calculate_serialized_size (offsets.globalSubrsInfo.offSize, subset_globalsubrs.length, dataSize);
+
+      /* local subrs */
+      if (!offsets.localSubrsInfos.resize (orig_fdcount))
+        return false;
+      if (!subset_localsubrs.resize (orig_fdcount))
+        return false;
+      for (unsigned int fd = 0; fd < orig_fdcount; fd++)
+      {
+        subset_localsubrs[fd].init ();
+        offsets.localSubrsInfos[fd].init ();
+        if (fdmap.includes (fd))
+        {
+          if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
+            return false;
+
+          unsigned int dataSize = subset_localsubrs[fd].total_size ();
+          if (dataSize > 0)
+          {
+            offsets.localSubrsInfos[fd].offset = final_size;
+            offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
+            if (unlikely (offsets.localSubrsInfos[fd].offSize > 4))
+              return false;
+            offsets.localSubrsInfos[fd].size = CFF1Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
+          }
+        }
+      }
+    }
+
+    /* global subrs */
+    offsets.globalSubrsInfo.offset = final_size;
+    final_size += offsets.globalSubrsInfo.size;
+
+    /* Encoding */
+    if (!subset_encoding)
+      offsets.encodingOffset = acc.topDict.EncodingOffset;
+    else
+    {
+      offsets.encodingOffset = final_size;
+      final_size += plan_subset_encoding (acc, plan);
+    }
+
+    /* Charset */
+    if (!subset_charset && acc.is_predef_charset ())
+      offsets.charsetInfo.offset = acc.topDict.CharsetOffset;
+    else
+      offsets.charsetInfo.offset = final_size;
+    final_size += offsets.charsetInfo.size;
+
+    /* FDSelect */
+    if (acc.fdSelect != &Null(CFF1FDSelect))
+    {
+      offsets.FDSelectInfo.offset = final_size;
+      final_size += offsets.FDSelectInfo.size;
+    }
+
+    /* FDArray (FDIndex) */
+    if (acc.fdArray != &Null(CFF1FDArray)) {
+      offsets.FDArrayInfo.offset = final_size;
+      cff1_font_dict_op_serializer_t fontSzr;
+      unsigned int dictsSize = 0;
+      for (unsigned int i = 0; i < acc.fontDicts.length; i++)
+        if (fdmap.includes (i))
+          dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr);
+
+      offsets.FDArrayInfo.offSize = calcOffSize (dictsSize);
+      if (unlikely (offsets.FDArrayInfo.offSize > 4))
+        return false;
+      final_size += CFF1Index::calculate_serialized_size (offsets.FDArrayInfo.offSize, subset_fdcount, dictsSize);
+    }
+
+    /* CharStrings */
+    {
+      offsets.charStringsInfo.offset = final_size;
+      unsigned int dataSize = subset_charstrings.total_size ();
+      offsets.charStringsInfo.offSize = calcOffSize (dataSize);
+      if (unlikely (offsets.charStringsInfo.offSize > 4))
+        return false;
+      final_size += CFF1CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->glyphs.length, dataSize);
+    }
+
+    /* private dicts & local subrs */
+    offsets.privateDictInfo.offset = final_size;
+    for (unsigned int i = 0; i < orig_fdcount; i++)
+    {
+      if (fdmap.includes (i))
+      {
+        bool  has_localsubrs = offsets.localSubrsInfos[i].size > 0;
+        cff_private_dict_op_serializer_t privSzr (desubroutinize, plan->drop_hints);
+        unsigned int  priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr, has_localsubrs);
+        table_info_t  privInfo = { final_size, priv_size, 0 };
+        font_dict_values_mod_t fontdict_mod;
+        if (!acc.is_CID ())
+          fontdict_mod.init ( &Null(cff1_font_dict_values_t), CFF_UNDEF_SID, privInfo );
+        else
+          fontdict_mod.init ( &acc.fontDicts[i], sidmap[acc.fontDicts[i].fontName], privInfo );
+        fontdicts_mod.push (fontdict_mod);
+        final_size += privInfo.size;
+
+        if (!plan->desubroutinize && has_localsubrs)
+        {
+          offsets.localSubrsInfos[i].offset = final_size;
+          final_size += offsets.localSubrsInfos[i].size;
+        }
+      }
+    }
+
+    if (!acc.is_CID ())
+      offsets.privateDictInfo = fontdicts_mod[0].privateDictInfo;
+
+    return ((subset_charstrings.length == plan->glyphs.length)
+           && (fontdicts_mod.length == subset_fdcount));
+  }
+
+  unsigned int get_final_size () const  { return final_size; }
+
+  unsigned int        final_size;
+  hb_vector_t<unsigned int>     topdict_sizes;
+  cff1_top_dict_values_mod_t    topdict_mod;
+  cff1_sub_table_offsets_t      offsets;
+
+  unsigned int    num_glyphs;
+  unsigned int    orig_fdcount;
+  unsigned int    subset_fdcount;
+  unsigned int    subset_fdselect_format;
+  hb_vector_t<code_pair_t>   subset_fdselect_ranges;
+
+  /* font dict index remap table from fullset FDArray to subset FDArray.
+   * set to CFF_UNDEF_CODE if excluded from subset */
+  remap_t   fdmap;
+
+  str_buff_vec_t                subset_charstrings;
+  str_buff_vec_t                subset_globalsubrs;
+  hb_vector_t<str_buff_vec_t>   subset_localsubrs;
+  hb_vector_t<font_dict_values_mod_t>  fontdicts_mod;
+
+  bool          drop_hints;
+
+  bool          gid_renum;
+  bool          subset_encoding;
+  uint8_t       subset_enc_format;
+  unsigned int  subset_enc_num_codes;
+  range_list_t  subset_enc_code_ranges;
+  hb_vector_t<code_pair_t>  subset_enc_supp_codes;
+
+  uint8_t       subset_charset_format;
+  range_list_t  subset_charset_ranges;
+  bool          subset_charset;
+
+  remap_sid_t   sidmap;
+  unsigned int  topDictModSIDs[name_dict_values_t::ValCount];
+
+  bool          desubroutinize;
+  cff1_subr_subsetter_t       subr_subsetter;
+};
+
+static inline bool _write_cff1 (const cff_subset_plan &plan,
+                                const OT::cff1::accelerator_subset_t  &acc,
+                                const hb_vector_t<hb_codepoint_t>& glyphs,
+                                unsigned int dest_sz,
+                                void *dest)
+{
+  hb_serialize_context_t c (dest, dest_sz);
+
+  OT::cff1 *cff = c.start_serialize<OT::cff1> ();
+  if (unlikely (!c.extend_min (*cff)))
+    return false;
+
+  /* header */
+  cff->version.major.set (0x01);
+  cff->version.minor.set (0x00);
+  cff->nameIndex.set (cff->min_size);
+  cff->offSize.set (4); /* unused? */
+
+  /* name INDEX */
+  {
+    assert (cff->nameIndex == (unsigned) (c.head - c.start));
+    CFF1NameIndex *dest = c.start_embed<CFF1NameIndex> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c, *acc.nameIndex)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF name INDEX");
+      return false;
+    }
+  }
+
+  /* top dict INDEX */
+  {
+    assert (plan.offsets.topDictInfo.offset == (unsigned) (c.head - c.start));
+    CFF1IndexOf<TopDict> *dest = c.start_embed< CFF1IndexOf<TopDict> > ();
+    if (dest == nullptr) return false;
+    cff1_top_dict_op_serializer_t topSzr;
+    top_dict_modifiers_t  modifier (plan.offsets, plan.topDictModSIDs);
+    if (unlikely (!dest->serialize (&c, plan.offsets.topDictInfo.offSize,
+                                    &plan.topdict_mod, 1,
+                                    plan.topdict_sizes, topSzr, modifier)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF top dict");
+      return false;
+    }
+  }
+
+  /* String INDEX */
+  {
+    assert (plan.offsets.stringIndexInfo.offset == (unsigned) (c.head - c.start));
+    CFF1StringIndex *dest = c.start_embed<CFF1StringIndex> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c, *acc.stringIndex, plan.offsets.stringIndexInfo.offSize, plan.sidmap)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF string INDEX");
+      return false;
+    }
+  }
+
+  /* global subrs */
+  {
+    assert (plan.offsets.globalSubrsInfo.offset != 0);
+    assert (plan.offsets.globalSubrsInfo.offset == (unsigned) (c.head - c.start));
+
+    CFF1Subrs *dest = c.start_embed <CFF1Subrs> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c, plan.offsets.globalSubrsInfo.offSize, plan.subset_globalsubrs)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize global subroutines");
+      return false;
+    }
+  }
+
+  /* Encoding */
+  if (plan.subset_encoding)
+  {
+    assert (plan.offsets.encodingOffset == (unsigned) (c.head - c.start));
+    Encoding *dest = c.start_embed<Encoding> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c,
+                                    plan.subset_enc_format,
+                                    plan.subset_enc_num_codes,
+                                    plan.subset_enc_code_ranges,
+                                    plan.subset_enc_supp_codes)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize Encoding");
+      return false;
+    }
+  }
+
+  /* Charset */
+  if (plan.subset_charset)
+  {
+    assert (plan.offsets.charsetInfo.offset == (unsigned) (c.head - c.start));
+    Charset *dest = c.start_embed<Charset> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c,
+                                    plan.subset_charset_format,
+                                    plan.num_glyphs,
+                                    plan.subset_charset_ranges)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize Charset");
+      return false;
+    }
+  }
+
+  /* FDSelect */
+  if (acc.fdSelect != &Null(CFF1FDSelect))
+  {
+    assert (plan.offsets.FDSelectInfo.offset == (unsigned) (c.head - c.start));
+
+    if (unlikely (!hb_serialize_cff_fdselect (&c, glyphs.length, *acc.fdSelect, acc.fdCount,
+                                              plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size,
+                                              plan.subset_fdselect_ranges)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF subset FDSelect");
+      return false;
+    }
+  }
+
+  /* FDArray (FD Index) */
+  if (acc.fdArray != &Null(CFF1FDArray))
+  {
+    assert (plan.offsets.FDArrayInfo.offset == (unsigned) (c.head - c.start));
+    CFF1FDArray  *fda = c.start_embed<CFF1FDArray> ();
+    if (unlikely (fda == nullptr)) return false;
+    cff1_font_dict_op_serializer_t  fontSzr;
+    if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize,
+                                   plan.fontdicts_mod,
+                                   fontSzr)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF FDArray");
+      return false;
+    }
+  }
+
+  /* CharStrings */
+  {
+    assert (plan.offsets.charStringsInfo.offset == (unsigned) (c.head - c.start));
+    CFF1CharStrings  *cs = c.start_embed<CFF1CharStrings> ();
+    if (unlikely (cs == nullptr)) return false;
+    if (unlikely (!cs->serialize (&c, plan.offsets.charStringsInfo.offSize, plan.subset_charstrings)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF CharStrings");
+      return false;
+    }
+  }
+
+  /* private dicts & local subrs */
+  assert (plan.offsets.privateDictInfo.offset == (unsigned) (c.head - c.start));
+  for (unsigned int i = 0; i < acc.privateDicts.length; i++)
+  {
+    if (plan.fdmap.includes (i))
+    {
+      PrivateDict  *pd = c.start_embed<PrivateDict> ();
+      if (unlikely (pd == nullptr)) return false;
+      unsigned int priv_size = plan.fontdicts_mod[plan.fdmap[i]].privateDictInfo.size;
+      bool result;
+      cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
+      /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
+      unsigned int  subroffset = (plan.offsets.localSubrsInfos[i].size > 0)? priv_size: 0;
+      result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
+      if (unlikely (!result))
+      {
+        DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
+        return false;
+      }
+      if (plan.offsets.localSubrsInfos[i].size > 0)
+      {
+        CFF1Subrs *dest = c.start_embed <CFF1Subrs> ();
+        if (unlikely (dest == nullptr)) return false;
+        if (unlikely (!dest->serialize (&c, plan.offsets.localSubrsInfos[i].offSize, plan.subset_localsubrs[i])))
+        {
+          DEBUG_MSG (SUBSET, nullptr, "failed to serialize local subroutines");
+          return false;
+        }
+      }
+    }
+  }
+
+  assert (c.head == c.end);
+  c.end_serialize ();
+
+  return true;
+}
+
+static bool
+_hb_subset_cff1 (const OT::cff1::accelerator_subset_t  &acc,
+                const char              *data,
+                hb_subset_plan_t        *plan,
+                hb_blob_t               **prime /* OUT */)
+{
+  cff_subset_plan cff_plan;
+
+  if (unlikely (!cff_plan.create (acc, plan)))
+  {
+    DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff subsetting plan.");
+    return false;
+  }
+
+  unsigned int  cff_prime_size = cff_plan.get_final_size ();
+  char *cff_prime_data = (char *) calloc (1, cff_prime_size);
+
+  if (unlikely (!_write_cff1 (cff_plan, acc, plan->glyphs,
+                              cff_prime_size, cff_prime_data))) {
+    DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff.");
+    free (cff_prime_data);
+    return false;
+  }
+
+  *prime = hb_blob_create (cff_prime_data,
+                           cff_prime_size,
+                           HB_MEMORY_MODE_READONLY,
+                           cff_prime_data,
+                           free);
+  return true;
+}
+
+/**
+ * hb_subset_cff1:
+ * Subsets the CFF table according to a provided plan.
+ *
+ * Return value: subsetted cff table.
+ **/
+bool
+hb_subset_cff1 (hb_subset_plan_t *plan,
+                hb_blob_t       **prime /* OUT */)
+{
+  hb_blob_t *cff_blob = hb_sanitize_context_t().reference_table<CFF::cff1> (plan->source);
+  const char *data = hb_blob_get_data(cff_blob, nullptr);
+
+  OT::cff1::accelerator_subset_t acc;
+  acc.init(plan->source);
+  bool result = likely (acc.is_valid ()) &&
+                        _hb_subset_cff1 (acc, data, plan, prime);
+  hb_blob_destroy (cff_blob);
+  acc.fini ();
+
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff1.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,38 @@
+/*
+ * 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_SUBSET_CFF1_HH
+#define HB_SUBSET_CFF1_HH
+
+#include "hb.hh"
+
+#include "hb-subset-plan.hh"
+
+HB_INTERNAL bool
+hb_subset_cff1 (hb_subset_plan_t *plan,
+               hb_blob_t        **cff_prime /* OUT */);
+
+#endif /* HB_SUBSET_CFF1_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff2.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,624 @@
+/*
+ * 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
+ */
+
+#include "hb-open-type.hh"
+#include "hb-ot-cff2-table.hh"
+#include "hb-set.h"
+#include "hb-subset-cff2.hh"
+#include "hb-subset-plan.hh"
+#include "hb-subset-cff-common.hh"
+#include "hb-cff2-interp-cs.hh"
+
+using namespace CFF;
+
+struct cff2_sub_table_offsets_t : cff_sub_table_offsets_t
+{
+  cff2_sub_table_offsets_t ()
+    : cff_sub_table_offsets_t (),
+      varStoreOffset (0)
+  {}
+
+  unsigned int  varStoreOffset;
+};
+
+struct cff2_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<>
+{
+  bool serialize (hb_serialize_context_t *c,
+                  const op_str_t &opstr,
+                  const cff2_sub_table_offsets_t &offsets) const
+  {
+    TRACE_SERIALIZE (this);
+
+    switch (opstr.op)
+    {
+      case OpCode_vstore:
+        return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.varStoreOffset));
+
+      default:
+        return_trace (cff_top_dict_op_serializer_t<>::serialize (c, opstr, offsets));
+    }
+  }
+
+  unsigned int calculate_serialized_size (const op_str_t &opstr) const
+  {
+    switch (opstr.op)
+    {
+      case OpCode_vstore:
+        return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
+
+      default:
+        return cff_top_dict_op_serializer_t<>::calculate_serialized_size (opstr);
+    }
+  }
+};
+
+struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t>
+{
+  static void flush_args_and_op (op_code_t op, cff2_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    switch (op)
+    {
+      case OpCode_return:
+      case OpCode_endchar:
+        /* dummy opcodes in CFF2. ignore */
+        break;
+
+      case OpCode_hstem:
+      case OpCode_hstemhm:
+      case OpCode_vstem:
+      case OpCode_vstemhm:
+      case OpCode_hintmask:
+      case OpCode_cntrmask:
+        if (param.drop_hints)
+        {
+          env.clear_args ();
+          return;
+        }
+        HB_FALLTHROUGH;
+
+      default:
+        SUPER::flush_args_and_op (op, env, param);
+        break;
+    }
+  }
+
+  static void flush_args (cff2_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    for (unsigned int i = 0; i < env.argStack.get_count ();)
+    {
+      const blend_arg_t &arg = env.argStack[i];
+      if (arg.blending ())
+      {
+        if (unlikely (!((arg.numValues > 0) && (env.argStack.get_count () >= arg.numValues))))
+        {
+          env.set_error ();
+          return;
+        }
+        flatten_blends (arg, i, env, param);
+        i += arg.numValues;
+      }
+      else
+      {
+        str_encoder_t  encoder (param.flatStr);
+        encoder.encode_num (arg);
+        i++;
+      }
+    }
+    SUPER::flush_args (env, param);
+  }
+
+  static void flatten_blends (const blend_arg_t &arg, unsigned int i, cff2_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    /* flatten the default values */
+    str_encoder_t  encoder (param.flatStr);
+    for (unsigned int j = 0; j < arg.numValues; j++)
+    {
+      const blend_arg_t &arg1 = env.argStack[i + j];
+      if (unlikely (!((arg1.blending () && (arg.numValues == arg1.numValues) && (arg1.valueIndex == j) &&
+              (arg1.deltas.length == env.get_region_count ())))))
+      {
+        env.set_error ();
+        return;
+      }
+      encoder.encode_num (arg1);
+    }
+    /* flatten deltas for each value */
+    for (unsigned int j = 0; j < arg.numValues; j++)
+    {
+      const blend_arg_t &arg1 = env.argStack[i + j];
+      for (unsigned int k = 0; k < arg1.deltas.length; k++)
+        encoder.encode_num (arg1.deltas[k]);
+    }
+    /* flatten the number of values followed by blend operator */
+    encoder.encode_int (arg.numValues);
+    encoder.encode_op (OpCode_blendcs);
+  }
+
+  static void flush_op (op_code_t op, cff2_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    switch (op)
+    {
+      case OpCode_return:
+      case OpCode_endchar:
+        return;
+      default:
+        str_encoder_t  encoder (param.flatStr);
+        encoder.encode_op (op);
+    }
+  }
+
+  private:
+  typedef cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t> SUPER;
+  typedef cs_opset_t<blend_arg_t, cff2_cs_opset_flatten_t, cff2_cs_opset_flatten_t, cff2_cs_interp_env_t, flatten_param_t> CSOPSET;
+};
+
+struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t>
+{
+  static void process_op (op_code_t op, cff2_cs_interp_env_t &env, subr_subset_param_t& param)
+  {
+    switch (op) {
+
+      case OpCode_return:
+        param.current_parsed_str->set_parsed ();
+        env.returnFromSubr ();
+        param.set_current_str (env, false);
+        break;
+
+      case OpCode_endchar:
+        param.current_parsed_str->set_parsed ();
+        SUPER::process_op (op, env, param);
+        break;
+
+      case OpCode_callsubr:
+        process_call_subr (op, CSType_LocalSubr, env, param, env.localSubrs, param.local_closure);
+        break;
+
+      case OpCode_callgsubr:
+        process_call_subr (op, CSType_GlobalSubr, env, param, env.globalSubrs, param.global_closure);
+        break;
+
+      default:
+        SUPER::process_op (op, env, param);
+        param.current_parsed_str->add_op (op, env.str_ref);
+        break;
+    }
+  }
+
+  protected:
+  static void process_call_subr (op_code_t op, cs_type_t type,
+                                 cff2_cs_interp_env_t &env, subr_subset_param_t& param,
+                                 cff2_biased_subrs_t& subrs, hb_set_t *closure)
+  {
+    byte_str_ref_t    str_ref = env.str_ref;
+    env.callSubr (subrs, type);
+    param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num);
+    hb_set_add (closure, env.context.subr_num);
+    param.set_current_str (env, true);
+  }
+
+  private:
+  typedef cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t> SUPER;
+};
+
+struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs, const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_subr_subset_t>
+{
+  static void finalize_parsed_str (cff2_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
+  {
+    /* vsindex is inserted at the beginning of the charstring as necessary */
+    if (env.seen_vsindex ())
+    {
+      number_t  ivs;
+      ivs.set_int ((int)env.get_ivs ());
+      charstring.set_prefix (ivs, OpCode_vsindexcs);
+    }
+  }
+};
+
+struct cff2_subset_plan {
+  cff2_subset_plan ()
+    : final_size (0),
+      orig_fdcount (0),
+      subset_fdcount(1),
+      subset_fdselect_format (0),
+      drop_hints (false),
+      desubroutinize (false)
+  {
+    subset_fdselect_ranges.init ();
+    fdmap.init ();
+    subset_charstrings.init ();
+    subset_globalsubrs.init ();
+    subset_localsubrs.init ();
+    privateDictInfos.init ();
+  }
+
+  ~cff2_subset_plan ()
+  {
+    subset_fdselect_ranges.fini ();
+    fdmap.fini ();
+    subset_charstrings.fini_deep ();
+    subset_globalsubrs.fini_deep ();
+    subset_localsubrs.fini_deep ();
+    privateDictInfos.fini ();
+  }
+
+  bool create (const OT::cff2::accelerator_subset_t &acc,
+              hb_subset_plan_t *plan)
+  {
+    final_size = 0;
+    orig_fdcount = acc.fdArray->count;
+
+    drop_hints = plan->drop_hints;
+    desubroutinize = plan->desubroutinize;
+
+    /* CFF2 header */
+    final_size += OT::cff2::static_size;
+
+    /* top dict */
+    {
+      cff2_top_dict_op_serializer_t topSzr;
+      offsets.topDictInfo.size = TopDict::calculate_serialized_size (acc.topDict, topSzr);
+      final_size += offsets.topDictInfo.size;
+    }
+
+    if (desubroutinize)
+    {
+      /* Flatten global & local subrs */
+      subr_flattener_t<const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_flatten_t>
+                    flattener(acc, plan->glyphs, plan->drop_hints);
+      if (!flattener.flatten (subset_charstrings))
+        return false;
+
+      /* no global/local subroutines */
+      offsets.globalSubrsInfo.size = CFF2Subrs::calculate_serialized_size (1, 0, 0);
+    }
+    else
+    {
+      /* Subset subrs: collect used subroutines, leaving all unused ones behind */
+      if (!subr_subsetter.subset (acc, plan->glyphs, plan->drop_hints))
+        return false;
+
+      /* encode charstrings, global subrs, local subrs with new subroutine numbers */
+      if (!subr_subsetter.encode_charstrings (acc, plan->glyphs, subset_charstrings))
+        return false;
+
+      if (!subr_subsetter.encode_globalsubrs (subset_globalsubrs))
+        return false;
+
+      /* global subrs */
+      unsigned int dataSize = subset_globalsubrs.total_size ();
+      offsets.globalSubrsInfo.offSize = calcOffSize (dataSize);
+      offsets.globalSubrsInfo.size = CFF2Subrs::calculate_serialized_size (offsets.globalSubrsInfo.offSize, subset_globalsubrs.length, dataSize);
+
+      /* local subrs */
+      if (!offsets.localSubrsInfos.resize (orig_fdcount))
+        return false;
+      if (!subset_localsubrs.resize (orig_fdcount))
+        return false;
+      for (unsigned int fd = 0; fd < orig_fdcount; fd++)
+      {
+        subset_localsubrs[fd].init ();
+        offsets.localSubrsInfos[fd].init ();
+        if (fdmap.includes (fd))
+        {
+          if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
+            return false;
+
+          unsigned int dataSize = subset_localsubrs[fd].total_size ();
+          if (dataSize > 0)
+          {
+            offsets.localSubrsInfos[fd].offset = final_size;
+            offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
+            offsets.localSubrsInfos[fd].size = CFF2Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
+          }
+        }
+      }
+    }
+
+    /* global subrs */
+    offsets.globalSubrsInfo.offset = final_size;
+    final_size += offsets.globalSubrsInfo.size;
+
+    /* variation store */
+    if (acc.varStore != &Null(CFF2VariationStore))
+    {
+      offsets.varStoreOffset = final_size;
+      final_size += acc.varStore->get_size ();
+    }
+
+    /* FDSelect */
+    if (acc.fdSelect != &Null(CFF2FDSelect))
+    {
+      offsets.FDSelectInfo.offset = final_size;
+      if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs,
+                                  orig_fdcount,
+                                  *(const FDSelect *)acc.fdSelect,
+                                  subset_fdcount,
+                                  offsets.FDSelectInfo.size,
+                                  subset_fdselect_format,
+                                  subset_fdselect_ranges,
+                                  fdmap)))
+        return false;
+
+      final_size += offsets.FDSelectInfo.size;
+    }
+    else
+      fdmap.identity (1);
+
+    /* FDArray (FDIndex) */
+    {
+      offsets.FDArrayInfo.offset = final_size;
+      cff_font_dict_op_serializer_t fontSzr;
+      unsigned int dictsSize = 0;
+      for (unsigned int i = 0; i < acc.fontDicts.length; i++)
+        if (fdmap.includes (i))
+          dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr);
+
+      offsets.FDArrayInfo.offSize = calcOffSize (dictsSize);
+      final_size += CFF2Index::calculate_serialized_size (offsets.FDArrayInfo.offSize, subset_fdcount, dictsSize);
+    }
+
+    /* CharStrings */
+    {
+      offsets.charStringsInfo.offset = final_size;
+      unsigned int dataSize = subset_charstrings.total_size ();
+      offsets.charStringsInfo.offSize = calcOffSize (dataSize);
+      final_size += CFF2CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->glyphs.length, dataSize);
+    }
+
+    /* private dicts & local subrs */
+    offsets.privateDictsOffset = final_size;
+    for (unsigned int i = 0; i < orig_fdcount; i++)
+    {
+      if (fdmap.includes (i))
+      {
+        bool  has_localsubrs = offsets.localSubrsInfos[i].size > 0;
+        cff_private_dict_op_serializer_t privSzr (desubroutinize, drop_hints);
+        unsigned int  priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr, has_localsubrs);
+        table_info_t  privInfo = { final_size, priv_size, 0 };
+        privateDictInfos.push (privInfo);
+        final_size += privInfo.size;
+
+        if (!plan->desubroutinize && has_localsubrs)
+        {
+          offsets.localSubrsInfos[i].offset = final_size;
+          final_size += offsets.localSubrsInfos[i].size;
+        }
+      }
+    }
+
+    return true;
+  }
+
+  unsigned int get_final_size () const  { return final_size; }
+
+  unsigned int  final_size;
+  cff2_sub_table_offsets_t offsets;
+
+  unsigned int    orig_fdcount;
+  unsigned int    subset_fdcount;
+  unsigned int    subset_fdselect_format;
+  hb_vector_t<code_pair_t>   subset_fdselect_ranges;
+
+  remap_t   fdmap;
+
+  str_buff_vec_t            subset_charstrings;
+  str_buff_vec_t            subset_globalsubrs;
+  hb_vector_t<str_buff_vec_t> subset_localsubrs;
+  hb_vector_t<table_info_t>  privateDictInfos;
+
+  bool      drop_hints;
+  bool      desubroutinize;
+  cff2_subr_subsetter_t       subr_subsetter;
+};
+
+static inline bool _write_cff2 (const cff2_subset_plan &plan,
+                                const OT::cff2::accelerator_subset_t  &acc,
+                                const hb_vector_t<hb_codepoint_t>& glyphs,
+                                unsigned int dest_sz,
+                                void *dest)
+{
+  hb_serialize_context_t c (dest, dest_sz);
+
+  OT::cff2 *cff2 = c.start_serialize<OT::cff2> ();
+  if (unlikely (!c.extend_min (*cff2)))
+    return false;
+
+  /* header */
+  cff2->version.major.set (0x02);
+  cff2->version.minor.set (0x00);
+  cff2->topDict.set (OT::cff2::static_size);
+
+  /* top dict */
+  {
+    assert (cff2->topDict == (unsigned) (c.head - c.start));
+    cff2->topDictSize.set (plan.offsets.topDictInfo.size);
+    TopDict &dict = cff2 + cff2->topDict;
+    cff2_top_dict_op_serializer_t topSzr;
+    if (unlikely (!dict.serialize (&c, acc.topDict, topSzr, plan.offsets)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 top dict");
+      return false;
+    }
+  }
+
+  /* global subrs */
+  {
+    assert (cff2->topDict + plan.offsets.topDictInfo.size == (unsigned) (c.head - c.start));
+    CFF2Subrs *dest = c.start_embed <CFF2Subrs> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c, plan.offsets.globalSubrsInfo.offSize, plan.subset_globalsubrs)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize global subroutines");
+      return false;
+    }
+  }
+
+  /* variation store */
+  if (acc.varStore != &Null(CFF2VariationStore))
+  {
+    assert (plan.offsets.varStoreOffset == (unsigned) (c.head - c.start));
+    CFF2VariationStore *dest = c.start_embed<CFF2VariationStore> ();
+    if (unlikely (!dest->serialize (&c, acc.varStore)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 Variation Store");
+      return false;
+    }
+  }
+
+  /* FDSelect */
+  if (acc.fdSelect != &Null(CFF2FDSelect))
+  {
+    assert (plan.offsets.FDSelectInfo.offset == (unsigned) (c.head - c.start));
+
+    if (unlikely (!hb_serialize_cff_fdselect (&c, glyphs.length, *(const FDSelect *)acc.fdSelect, acc.fdArray->count,
+                                              plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size,
+                                              plan.subset_fdselect_ranges)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 subset FDSelect");
+      return false;
+    }
+  }
+
+  /* FDArray (FD Index) */
+  {
+    assert (plan.offsets.FDArrayInfo.offset == (unsigned) (c.head - c.start));
+    CFF2FDArray  *fda = c.start_embed<CFF2FDArray> ();
+    if (unlikely (fda == nullptr)) return false;
+    cff_font_dict_op_serializer_t  fontSzr;
+    if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize,
+                                   acc.fontDicts, plan.subset_fdcount, plan.fdmap,
+                                   fontSzr, plan.privateDictInfos)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 FDArray");
+      return false;
+    }
+  }
+
+  /* CharStrings */
+  {
+    assert (plan.offsets.charStringsInfo.offset == (unsigned) (c.head - c.start));
+    CFF2CharStrings  *cs = c.start_embed<CFF2CharStrings> ();
+    if (unlikely (cs == nullptr)) return false;
+    if (unlikely (!cs->serialize (&c, plan.offsets.charStringsInfo.offSize, plan.subset_charstrings)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 CharStrings");
+      return false;
+    }
+  }
+
+  /* private dicts & local subrs */
+  assert (plan.offsets.privateDictsOffset == (unsigned) (c.head - c.start));
+  for (unsigned int i = 0; i < acc.privateDicts.length; i++)
+  {
+    if (plan.fdmap.includes (i))
+    {
+      PrivateDict  *pd = c.start_embed<PrivateDict> ();
+      if (unlikely (pd == nullptr)) return false;
+      unsigned int priv_size = plan.privateDictInfos[plan.fdmap[i]].size;
+      bool result;
+      cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
+      /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
+      unsigned int  subroffset = (plan.offsets.localSubrsInfos[i].size > 0)? priv_size: 0;
+      result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
+      if (unlikely (!result))
+      {
+        DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
+        return false;
+      }
+      if (plan.offsets.localSubrsInfos[i].size > 0)
+      {
+        CFF2Subrs *dest = c.start_embed <CFF2Subrs> ();
+        if (unlikely (dest == nullptr)) return false;
+        if (unlikely (!dest->serialize (&c, plan.offsets.localSubrsInfos[i].offSize, plan.subset_localsubrs[i])))
+        {
+          DEBUG_MSG (SUBSET, nullptr, "failed to serialize local subroutines");
+          return false;
+        }
+      }
+    }
+  }
+
+  assert (c.head == c.end);
+  c.end_serialize ();
+
+  return true;
+}
+
+static bool
+_hb_subset_cff2 (const OT::cff2::accelerator_subset_t  &acc,
+                const char                    *data,
+                hb_subset_plan_t                *plan,
+                hb_blob_t                      **prime /* OUT */)
+{
+  cff2_subset_plan cff2_plan;
+
+  if (unlikely (!cff2_plan.create (acc, plan)))
+  {
+    DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff2 subsetting plan.");
+    return false;
+  }
+
+  unsigned int  cff2_prime_size = cff2_plan.get_final_size ();
+  char *cff2_prime_data = (char *) calloc (1, cff2_prime_size);
+
+  if (unlikely (!_write_cff2 (cff2_plan, acc, plan->glyphs,
+                              cff2_prime_size, cff2_prime_data))) {
+    DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff2.");
+    free (cff2_prime_data);
+    return false;
+  }
+
+  *prime = hb_blob_create (cff2_prime_data,
+                                cff2_prime_size,
+                                HB_MEMORY_MODE_READONLY,
+                                cff2_prime_data,
+                                free);
+  return true;
+}
+
+/**
+ * hb_subset_cff2:
+ * Subsets the CFF2 table according to a provided plan.
+ *
+ * Return value: subsetted cff2 table.
+ **/
+bool
+hb_subset_cff2 (hb_subset_plan_t *plan,
+                hb_blob_t       **prime /* OUT */)
+{
+  hb_blob_t *cff2_blob = hb_sanitize_context_t().reference_table<CFF::cff2> (plan->source);
+  const char *data = hb_blob_get_data(cff2_blob, nullptr);
+
+  OT::cff2::accelerator_subset_t acc;
+  acc.init(plan->source);
+  bool result = likely (acc.is_valid ()) &&
+                _hb_subset_cff2 (acc, data, plan, prime);
+
+  hb_blob_destroy (cff2_blob);
+  acc.fini ();
+
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff2.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,38 @@
+/*
+ * 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_SUBSET_CFF2_HH
+#define HB_SUBSET_CFF2_HH
+
+#include "hb.hh"
+
+#include "hb-subset-plan.hh"
+
+HB_INTERNAL bool
+hb_subset_cff2 (hb_subset_plan_t *plan,
+               hb_blob_t       **cff2_prime /* OUT */);
+
+#endif /* HB_SUBSET_CFF2_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-glyf.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,310 @@
+/*
+ * 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): Garret Rieger, Roderick Sheeter
+ */
+
+#include "hb-open-type.hh"
+#include "hb-ot-glyf-table.hh"
+#include "hb-set.h"
+#include "hb-subset-glyf.hh"
+
+static bool
+_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
+                                     hb_vector_t<hb_codepoint_t> &glyph_ids,
+                                     hb_bool_t drop_hints,
+                                     bool *use_short_loca /* OUT */,
+                                     unsigned int *glyf_size /* OUT */,
+                                     unsigned int *loca_size /* OUT */,
+                                     hb_vector_t<unsigned int> *instruction_ranges /* OUT */)
+{
+  unsigned int total = 0;
+  for (unsigned int i = 0; i < glyph_ids.length; i++)
+  {
+    hb_codepoint_t next_glyph = glyph_ids[i];
+    if (!instruction_ranges->resize (instruction_ranges->length + 2))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges.");
+      return false;
+    }
+    unsigned int *instruction_start = &(*instruction_ranges)[instruction_ranges->length - 2];
+    *instruction_start = 0;
+    unsigned int *instruction_end = &(*instruction_ranges)[instruction_ranges->length - 1];
+    *instruction_end = 0;
+
+    unsigned int start_offset, end_offset;
+    if (unlikely (!(glyf.get_offsets (next_glyph, &start_offset, &end_offset) &&
+                    glyf.remove_padding (start_offset, &end_offset))))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Invalid gid %d", next_glyph);
+      continue;
+    }
+    if (end_offset - start_offset < OT::glyf::GlyphHeader::static_size)
+      continue; /* 0-length glyph */
+
+    if (drop_hints)
+    {
+      if (unlikely (!glyf.get_instruction_offsets (start_offset, end_offset,
+                                                   instruction_start, instruction_end)))
+      {
+        DEBUG_MSG(SUBSET, nullptr, "Unable to get instruction offsets for %d", next_glyph);
+        return false;
+      }
+    }
+
+    total += end_offset - start_offset - (*instruction_end - *instruction_start);
+    /* round2 so short loca will work */
+    total += total % 2;
+  }
+
+  *glyf_size = total;
+  *use_short_loca = (total <= 131070);
+  *loca_size = (glyph_ids.length + 1)
+      * (*use_short_loca ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32));
+
+  DEBUG_MSG(SUBSET, nullptr, "preparing to subset glyf: final size %d, loca size %d, using %s loca",
+            total,
+            *loca_size,
+            *use_short_loca ? "short" : "long");
+  return true;
+}
+
+static bool
+_write_loca_entry (unsigned int  id,
+                   unsigned int  offset,
+                   bool          is_short,
+                   void         *loca_prime,
+                   unsigned int  loca_size)
+{
+  unsigned int entry_size = is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32);
+  if ((id + 1) * entry_size <= loca_size)
+  {
+    if (is_short) {
+      ((OT::HBUINT16*) loca_prime) [id].set (offset / 2);
+    } else {
+      ((OT::HBUINT32*) loca_prime) [id].set (offset);
+    }
+    return true;
+  }
+
+  // Offset was not written because the write is out of bounds.
+  DEBUG_MSG(SUBSET,
+            nullptr,
+            "WARNING: Attempted to write an out of bounds loca entry at index %d. Loca size is %d.",
+            id,
+            loca_size);
+  return false;
+}
+
+static void
+_update_components (hb_subset_plan_t * plan,
+                    char * glyph_start,
+                    unsigned int length)
+{
+  OT::glyf::CompositeGlyphHeader::Iterator iterator;
+  if (OT::glyf::CompositeGlyphHeader::get_iterator (glyph_start,
+                                                    length,
+                                                    &iterator))
+  {
+    do
+    {
+      hb_codepoint_t new_gid;
+      if (!plan->new_gid_for_old_gid (iterator.current->glyphIndex,
+                                      &new_gid))
+        continue;
+
+      ((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex.set (new_gid);
+    } while (iterator.move_to_next ());
+  }
+}
+
+static bool _remove_composite_instruction_flag (char *glyf_prime, unsigned int length)
+{
+  /* remove WE_HAVE_INSTRUCTIONS from flags in dest */
+  OT::glyf::CompositeGlyphHeader::Iterator composite_it;
+  if (unlikely (!OT::glyf::CompositeGlyphHeader::get_iterator (glyf_prime, length, &composite_it))) return false;
+  const OT::glyf::CompositeGlyphHeader *glyph;
+  do {
+    glyph = composite_it.current;
+    OT::HBUINT16 *flags = const_cast<OT::HBUINT16 *> (&glyph->flags);
+    flags->set ( (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS);
+  } while (composite_it.move_to_next ());
+  return true;
+}
+
+static bool
+_write_glyf_and_loca_prime (hb_subset_plan_t              *plan,
+                            const OT::glyf::accelerator_t &glyf,
+                            const char                    *glyf_data,
+                            bool                           use_short_loca,
+                            hb_vector_t<unsigned int> &instruction_ranges,
+                            unsigned int                   glyf_prime_size,
+                            char                          *glyf_prime_data /* OUT */,
+                            unsigned int                   loca_prime_size,
+                            char                          *loca_prime_data /* OUT */)
+{
+  hb_vector_t<hb_codepoint_t> &glyph_ids = plan->glyphs;
+  char *glyf_prime_data_next = glyf_prime_data;
+
+  bool success = true;
+  for (unsigned int i = 0; i < glyph_ids.length; i++)
+  {
+    unsigned int start_offset, end_offset;
+    if (unlikely (!(glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset) &&
+                    glyf.remove_padding (start_offset, &end_offset))))
+      end_offset = start_offset = 0;
+
+    unsigned int instruction_start = instruction_ranges[i * 2];
+    unsigned int instruction_end = instruction_ranges[i * 2 + 1];
+
+    int length = end_offset - start_offset - (instruction_end - instruction_start);
+
+    if (glyf_prime_data_next + length > glyf_prime_data + glyf_prime_size)
+    {
+      DEBUG_MSG(SUBSET,
+                 nullptr,
+                 "WARNING: Attempted to write an out of bounds glyph entry for gid %d (length %d)",
+                 i, length);
+      return false;
+    }
+
+    if (instruction_start == instruction_end)
+      memcpy (glyf_prime_data_next, glyf_data + start_offset, length);
+    else
+    {
+      memcpy (glyf_prime_data_next, glyf_data + start_offset, instruction_start - start_offset);
+      memcpy (glyf_prime_data_next + instruction_start - start_offset, glyf_data + instruction_end, end_offset - instruction_end);
+      /* if the instructions end at the end this was a composite glyph, else simple */
+      if (instruction_end == end_offset)
+      {
+        if (unlikely (!_remove_composite_instruction_flag (glyf_prime_data_next, length))) return false;
+      }
+      else
+        /* zero instruction length, which is just before instruction_start */
+        memset (glyf_prime_data_next + instruction_start - start_offset - 2, 0, 2);
+    }
+
+    success = success && _write_loca_entry (i,
+                                            glyf_prime_data_next - glyf_prime_data,
+                                            use_short_loca,
+                                            loca_prime_data,
+                                            loca_prime_size);
+    _update_components (plan, glyf_prime_data_next, length);
+
+    // TODO: don't align to two bytes if using long loca.
+    glyf_prime_data_next += length + (length % 2); // Align to 2 bytes for short loca.
+  }
+
+  success = success && _write_loca_entry (glyph_ids.length,
+                                          glyf_prime_data_next - glyf_prime_data,
+                                          use_short_loca,
+                                          loca_prime_data,
+                                          loca_prime_size);
+  return success;
+}
+
+static bool
+_hb_subset_glyf_and_loca (const OT::glyf::accelerator_t  &glyf,
+                          const char                     *glyf_data,
+                          hb_subset_plan_t               *plan,
+                          bool                           *use_short_loca,
+                          hb_blob_t                     **glyf_prime /* OUT */,
+                          hb_blob_t                     **loca_prime /* OUT */)
+{
+  // TODO(grieger): Sanity check allocation size for the new table.
+  hb_vector_t<hb_codepoint_t> &glyphs_to_retain = plan->glyphs;
+
+  unsigned int glyf_prime_size;
+  unsigned int loca_prime_size;
+  hb_vector_t<unsigned int> instruction_ranges;
+  instruction_ranges.init ();
+
+  if (unlikely (!_calculate_glyf_and_loca_prime_size (glyf,
+                                                      glyphs_to_retain,
+                                                      plan->drop_hints,
+                                                      use_short_loca,
+                                                      &glyf_prime_size,
+                                                      &loca_prime_size,
+                                                      &instruction_ranges))) {
+    instruction_ranges.fini ();
+    return false;
+  }
+
+  char *glyf_prime_data = (char *) calloc (1, glyf_prime_size);
+  char *loca_prime_data = (char *) calloc (1, loca_prime_size);
+  if (unlikely (!_write_glyf_and_loca_prime (plan, glyf, glyf_data,
+                                             *use_short_loca,
+                                             instruction_ranges,
+                                             glyf_prime_size, glyf_prime_data,
+                                             loca_prime_size, loca_prime_data))) {
+    free (glyf_prime_data);
+    free (loca_prime_data);
+    instruction_ranges.fini ();
+    return false;
+  }
+  instruction_ranges.fini ();
+
+  *glyf_prime = hb_blob_create (glyf_prime_data,
+                                glyf_prime_size,
+                                HB_MEMORY_MODE_READONLY,
+                                glyf_prime_data,
+                                free);
+  *loca_prime = hb_blob_create (loca_prime_data,
+                                loca_prime_size,
+                                HB_MEMORY_MODE_READONLY,
+                                loca_prime_data,
+                                free);
+  return true;
+}
+
+/**
+ * hb_subset_glyf:
+ * Subsets the glyph table according to a provided plan.
+ *
+ * Return value: subsetted glyf table.
+ *
+ * Since: 1.7.5
+ **/
+bool
+hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
+                         bool             *use_short_loca, /* OUT */
+                         hb_blob_t       **glyf_prime, /* OUT */
+                         hb_blob_t       **loca_prime /* OUT */)
+{
+  hb_blob_t *glyf_blob = hb_sanitize_context_t ().reference_table<OT::glyf> (plan->source);
+  const char *glyf_data = hb_blob_get_data (glyf_blob, nullptr);
+
+  OT::glyf::accelerator_t glyf;
+  glyf.init (plan->source);
+  bool result = _hb_subset_glyf_and_loca (glyf,
+                                          glyf_data,
+                                          plan,
+                                          use_short_loca,
+                                          glyf_prime,
+                                          loca_prime);
+
+  hb_blob_destroy (glyf_blob);
+  glyf.fini ();
+
+  return result;
+}
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-glyf.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-glyf.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,14 +27,14 @@
 #ifndef HB_SUBSET_GLYF_HH
 #define HB_SUBSET_GLYF_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-subset-plan.hh"
+#include "hb-subset.hh"
 
 HB_INTERNAL bool
 hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
                          bool             *use_short_loca, /* OUT */
-                         hb_blob_t       **glyf_prime /* OUT */,
-                         hb_blob_t       **loca_prime /* OUT */);
+                         hb_blob_t       **glyf_prime      /* OUT */,
+                         hb_blob_t       **loca_prime      /* OUT */);
 
 #endif /* HB_SUBSET_GLYF_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-input.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,146 @@
+/*
+ * 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): Garret Rieger, Rod Sheeter, Behdad Esfahbod
+ */
+
+#include "hb-subset.hh"
+#include "hb-set.hh"
+
+/**
+ * hb_subset_input_create_or_fail:
+ *
+ * Return value: New subset input.
+ *
+ * Since: 1.8.0
+ **/
+hb_subset_input_t *
+hb_subset_input_create_or_fail ()
+{
+  hb_subset_input_t *input = hb_object_create<hb_subset_input_t>();
+
+  if (unlikely (!input))
+    return nullptr;
+
+  input->unicodes = hb_set_create ();
+  input->glyphs = hb_set_create ();
+  input->drop_layout = true;
+
+  return input;
+}
+
+/**
+ * hb_subset_input_reference: (skip)
+ * @subset_input: a subset_input.
+ *
+ *
+ *
+ * Return value:
+ *
+ * Since: 1.8.0
+ **/
+hb_subset_input_t *
+hb_subset_input_reference (hb_subset_input_t *subset_input)
+{
+  return hb_object_reference (subset_input);
+}
+
+/**
+ * hb_subset_input_destroy:
+ * @subset_input: a subset_input.
+ *
+ * Since: 1.8.0
+ **/
+void
+hb_subset_input_destroy (hb_subset_input_t *subset_input)
+{
+  if (!hb_object_destroy (subset_input)) return;
+
+  hb_set_destroy (subset_input->unicodes);
+  hb_set_destroy (subset_input->glyphs);
+
+  free (subset_input);
+}
+
+/**
+ * hb_subset_input_unicode_set:
+ * @subset_input: a subset_input.
+ *
+ * Since: 1.8.0
+ **/
+HB_EXTERN hb_set_t *
+hb_subset_input_unicode_set (hb_subset_input_t *subset_input)
+{
+  return subset_input->unicodes;
+}
+
+/**
+ * hb_subset_input_glyph_set:
+ * @subset_input: a subset_input.
+ *
+ * Since: 1.8.0
+ **/
+HB_EXTERN hb_set_t *
+hb_subset_input_glyph_set (hb_subset_input_t *subset_input)
+{
+  return subset_input->glyphs;
+}
+
+HB_EXTERN void
+hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
+                                hb_bool_t drop_hints)
+{
+  subset_input->drop_hints = drop_hints;
+}
+
+HB_EXTERN hb_bool_t
+hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input)
+{
+  return subset_input->drop_hints;
+}
+
+HB_EXTERN void
+hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input,
+                                 hb_bool_t drop_layout)
+{
+  subset_input->drop_layout = drop_layout;
+}
+
+HB_EXTERN hb_bool_t
+hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input)
+{
+  return subset_input->drop_layout;
+}
+
+HB_EXTERN void
+hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
+        hb_bool_t desubroutinize)
+{
+  subset_input->desubroutinize = desubroutinize;
+}
+
+HB_EXTERN hb_bool_t
+hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input)
+{
+  return subset_input->desubroutinize;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-input.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,57 @@
+/*
+ * 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): Garret Rieger, Roderick Sheeter
+ */
+
+#ifndef HB_SUBSET_INPUT_HH
+#define HB_SUBSET_INPUT_HH
+
+
+#include "hb.hh"
+
+#include "hb-subset.h"
+
+#include "hb-font.hh"
+
+struct hb_subset_input_t
+{
+  hb_object_header_t header;
+
+  hb_set_t *unicodes;
+  hb_set_t *glyphs;
+
+  bool drop_hints : 1;
+  bool drop_layout : 1;
+  bool desubroutinize : 1;
+  /* TODO
+   *
+   * features
+   * lookups
+   * nameIDs
+   * ...
+   */
+};
+
+
+#endif /* HB_SUBSET_INPUT_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-plan.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,223 @@
+/*
+ * 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): Garret Rieger, Roderick Sheeter
+ */
+
+#include "hb-subset-plan.hh"
+#include "hb-map.hh"
+#include "hb-set.hh"
+
+#include "hb-ot-cmap-table.hh"
+#include "hb-ot-glyf-table.hh"
+#include "hb-ot-cff1-table.hh"
+
+static void
+_add_gid_and_children (const OT::glyf::accelerator_t &glyf,
+                       hb_codepoint_t gid,
+                       hb_set_t *gids_to_retain)
+{
+  if (hb_set_has (gids_to_retain, gid))
+    // Already visited this gid, ignore.
+    return;
+
+  hb_set_add (gids_to_retain, gid);
+
+  OT::glyf::CompositeGlyphHeader::Iterator composite;
+  if (glyf.get_composite (gid, &composite))
+  {
+    do
+    {
+      _add_gid_and_children (glyf, (hb_codepoint_t) composite.current->glyphIndex, gids_to_retain);
+    } while (composite.move_to_next());
+  }
+}
+
+static void
+_add_cff_seac_components (const OT::cff1::accelerator_t &cff,
+           hb_codepoint_t gid,
+           hb_set_t *gids_to_retain)
+{
+  hb_codepoint_t base_gid, accent_gid;
+  if (cff.get_seac_components (gid, &base_gid, &accent_gid))
+  {
+    hb_set_add (gids_to_retain, base_gid);
+    hb_set_add (gids_to_retain, accent_gid);
+  }
+}
+
+static void
+_gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain)
+{
+  hb_set_t lookup_indices;
+  hb_ot_layout_collect_lookups (face,
+                                HB_OT_TAG_GSUB,
+                                nullptr,
+                                nullptr,
+                                nullptr,
+                                &lookup_indices);
+  hb_ot_layout_lookups_substitute_closure (face,
+                                           &lookup_indices,
+                                           gids_to_retain);
+}
+
+static void
+_remove_invalid_gids (hb_set_t *glyphs,
+                      unsigned int num_glyphs)
+{
+  hb_codepoint_t gid = HB_SET_VALUE_INVALID;
+  while (glyphs->next (&gid))
+  {
+    if (gid >= num_glyphs)
+      glyphs->del (gid);
+  }
+}
+
+static hb_set_t *
+_populate_gids_to_retain (hb_face_t *face,
+                          const hb_set_t *unicodes,
+                          bool close_over_gsub,
+                          hb_set_t *unicodes_to_retain,
+                          hb_map_t *codepoint_to_glyph,
+                          hb_vector_t<hb_codepoint_t> *glyphs)
+{
+  OT::cmap::accelerator_t cmap;
+  OT::glyf::accelerator_t glyf;
+  OT::cff1::accelerator_t cff;
+  cmap.init (face);
+  glyf.init (face);
+  cff.init (face);
+
+  hb_set_t *initial_gids_to_retain = hb_set_create ();
+  initial_gids_to_retain->add (0); // Not-def
+
+  hb_codepoint_t cp = HB_SET_VALUE_INVALID;
+  while (unicodes->next (&cp))
+  {
+    hb_codepoint_t gid;
+    if (!cmap.get_nominal_glyph (cp, &gid))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
+      continue;
+    }
+    unicodes_to_retain->add (cp);
+    codepoint_to_glyph->set (cp, gid);
+    initial_gids_to_retain->add (gid);
+  }
+
+  if (close_over_gsub)
+    // Add all glyphs needed for GSUB substitutions.
+    _gsub_closure (face, initial_gids_to_retain);
+
+  // Populate a full set of glyphs to retain by adding all referenced
+  // composite glyphs.
+  hb_codepoint_t gid = HB_SET_VALUE_INVALID;
+  hb_set_t *all_gids_to_retain = hb_set_create ();
+  while (initial_gids_to_retain->next (&gid))
+  {
+    _add_gid_and_children (glyf, gid, all_gids_to_retain);
+    if (cff.is_valid ())
+      _add_cff_seac_components (cff, gid, all_gids_to_retain);
+  }
+  hb_set_destroy (initial_gids_to_retain);
+
+  _remove_invalid_gids (all_gids_to_retain, face->get_num_glyphs ());
+
+  glyphs->alloc (all_gids_to_retain->get_population ());
+  gid = HB_SET_VALUE_INVALID;
+  while (all_gids_to_retain->next (&gid))
+    glyphs->push (gid);
+
+  cff.fini ();
+  glyf.fini ();
+  cmap.fini ();
+
+  return all_gids_to_retain;
+}
+
+static void
+_create_old_gid_to_new_gid_map (const hb_vector_t<hb_codepoint_t> &glyphs,
+                                hb_map_t *glyph_map)
+{
+  for (unsigned int i = 0; i < glyphs.length; i++) {
+    glyph_map->set (glyphs[i], i);
+  }
+}
+
+/**
+ * hb_subset_plan_create:
+ * Computes a plan for subsetting the supplied face according
+ * to a provided input. The plan describes
+ * which tables and glyphs should be retained.
+ *
+ * Return value: New subset plan.
+ *
+ * Since: 1.7.5
+ **/
+hb_subset_plan_t *
+hb_subset_plan_create (hb_face_t           *face,
+                       hb_subset_input_t   *input)
+{
+  hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> ();
+
+  plan->drop_hints = input->drop_hints;
+  plan->drop_layout = input->drop_layout;
+  plan->desubroutinize = input->desubroutinize;
+  plan->unicodes = hb_set_create();
+  plan->glyphs.init();
+  plan->source = hb_face_reference (face);
+  plan->dest = hb_face_builder_create ();
+  plan->codepoint_to_glyph = hb_map_create();
+  plan->glyph_map = hb_map_create();
+  plan->glyphset = _populate_gids_to_retain (face,
+                                             input->unicodes,
+                                             !plan->drop_layout,
+                                             plan->unicodes,
+                                             plan->codepoint_to_glyph,
+                                             &plan->glyphs);
+  _create_old_gid_to_new_gid_map (plan->glyphs,
+                                  plan->glyph_map);
+
+  return plan;
+}
+
+/**
+ * hb_subset_plan_destroy:
+ *
+ * Since: 1.7.5
+ **/
+void
+hb_subset_plan_destroy (hb_subset_plan_t *plan)
+{
+  if (!hb_object_destroy (plan)) return;
+
+  hb_set_destroy (plan->unicodes);
+  plan->glyphs.fini ();
+  hb_face_destroy (plan->source);
+  hb_face_destroy (plan->dest);
+  hb_map_destroy (plan->codepoint_to_glyph);
+  hb_map_destroy (plan->glyph_map);
+  hb_set_destroy (plan->glyphset);
+
+  free (plan);
+}
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-plan.hh	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-plan.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -27,28 +27,26 @@
 #ifndef HB_SUBSET_PLAN_HH
 #define HB_SUBSET_PLAN_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 #include "hb-subset.h"
-#include "hb-subset-private.hh"
+#include "hb-subset-input.hh"
 
-#include "hb-object-private.hh"
-#include "hb-map-private.hh"
+#include "hb-map.hh"
 
 struct hb_subset_plan_t
 {
   hb_object_header_t header;
-  ASSERT_POD ();
 
-  hb_bool_t drop_hints;
-  hb_bool_t drop_ot_layout;
+  bool drop_hints : 1;
+  bool drop_layout : 1;
+  bool desubroutinize : 1;
 
   // For each cp that we'd like to retain maps to the corresponding gid.
   hb_set_t *unicodes;
 
-  // This list contains the complete set of glyphs to retain and may contain
-  // more glyphs then the lists above.
   hb_vector_t<hb_codepoint_t> glyphs;
+  hb_set_t *glyphset;
 
   hb_map_t *codepoint_to_glyph;
   hb_map_t *glyph_map;
@@ -57,9 +55,8 @@
   hb_face_t *source;
   hb_face_t *dest;
 
-  inline hb_bool_t
-  new_gid_for_codepoint (hb_codepoint_t codepoint,
-                         hb_codepoint_t *new_gid) const
+  bool new_gid_for_codepoint (hb_codepoint_t codepoint,
+                              hb_codepoint_t *new_gid) const
   {
     hb_codepoint_t old_gid = codepoint_to_glyph->get (codepoint);
     if (old_gid == HB_MAP_VALUE_INVALID)
@@ -68,9 +65,8 @@
     return new_gid_for_old_gid (old_gid, new_gid);
   }
 
-  inline hb_bool_t
-  new_gid_for_old_gid (hb_codepoint_t old_gid,
-                      hb_codepoint_t *new_gid) const
+  bool new_gid_for_old_gid (hb_codepoint_t old_gid,
+                            hb_codepoint_t *new_gid) const
   {
     hb_codepoint_t gid = glyph_map->get (old_gid);
     if (gid == HB_MAP_VALUE_INVALID)
@@ -80,7 +76,7 @@
     return true;
   }
 
-  inline hb_bool_t
+  bool
   add_table (hb_tag_t tag,
              hb_blob_t *contents)
   {
@@ -90,7 +86,7 @@
               hb_blob_get_length (contents),
               hb_blob_get_length (source_blob));
     hb_blob_destroy (source_blob);
-    return hb_subset_face_add_table(dest, tag, contents);
+    return hb_face_builder_add_table (dest, tag, contents);
   }
 };
 
@@ -98,7 +94,6 @@
 
 HB_INTERNAL hb_subset_plan_t *
 hb_subset_plan_create (hb_face_t           *face,
-                       hb_subset_profile_t *profile,
                        hb_subset_input_t   *input);
 
 HB_INTERNAL void
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * 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): Garret Rieger, Roderick Sheeter
- */
-
-#ifndef HB_SUBSET_PRIVATE_HH
-#define HB_SUBSET_PRIVATE_HH
-
-
-#include "hb-private.hh"
-
-#include "hb-subset.h"
-
-#include "hb-font-private.hh"
-
-typedef struct hb_subset_face_data_t hb_subset_face_data_t;
-
-struct hb_subset_input_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_set_t *unicodes;
-  hb_set_t *glyphs;
-
-  hb_bool_t drop_hints;
-  hb_bool_t drop_ot_layout;
-  /* TODO
-   *
-   * features
-   * lookups
-   * nameIDs
-   * ...
-   */
-};
-
-HB_INTERNAL hb_face_t *
-hb_subset_face_create (void);
-
-HB_INTERNAL hb_bool_t
-hb_subset_face_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob);
-
-#endif /* HB_SUBSET_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,293 @@
+/*
+ * 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): Garret Rieger, Rod Sheeter, Behdad Esfahbod
+ */
+
+#include "hb.hh"
+#include "hb-open-type.hh"
+
+#include "hb-subset.hh"
+#include "hb-subset-glyf.hh"
+
+#include "hb-open-file.hh"
+#include "hb-ot-cmap-table.hh"
+#include "hb-ot-glyf-table.hh"
+#include "hb-ot-hdmx-table.hh"
+#include "hb-ot-head-table.hh"
+#include "hb-ot-hhea-table.hh"
+#include "hb-ot-hmtx-table.hh"
+#include "hb-ot-maxp-table.hh"
+#include "hb-ot-os2-table.hh"
+#include "hb-ot-post-table.hh"
+#include "hb-ot-cff1-table.hh"
+#include "hb-ot-cff2-table.hh"
+#include "hb-ot-vorg-table.hh"
+#include "hb-ot-layout-gsub-table.hh"
+#include "hb-ot-layout-gpos-table.hh"
+
+
+static unsigned int
+_plan_estimate_subset_table_size (hb_subset_plan_t *plan,
+                                  unsigned int table_len)
+{
+  unsigned int src_glyphs = plan->source->get_num_glyphs ();
+  unsigned int dst_glyphs = plan->glyphset->get_population ();
+
+  if (unlikely (!src_glyphs))
+    return 512 + table_len;
+
+  return 512 + (unsigned int) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
+}
+
+template<typename TableType>
+static bool
+_subset2 (hb_subset_plan_t *plan)
+{
+  hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
+  const TableType *table = source_blob->as<TableType> ();
+
+  hb_tag_t tag = TableType::tableTag;
+  hb_bool_t result = false;
+  if (source_blob->data)
+  {
+    hb_vector_t<char> buf;
+    unsigned int buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
+    DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
+    if (unlikely (!buf.alloc (buf_size)))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
+      return false;
+    }
+  retry:
+    hb_serialize_context_t serializer ((void *) buf, buf_size);
+    hb_subset_context_t c (plan, &serializer);
+    result = table->subset (&c);
+    if (serializer.in_error ())
+    {
+      buf_size += (buf_size >> 1) + 32;
+      DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", HB_UNTAG (tag), buf_size);
+      if (unlikely (!buf.alloc (buf_size)))
+      {
+        DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (tag), buf_size);
+        return false;
+      }
+      goto retry;
+    }
+    if (result)
+    {
+      hb_blob_t *dest_blob = serializer.copy_blob ();
+      DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
+      result = c.plan->add_table (tag, dest_blob);
+      hb_blob_destroy (dest_blob);
+    }
+    else
+    {
+      DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
+      result = true;
+    }
+  }
+  else
+    DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
+
+  hb_blob_destroy (source_blob);
+  DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
+  return result;
+}
+
+template<typename TableType>
+static bool
+_subset (hb_subset_plan_t *plan)
+{
+  hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
+  const TableType *table = source_blob->as<TableType> ();
+
+  hb_tag_t tag = TableType::tableTag;
+  hb_bool_t result = false;
+  if (source_blob->data)
+    result = table->subset (plan);
+  else
+    DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
+
+  hb_blob_destroy (source_blob);
+  DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
+  return result;
+}
+
+
+static bool
+_subset_table (hb_subset_plan_t *plan,
+               hb_tag_t          tag)
+{
+  DEBUG_MSG(SUBSET, nullptr, "begin subset %c%c%c%c", HB_UNTAG (tag));
+  bool result = true;
+  switch (tag) {
+    case HB_OT_TAG_glyf:
+      result = _subset<const OT::glyf> (plan);
+      break;
+    case HB_OT_TAG_hdmx:
+      result = _subset<const OT::hdmx> (plan);
+      break;
+    case HB_OT_TAG_head:
+      // TODO that won't work well if there is no glyf
+      DEBUG_MSG(SUBSET, nullptr, "skip head, handled by glyf");
+      result = true;
+      break;
+    case HB_OT_TAG_hhea:
+      DEBUG_MSG(SUBSET, nullptr, "skip hhea handled by hmtx");
+      return true;
+    case HB_OT_TAG_hmtx:
+      result = _subset<const OT::hmtx> (plan);
+      break;
+    case HB_OT_TAG_vhea:
+      DEBUG_MSG(SUBSET, nullptr, "skip vhea handled by vmtx");
+      return true;
+    case HB_OT_TAG_vmtx:
+      result = _subset<const OT::vmtx> (plan);
+      break;
+    case HB_OT_TAG_maxp:
+      result = _subset<const OT::maxp> (plan);
+      break;
+    case HB_OT_TAG_loca:
+      DEBUG_MSG(SUBSET, nullptr, "skip loca handled by glyf");
+      return true;
+    case HB_OT_TAG_cmap:
+      result = _subset<const OT::cmap> (plan);
+      break;
+    case HB_OT_TAG_OS2:
+      result = _subset<const OT::OS2> (plan);
+      break;
+    case HB_OT_TAG_post:
+      result = _subset<const OT::post> (plan);
+      break;
+    case HB_OT_TAG_cff1:
+      result = _subset<const OT::cff1> (plan);
+      break;
+    case HB_OT_TAG_cff2:
+      result = _subset<const OT::cff2> (plan);
+      break;
+    case HB_OT_TAG_VORG:
+      result = _subset<const OT::VORG> (plan);
+      break;
+    case HB_OT_TAG_GDEF:
+      result = _subset2<const OT::GDEF> (plan);
+      break;
+    case HB_OT_TAG_GSUB:
+      result = _subset2<const OT::GSUB> (plan);
+      break;
+    case HB_OT_TAG_GPOS:
+      result = _subset2<const OT::GPOS> (plan);
+      break;
+
+    default:
+      hb_blob_t *source_table = hb_face_reference_table (plan->source, tag);
+      if (likely (source_table))
+        result = plan->add_table (tag, source_table);
+      else
+        result = false;
+      hb_blob_destroy (source_table);
+      break;
+  }
+  DEBUG_MSG(SUBSET, nullptr, "subset %c%c%c%c %s", HB_UNTAG (tag), result ? "ok" : "FAILED");
+  return result;
+}
+
+static bool
+_should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
+{
+  switch (tag) {
+    case HB_TAG ('c', 'v', 'a', 'r'): /* hint table, fallthrough */
+    case HB_TAG ('c', 'v', 't', ' '): /* hint table, fallthrough */
+    case HB_TAG ('f', 'p', 'g', 'm'): /* hint table, fallthrough */
+    case HB_TAG ('p', 'r', 'e', 'p'): /* hint table, fallthrough */
+    case HB_TAG ('h', 'd', 'm', 'x'): /* hint table, fallthrough */
+    case HB_TAG ('V', 'D', 'M', 'X'): /* hint table, fallthrough */
+      return plan->drop_hints;
+    // Drop Layout Tables if requested.
+    case HB_OT_TAG_GDEF:
+    case HB_OT_TAG_GPOS:
+    case HB_OT_TAG_GSUB:
+      return plan->drop_layout;
+    // Drop these tables below by default, list pulled
+    // from fontTools:
+    case HB_TAG ('B', 'A', 'S', 'E'):
+    case HB_TAG ('J', 'S', 'T', 'F'):
+    case HB_TAG ('D', 'S', 'I', 'G'):
+    case HB_TAG ('E', 'B', 'D', 'T'):
+    case HB_TAG ('E', 'B', 'L', 'C'):
+    case HB_TAG ('E', 'B', 'S', 'C'):
+    case HB_TAG ('S', 'V', 'G', ' '):
+    case HB_TAG ('P', 'C', 'L', 'T'):
+    case HB_TAG ('L', 'T', 'S', 'H'):
+    // Graphite tables:
+    case HB_TAG ('F', 'e', 'a', 't'):
+    case HB_TAG ('G', 'l', 'a', 't'):
+    case HB_TAG ('G', 'l', 'o', 'c'):
+    case HB_TAG ('S', 'i', 'l', 'f'):
+    case HB_TAG ('S', 'i', 'l', 'l'):
+    // Colour
+    case HB_TAG ('s', 'b', 'i', 'x'):
+      return true;
+    default:
+      return false;
+  }
+}
+
+/**
+ * hb_subset:
+ * @source: font face data to be subset.
+ * @input: input to use for the subsetting.
+ *
+ * Subsets a font according to provided input.
+ **/
+hb_face_t *
+hb_subset (hb_face_t *source,
+           hb_subset_input_t *input)
+{
+  if (unlikely (!input || !source)) return hb_face_get_empty ();
+
+  hb_subset_plan_t *plan = hb_subset_plan_create (source, input);
+
+  hb_tag_t table_tags[32];
+  unsigned int offset = 0, count;
+  bool success = true;
+  do {
+    count = ARRAY_LENGTH (table_tags);
+    hb_face_get_table_tags (source, offset, &count, table_tags);
+    for (unsigned int i = 0; i < count; i++)
+    {
+      hb_tag_t tag = table_tags[i];
+      if (_should_drop_table (plan, tag))
+      {
+        DEBUG_MSG(SUBSET, nullptr, "drop %c%c%c%c", HB_UNTAG (tag));
+        continue;
+      }
+      success = success && _subset_table (plan, tag);
+    }
+    offset += count;
+  } while (success && count == ARRAY_LENGTH (table_tags));
+
+  hb_face_t *result = success ? hb_face_reference (plan->dest) : hb_face_get_empty ();
+  hb_subset_plan_destroy (plan);
+  return result;
+}
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset.h	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset.h	Fri Mar 01 16:59:19 2019 -0800
@@ -32,20 +32,6 @@
 HB_BEGIN_DECLS
 
 /*
- * hb_subset_profile_t
- * Things that change based on target environment, e.g. OS.
- * Threadsafe for multiple concurrent subset operations.
- */
-
-typedef struct hb_subset_profile_t hb_subset_profile_t;
-
-HB_EXTERN hb_subset_profile_t *
-hb_subset_profile_create (void);
-
-HB_EXTERN void
-hb_subset_profile_destroy (hb_subset_profile_t *profile);
-
-/*
  * hb_subset_input_t
  *
  * Things that change based on the input. Characters to keep, etc.
@@ -68,21 +54,28 @@
 HB_EXTERN hb_set_t *
 hb_subset_input_glyph_set (hb_subset_input_t *subset_input);
 
-HB_EXTERN hb_bool_t *
-hb_subset_input_drop_hints (hb_subset_input_t *subset_input);
+HB_EXTERN void
+hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
+                                hb_bool_t drop_hints);
+HB_EXTERN hb_bool_t
+hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input);
 
-HB_EXTERN hb_bool_t *
-hb_subset_input_drop_ot_layout (hb_subset_input_t *subset_input);
+HB_EXTERN void
+hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input,
+                                 hb_bool_t drop_layout);
+HB_EXTERN hb_bool_t
+hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input);
 
-/* hb_subset() */
+HB_EXTERN void
+hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
+        hb_bool_t desubroutinize);
+HB_EXTERN hb_bool_t
+hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input);
+
+/* hb_subset () */
 HB_EXTERN hb_face_t *
-hb_subset (hb_face_t *source,
-           hb_subset_profile_t *profile,
-           hb_subset_input_t *input);
+hb_subset (hb_face_t *source, hb_subset_input_t *input);
 
-/* hb_subset_get_all_codepoints */
-HB_EXTERN void
-hb_subset_get_all_codepoints (hb_face_t *source, hb_set_t *out);
 
 HB_END_DECLS
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,59 @@
+/*
+ * 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): Garret Rieger, Roderick Sheeter
+ */
+
+#ifndef HB_SUBSET_HH
+#define HB_SUBSET_HH
+
+
+#include "hb.hh"
+
+#include "hb-subset.h"
+
+#include "hb-machinery.hh"
+#include "hb-subset-input.hh"
+#include "hb-subset-plan.hh"
+
+struct hb_subset_context_t :
+       hb_dispatch_context_t<hb_subset_context_t, bool, HB_DEBUG_SUBSET>
+{
+  const char *get_name () { return "SUBSET"; }
+  template <typename T>
+  bool dispatch (const T &obj) { return obj.subset (this); }
+  static bool default_return_value () { return true; }
+
+  hb_subset_plan_t *plan;
+  hb_serialize_context_t *serializer;
+  unsigned int debug_depth;
+
+  hb_subset_context_t (hb_subset_plan_t *plan_,
+                       hb_serialize_context_t *serializer_) :
+                        plan (plan_),
+                        serializer (serializer_),
+                        debug_depth (0) {}
+};
+
+
+#endif /* HB_SUBSET_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ucdn.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ucdn.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -14,9 +14,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-unicode-private.hh"
+#include "hb-machinery.hh"
 
 #include "ucdn.h"
 
@@ -181,15 +181,6 @@
     return (hb_unicode_combining_class_t) ucdn_get_combining_class(unicode);
 }
 
-static unsigned int
-hb_ucdn_eastasian_width(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                        hb_codepoint_t unicode,
-                        void *user_data HB_UNUSED)
-{
-    int w = ucdn_get_east_asian_width(unicode);
-    return (w == UCDN_EAST_ASIAN_F || w == UCDN_EAST_ASIAN_W) ? 2 : 1;
-}
-
 static hb_unicode_general_category_t
 hb_ucdn_general_category(hb_unicode_funcs_t *ufuncs HB_UNUSED,
                          hb_codepoint_t unicode,
@@ -230,56 +221,48 @@
     return ucdn_decompose(ab, a, b);
 }
 
-static unsigned int
-hb_ucdn_decompose_compatibility(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                                hb_codepoint_t u, hb_codepoint_t *decomposed,
-                                void *user_data HB_UNUSED)
+
+#if HB_USE_ATEXIT
+static void free_static_ucdn_funcs ();
+#endif
+
+static struct hb_ucdn_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_ucdn_unicode_funcs_lazy_loader_t>
 {
-    return ucdn_compat_decompose(u, decomposed);
-}
-
-static hb_unicode_funcs_t *static_ucdn_funcs = nullptr;
+  static hb_unicode_funcs_t *create ()
+  {
+    hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr);
 
-#ifdef HB_USE_ATEXIT
+    hb_unicode_funcs_set_combining_class_func (funcs, hb_ucdn_combining_class, nullptr, nullptr);
+    hb_unicode_funcs_set_general_category_func (funcs, hb_ucdn_general_category, nullptr, nullptr);
+    hb_unicode_funcs_set_mirroring_func (funcs, hb_ucdn_mirroring, nullptr, nullptr);
+    hb_unicode_funcs_set_script_func (funcs, hb_ucdn_script, nullptr, nullptr);
+    hb_unicode_funcs_set_compose_func (funcs, hb_ucdn_compose, nullptr, nullptr);
+    hb_unicode_funcs_set_decompose_func (funcs, hb_ucdn_decompose, nullptr, nullptr);
+
+    hb_unicode_funcs_make_immutable (funcs);
+
+#if HB_USE_ATEXIT
+    atexit (free_static_ucdn_funcs);
+#endif
+
+    return funcs;
+  }
+} static_ucdn_funcs;
+
+#if HB_USE_ATEXIT
 static
-void free_static_ucdn_funcs (void)
+void free_static_ucdn_funcs ()
 {
-retry:
-  hb_unicode_funcs_t *ucdn_funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs);
-  if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, ucdn_funcs, nullptr))
-    goto retry;
-
-  hb_unicode_funcs_destroy (ucdn_funcs);
+  static_ucdn_funcs.free_instance ();
 }
 #endif
 
 extern "C" HB_INTERNAL
 hb_unicode_funcs_t *
-hb_ucdn_get_unicode_funcs (void)
-{
-retry:
-  hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs);
-
-  if (unlikely (!funcs))
-  {
-    funcs = hb_unicode_funcs_create (nullptr);
-
-#define HB_UNICODE_FUNC_IMPLEMENT(name) \
-    hb_unicode_funcs_set_##name##_func (funcs, hb_ucdn_##name, nullptr, nullptr);
-      HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
+hb_ucdn_get_unicode_funcs ();
 
-    hb_unicode_funcs_make_immutable (funcs);
-
-    if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, nullptr, funcs)) {
-      hb_unicode_funcs_destroy (funcs);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_ucdn_funcs); /* First person registers atexit() callback. */
-#endif
-  };
-
-  return hb_unicode_funcs_reference (funcs);
+hb_unicode_funcs_t *
+hb_ucdn_get_unicode_funcs ()
+{
+  return static_ucdn_funcs.get_unconst ();
 }
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ucdn/ucdn.h	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ucdn/ucdn.h	Fri Mar 01 16:59:19 2019 -0800
@@ -456,8 +456,6 @@
  */
 int ucdn_compose(uint32_t *code, uint32_t a, uint32_t b);
 
-#ifdef __cplusplus
-}
-#endif
+HB_END_HEADER
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode-emoji-table.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,110 @@
+/* == Start of generated table == */
+/*
+ * The following tables are generated by running:
+ *
+ *   ./gen-emoji-table.py emoji-data.txt
+ *
+ * on file with this header:
+ *
+ * # emoji-data.txt
+ * # Date: 2018-02-07, 07:55:18 GMT
+ * # © 2018 Unicode®, Inc.
+ * # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
+ * # For terms of use, see http://www.unicode.org/terms_of_use.html
+ * #
+ * # Emoji Data for UTS #51
+ * # Version: 11.0
+ * #
+ * # For documentation and usage, see http://www.unicode.org/reports/tr51
+ */
+
+#ifndef HB_UNICODE_EMOJI_TABLE_HH
+#define HB_UNICODE_EMOJI_TABLE_HH
+
+#include "hb-unicode.hh"
+
+
+static const struct hb_unicode_range_t _hb_unicode_emoji_Extended_Pictographic_table[] =
+{
+  {0x00A9, 0x00A9},
+  {0x00AE, 0x00AE},
+  {0x203C, 0x203C},
+  {0x2049, 0x2049},
+  {0x2122, 0x2122},
+  {0x2139, 0x2139},
+  {0x2194, 0x2199},
+  {0x21A9, 0x21AA},
+  {0x231A, 0x231B},
+  {0x2328, 0x2328},
+  {0x2388, 0x2388},
+  {0x23CF, 0x23CF},
+  {0x23E9, 0x23F3},
+  {0x23F8, 0x23FA},
+  {0x24C2, 0x24C2},
+  {0x25AA, 0x25AB},
+  {0x25B6, 0x25B6},
+  {0x25C0, 0x25C0},
+  {0x25FB, 0x25FE},
+  {0x2600, 0x2605},
+  {0x2607, 0x2612},
+  {0x2614, 0x2685},
+  {0x2690, 0x2705},
+  {0x2708, 0x2712},
+  {0x2714, 0x2714},
+  {0x2716, 0x2716},
+  {0x271D, 0x271D},
+  {0x2721, 0x2721},
+  {0x2728, 0x2728},
+  {0x2733, 0x2734},
+  {0x2744, 0x2744},
+  {0x2747, 0x2747},
+  {0x274C, 0x274C},
+  {0x274E, 0x274E},
+  {0x2753, 0x2755},
+  {0x2757, 0x2757},
+  {0x2763, 0x2767},
+  {0x2795, 0x2797},
+  {0x27A1, 0x27A1},
+  {0x27B0, 0x27B0},
+  {0x27BF, 0x27BF},
+  {0x2934, 0x2935},
+  {0x2B05, 0x2B07},
+  {0x2B1B, 0x2B1C},
+  {0x2B50, 0x2B50},
+  {0x2B55, 0x2B55},
+  {0x3030, 0x3030},
+  {0x303D, 0x303D},
+  {0x3297, 0x3297},
+  {0x3299, 0x3299},
+  {0x1F000, 0x1F0FF},
+  {0x1F10D, 0x1F10F},
+  {0x1F12F, 0x1F12F},
+  {0x1F16C, 0x1F171},
+  {0x1F17E, 0x1F17F},
+  {0x1F18E, 0x1F18E},
+  {0x1F191, 0x1F19A},
+  {0x1F1AD, 0x1F1E5},
+  {0x1F201, 0x1F20F},
+  {0x1F21A, 0x1F21A},
+  {0x1F22F, 0x1F22F},
+  {0x1F232, 0x1F23A},
+  {0x1F23C, 0x1F23F},
+  {0x1F249, 0x1F3FA},
+  {0x1F400, 0x1F53D},
+  {0x1F546, 0x1F64F},
+  {0x1F680, 0x1F6FF},
+  {0x1F774, 0x1F77F},
+  {0x1F7D5, 0x1F7FF},
+  {0x1F80C, 0x1F80F},
+  {0x1F848, 0x1F84F},
+  {0x1F85A, 0x1F85F},
+  {0x1F888, 0x1F88F},
+  {0x1F8AE, 0x1F8FF},
+  {0x1F90C, 0x1F93A},
+  {0x1F93C, 0x1F945},
+  {0x1F947, 0x1FFFD},
+};
+
+#endif /* HB_UNICODE_EMOJI_TABLE_HH */
+
+/* == End of generated table == */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,371 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  Codethink Limited
- * Copyright © 2010,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): Behdad Esfahbod
- * Codethink Author(s): Ryan Lortie
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_UNICODE_PRIVATE_HH
-#define HB_UNICODE_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-
-
-extern HB_INTERNAL const uint8_t _hb_modified_combining_class[256];
-
-/*
- * hb_unicode_funcs_t
- */
-
-#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS \
-  HB_UNICODE_FUNC_IMPLEMENT (combining_class) \
-  HB_UNICODE_FUNC_IMPLEMENT (eastasian_width) \
-  HB_UNICODE_FUNC_IMPLEMENT (general_category) \
-  HB_UNICODE_FUNC_IMPLEMENT (mirroring) \
-  HB_UNICODE_FUNC_IMPLEMENT (script) \
-  HB_UNICODE_FUNC_IMPLEMENT (compose) \
-  HB_UNICODE_FUNC_IMPLEMENT (decompose) \
-  HB_UNICODE_FUNC_IMPLEMENT (decompose_compatibility) \
-  /* ^--- Add new callbacks here */
-
-/* Simple callbacks are those taking a hb_codepoint_t and returning a hb_codepoint_t */
-#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_combining_class_t, combining_class) \
-  HB_UNICODE_FUNC_IMPLEMENT (unsigned int, eastasian_width) \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_general_category_t, general_category) \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_codepoint_t, mirroring) \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \
-  /* ^--- Add new simple callbacks here */
-
-struct hb_unicode_funcs_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_unicode_funcs_t *parent;
-
-  bool immutable;
-
-#define HB_UNICODE_FUNC_IMPLEMENT(return_type, name) \
-  inline return_type name (hb_codepoint_t unicode) { return func.name (this, unicode, user_data.name); }
-HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
-#undef HB_UNICODE_FUNC_IMPLEMENT
-
-  inline hb_bool_t compose (hb_codepoint_t a, hb_codepoint_t b,
-                            hb_codepoint_t *ab)
-  {
-    *ab = 0;
-    if (unlikely (!a || !b)) return false;
-    return func.compose (this, a, b, ab, user_data.compose);
-  }
-
-  inline hb_bool_t decompose (hb_codepoint_t ab,
-                              hb_codepoint_t *a, hb_codepoint_t *b)
-  {
-    *a = ab; *b = 0;
-    return func.decompose (this, ab, a, b, user_data.decompose);
-  }
-
-  inline unsigned int decompose_compatibility (hb_codepoint_t  u,
-                                               hb_codepoint_t *decomposed)
-  {
-    unsigned int ret = func.decompose_compatibility (this, u, decomposed, user_data.decompose_compatibility);
-    if (ret == 1 && u == decomposed[0]) {
-      decomposed[0] = 0;
-      return 0;
-    }
-    decomposed[ret] = 0;
-    return ret;
-  }
-
-
-  inline unsigned int
-  modified_combining_class (hb_codepoint_t unicode)
-  {
-    /* XXX This hack belongs to the Myanmar shaper. */
-    if (unlikely (unicode == 0x1037u)) unicode = 0x103Au;
-
-    /* XXX This hack belongs to the USE shaper (for Tai Tham):
-     * Reorder SAKOT to ensure it comes after any tone marks. */
-    if (unlikely (unicode == 0x1A60u)) return 254;
-
-    /* XXX This hack belongs to the Tibetan shaper:
-     * Reorder PADMA to ensure it comes after any vowel marks. */
-    if (unlikely (unicode == 0x0FC6u)) return 254;
-    /* Reorder TSA -PHRU to reorder before U+0F74 */
-    if (unlikely (unicode == 0x0F39u)) return 127;
-
-    return _hb_modified_combining_class[combining_class (unicode)];
-  }
-
-  static inline hb_bool_t
-  is_variation_selector (hb_codepoint_t unicode)
-  {
-    /* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the
-     * Arabic shaper.  No need to match them here. */
-    return unlikely (hb_in_ranges<hb_codepoint_t> (unicode,
-                                   0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */
-                                   0xE0100u, 0xE01EFu));  /* VARIATION SELECTOR-17..256 */
-  }
-
-  /* Default_Ignorable codepoints:
-   *
-   * Note: While U+115F, U+1160, U+3164 and U+FFA0 are Default_Ignorable,
-   * we do NOT want to hide them, as the way Uniscribe has implemented them
-   * is with regular spacing glyphs, and that's the way fonts are made to work.
-   * As such, we make exceptions for those four.
-   * Also ignoring U+1BCA0..1BCA3. https://github.com/harfbuzz/harfbuzz/issues/503
-   *
-   * Unicode 7.0:
-   * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
-   * 00AD          # Cf       SOFT HYPHEN
-   * 034F          # Mn       COMBINING GRAPHEME JOINER
-   * 061C          # Cf       ARABIC LETTER MARK
-   * 115F..1160    # Lo   [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
-   * 17B4..17B5    # Mn   [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
-   * 180B..180D    # Mn   [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
-   * 180E          # Cf       MONGOLIAN VOWEL SEPARATOR
-   * 200B..200F    # Cf   [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
-   * 202A..202E    # Cf   [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
-   * 2060..2064    # Cf   [5] WORD JOINER..INVISIBLE PLUS
-   * 2065          # Cn       <reserved-2065>
-   * 2066..206F    # Cf  [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
-   * 3164          # Lo       HANGUL FILLER
-   * FE00..FE0F    # Mn  [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
-   * FEFF          # Cf       ZERO WIDTH NO-BREAK SPACE
-   * FFA0          # Lo       HALFWIDTH HANGUL FILLER
-   * FFF0..FFF8    # Cn   [9] <reserved-FFF0>..<reserved-FFF8>
-   * 1BCA0..1BCA3  # Cf   [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
-   * 1D173..1D17A  # Cf   [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
-   * E0000         # Cn       <reserved-E0000>
-   * E0001         # Cf       LANGUAGE TAG
-   * E0002..E001F  # Cn  [30] <reserved-E0002>..<reserved-E001F>
-   * E0020..E007F  # Cf  [96] TAG SPACE..CANCEL TAG
-   * E0080..E00FF  # Cn [128] <reserved-E0080>..<reserved-E00FF>
-   * E0100..E01EF  # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
-   * E01F0..E0FFF  # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
-   */
-  static inline hb_bool_t
-  is_default_ignorable (hb_codepoint_t ch)
-  {
-    hb_codepoint_t plane = ch >> 16;
-    if (likely (plane == 0))
-    {
-      /* BMP */
-      hb_codepoint_t page = ch >> 8;
-      switch (page) {
-        case 0x00: return unlikely (ch == 0x00ADu);
-        case 0x03: return unlikely (ch == 0x034Fu);
-        case 0x06: return unlikely (ch == 0x061Cu);
-        case 0x17: return hb_in_range<hb_codepoint_t> (ch, 0x17B4u, 0x17B5u);
-        case 0x18: return hb_in_range<hb_codepoint_t> (ch, 0x180Bu, 0x180Eu);
-        case 0x20: return hb_in_ranges<hb_codepoint_t> (ch, 0x200Bu, 0x200Fu,
-                                            0x202Au, 0x202Eu,
-                                            0x2060u, 0x206Fu);
-        case 0xFE: return hb_in_range<hb_codepoint_t> (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu;
-        case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0u, 0xFFF8u);
-        default: return false;
-      }
-    }
-    else
-    {
-      /* Other planes */
-      switch (plane) {
-        case 0x01: return hb_in_range<hb_codepoint_t> (ch, 0x1D173u, 0x1D17Au);
-        case 0x0E: return hb_in_range<hb_codepoint_t> (ch, 0xE0000u, 0xE0FFFu);
-        default: return false;
-      }
-    }
-  }
-
-  /* Space estimates based on:
-   * https://unicode.org/charts/PDF/U2000.pdf
-   * https://docs.microsoft.com/en-us/typography/develop/character-design-standards/whitespace
-   */
-  enum space_t {
-    NOT_SPACE = 0,
-    SPACE_EM   = 1,
-    SPACE_EM_2 = 2,
-    SPACE_EM_3 = 3,
-    SPACE_EM_4 = 4,
-    SPACE_EM_5 = 5,
-    SPACE_EM_6 = 6,
-    SPACE_EM_16 = 16,
-    SPACE_4_EM_18,      /* 4/18th of an EM! */
-    SPACE,
-    SPACE_FIGURE,
-    SPACE_PUNCTUATION,
-    SPACE_NARROW,
-  };
-  static inline space_t
-  space_fallback_type (hb_codepoint_t u)
-  {
-    switch (u)
-    {
-      /* All GC=Zs chars that can use a fallback. */
-      default:      return NOT_SPACE;   /* U+1680 OGHAM SPACE MARK */
-      case 0x0020u: return SPACE;       /* U+0020 SPACE */
-      case 0x00A0u: return SPACE;       /* U+00A0 NO-BREAK SPACE */
-      case 0x2000u: return SPACE_EM_2;  /* U+2000 EN QUAD */
-      case 0x2001u: return SPACE_EM;    /* U+2001 EM QUAD */
-      case 0x2002u: return SPACE_EM_2;  /* U+2002 EN SPACE */
-      case 0x2003u: return SPACE_EM;    /* U+2003 EM SPACE */
-      case 0x2004u: return SPACE_EM_3;  /* U+2004 THREE-PER-EM SPACE */
-      case 0x2005u: return SPACE_EM_4;  /* U+2005 FOUR-PER-EM SPACE */
-      case 0x2006u: return SPACE_EM_6;  /* U+2006 SIX-PER-EM SPACE */
-      case 0x2007u: return SPACE_FIGURE;        /* U+2007 FIGURE SPACE */
-      case 0x2008u: return SPACE_PUNCTUATION;   /* U+2008 PUNCTUATION SPACE */
-      case 0x2009u: return SPACE_EM_5;          /* U+2009 THIN SPACE */
-      case 0x200Au: return SPACE_EM_16;         /* U+200A HAIR SPACE */
-      case 0x202Fu: return SPACE_NARROW;        /* U+202F NARROW NO-BREAK SPACE */
-      case 0x205Fu: return SPACE_4_EM_18;       /* U+205F MEDIUM MATHEMATICAL SPACE */
-      case 0x3000u: return SPACE_EM;            /* U+3000 IDEOGRAPHIC SPACE */
-    }
-  }
-
-  struct {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_func_t name;
-    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-  } func;
-
-  struct {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) void *name;
-    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-  } user_data;
-
-  struct {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
-    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-  } destroy;
-};
-
-
-extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
-
-
-/* Modified combining marks */
-
-/* Hebrew
- *
- * We permute the "fixed-position" classes 10-26 into the order
- * described in the SBL Hebrew manual:
- *
- * https://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf
- *
- * (as recommended by:
- *  https://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering/msg22823/)
- *
- * More details here:
- * https://bugzilla.mozilla.org/show_bug.cgi?id=662055
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC10 22 /* sheva */
-#define HB_MODIFIED_COMBINING_CLASS_CCC11 15 /* hataf segol */
-#define HB_MODIFIED_COMBINING_CLASS_CCC12 16 /* hataf patah */
-#define HB_MODIFIED_COMBINING_CLASS_CCC13 17 /* hataf qamats */
-#define HB_MODIFIED_COMBINING_CLASS_CCC14 23 /* hiriq */
-#define HB_MODIFIED_COMBINING_CLASS_CCC15 18 /* tsere */
-#define HB_MODIFIED_COMBINING_CLASS_CCC16 19 /* segol */
-#define HB_MODIFIED_COMBINING_CLASS_CCC17 20 /* patah */
-#define HB_MODIFIED_COMBINING_CLASS_CCC18 21 /* qamats */
-#define HB_MODIFIED_COMBINING_CLASS_CCC19 14 /* holam */
-#define HB_MODIFIED_COMBINING_CLASS_CCC20 24 /* qubuts */
-#define HB_MODIFIED_COMBINING_CLASS_CCC21 12 /* dagesh */
-#define HB_MODIFIED_COMBINING_CLASS_CCC22 25 /* meteg */
-#define HB_MODIFIED_COMBINING_CLASS_CCC23 13 /* rafe */
-#define HB_MODIFIED_COMBINING_CLASS_CCC24 10 /* shin dot */
-#define HB_MODIFIED_COMBINING_CLASS_CCC25 11 /* sin dot */
-#define HB_MODIFIED_COMBINING_CLASS_CCC26 26 /* point varika */
-
-/*
- * Arabic
- *
- * Modify to move Shadda (ccc=33) before other marks.  See:
- * https://unicode.org/faq/normalization.html#8
- * https://unicode.org/faq/normalization.html#9
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC27 28 /* fathatan */
-#define HB_MODIFIED_COMBINING_CLASS_CCC28 29 /* dammatan */
-#define HB_MODIFIED_COMBINING_CLASS_CCC29 30 /* kasratan */
-#define HB_MODIFIED_COMBINING_CLASS_CCC30 31 /* fatha */
-#define HB_MODIFIED_COMBINING_CLASS_CCC31 32 /* damma */
-#define HB_MODIFIED_COMBINING_CLASS_CCC32 33 /* kasra */
-#define HB_MODIFIED_COMBINING_CLASS_CCC33 27 /* shadda */
-#define HB_MODIFIED_COMBINING_CLASS_CCC34 34 /* sukun */
-#define HB_MODIFIED_COMBINING_CLASS_CCC35 35 /* superscript alef */
-
-/* Syriac */
-#define HB_MODIFIED_COMBINING_CLASS_CCC36 36 /* superscript alaph */
-
-/* Telugu
- *
- * Modify Telugu length marks (ccc=84, ccc=91).
- * These are the only matras in the main Indic scripts range that have
- * a non-zero ccc.  That makes them reorder with the Halant that is
- * ccc=9.  Just zero them, we don't need them in our Indic shaper.
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC84 0 /* length mark */
-#define HB_MODIFIED_COMBINING_CLASS_CCC91 0 /* ai length mark */
-
-/* Thai
- *
- * Modify U+0E38 and U+0E39 (ccc=103) to be reordered before U+0E3A (ccc=9).
- * Assign 3, which is unassigned otherwise.
- * Uniscribe does this reordering too.
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC103 3 /* sara u / sara uu */
-#define HB_MODIFIED_COMBINING_CLASS_CCC107 107 /* mai * */
-
-/* Lao */
-#define HB_MODIFIED_COMBINING_CLASS_CCC118 118 /* sign u / sign uu */
-#define HB_MODIFIED_COMBINING_CLASS_CCC122 122 /* mai * */
-
-/* Tibetan
- *
- * In case of multiple vowel-signs, use u first (but after achung)
- * this allows Dzongkha multi-vowel shortcuts to render correctly
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC129 129 /* sign aa */
-#define HB_MODIFIED_COMBINING_CLASS_CCC130 132 /* sign i */
-#define HB_MODIFIED_COMBINING_CLASS_CCC132 131 /* sign u */
-
-/* Misc */
-
-#define HB_UNICODE_GENERAL_CATEGORY_IS_MARK(gen_cat) \
-        (FLAG_UNSAFE (gen_cat) & \
-         (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
-          FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
-          FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
-
-#define HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL(gen_cat) \
-        (FLAG_UNSAFE (gen_cat) & \
-         (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
-          FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \
-          FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL)))
-
-#endif /* HB_UNICODE_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -28,10 +28,24 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
+
+#include "hb-unicode.hh"
+
 
-#include "hb-unicode-private.hh"
-
+/**
+ * SECTION: hb-unicode
+ * @title: hb-unicode
+ * @short_description: Unicode character property access
+ * @include: hb.h
+ *
+ * Unicode functions are used to access Unicode character properties.
+ * Client can pass its own Unicode functions to HarfBuzz, or access
+ * the built-in Unicode functions that come with HarfBuzz.
+ *
+ * With the Unicode functions, one can query variour Unicode character
+ * properties, such as General Category, Script, Combining Class, etc.
+ **/
 
 
 /*
@@ -109,40 +123,23 @@
 }
 
 
-#define HB_UNICODE_FUNCS_IMPLEMENT_SET \
-  HB_UNICODE_FUNCS_IMPLEMENT (glib) \
-  HB_UNICODE_FUNCS_IMPLEMENT (icu) \
-  HB_UNICODE_FUNCS_IMPLEMENT (ucdn) \
-  HB_UNICODE_FUNCS_IMPLEMENT (nil) \
-  /* ^--- Add new callbacks before nil */
-
-#define hb_nil_get_unicode_funcs hb_unicode_funcs_get_empty
-
-/* Prototype them all */
-#define HB_UNICODE_FUNCS_IMPLEMENT(set) \
-extern "C" hb_unicode_funcs_t *hb_##set##_get_unicode_funcs (void);
-HB_UNICODE_FUNCS_IMPLEMENT_SET
-#undef HB_UNICODE_FUNCS_IMPLEMENT
-
+extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs ();
+extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs ();
+extern "C" hb_unicode_funcs_t *hb_ucdn_get_unicode_funcs ();
 
 hb_unicode_funcs_t *
-hb_unicode_funcs_get_default (void)
+hb_unicode_funcs_get_default ()
 {
-#define HB_UNICODE_FUNCS_IMPLEMENT(set) \
-  return hb_##set##_get_unicode_funcs ();
-
 #if defined(HAVE_UCDN)
-  HB_UNICODE_FUNCS_IMPLEMENT(ucdn)
+  return hb_ucdn_get_unicode_funcs ();
 #elif defined(HAVE_GLIB)
-  HB_UNICODE_FUNCS_IMPLEMENT(glib)
+  return hb_glib_get_unicode_funcs ();
 #elif defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN)
-  HB_UNICODE_FUNCS_IMPLEMENT(icu)
+  return hb_icu_get_unicode_funcs ();
 #else
 #define HB_UNICODE_FUNCS_NIL 1
-  HB_UNICODE_FUNCS_IMPLEMENT(nil)
+  return hb_unicode_funcs_get_empty ();
 #endif
-
-#undef HB_UNICODE_FUNCS_IMPLEMENT
 }
 
 #if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
@@ -185,11 +182,11 @@
 }
 
 
-const hb_unicode_funcs_t _hb_unicode_funcs_nil = {
+DEFINE_NULL_INSTANCE (hb_unicode_funcs_t) =
+{
   HB_OBJECT_HEADER_STATIC,
 
   nullptr, /* parent */
-  true, /* immutable */
   {
 #define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_nil,
     HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
@@ -207,9 +204,9 @@
  * Since: 0.9.2
  **/
 hb_unicode_funcs_t *
-hb_unicode_funcs_get_empty (void)
+hb_unicode_funcs_get_empty ()
 {
-  return const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil);
+  return const_cast<hb_unicode_funcs_t *> (&Null(hb_unicode_funcs_t));
 }
 
 /**
@@ -305,10 +302,10 @@
 void
 hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
 {
-  if (unlikely (hb_object_is_inert (ufuncs)))
+  if (hb_object_is_immutable (ufuncs))
     return;
 
-  ufuncs->immutable = true;
+  hb_object_make_immutable (ufuncs);
 }
 
 /**
@@ -324,7 +321,7 @@
 hb_bool_t
 hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs)
 {
-  return ufuncs->immutable;
+  return hb_object_is_immutable (ufuncs);
 }
 
 /**
@@ -352,7 +349,7 @@
                                     void                           *user_data,  \
                                     hb_destroy_func_t               destroy)    \
 {                                                                               \
-  if (ufuncs->immutable)                                                        \
+  if (hb_object_is_immutable (ufuncs))                                          \
     return;                                                                     \
                                                                                 \
   if (ufuncs->destroy.name)                                                     \
@@ -439,6 +436,7 @@
  * Return value:
  *
  * Since: 0.9.2
+ * Deprecated: 2.0.0
  **/
 unsigned int
 hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
@@ -449,7 +447,7 @@
 }
 
 
-/* See hb-unicode-private.hh for details. */
+/* See hb-unicode.hh for details. */
 const uint8_t
 _hb_modified_combining_class[256] =
 {
@@ -561,3 +559,19 @@
   241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
   255, /* HB_UNICODE_COMBINING_CLASS_INVALID */
 };
+
+
+/*
+ * Emoji
+ */
+
+#include "hb-unicode-emoji-table.hh"
+
+bool
+_hb_unicode_is_emoji_Extended_Pictographic (hb_codepoint_t cp)
+{
+  return hb_bsearch (&cp, _hb_unicode_emoji_Extended_Pictographic_table,
+                     ARRAY_LENGTH (_hb_unicode_emoji_Extended_Pictographic_table),
+                     sizeof (hb_unicode_range_t),
+                     hb_unicode_range_t::cmp);
+}
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.h	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.h	Fri Mar 01 16:59:19 2019 -0800
@@ -40,6 +40,14 @@
 HB_BEGIN_DECLS
 
 
+/**
+ * HB_UNICODE_MAX
+ *
+ * Since: 1.9.0
+ **/
+#define HB_UNICODE_MAX 0x10FFFFu
+
+
 /* hb_unicode_general_category_t */
 
 /* Unicode Character Database property: General_Category (gc) */
@@ -222,9 +230,6 @@
 typedef hb_unicode_combining_class_t    (*hb_unicode_combining_class_func_t)    (hb_unicode_funcs_t *ufuncs,
                                                                                  hb_codepoint_t      unicode,
                                                                                  void               *user_data);
-typedef unsigned int                    (*hb_unicode_eastasian_width_func_t)    (hb_unicode_funcs_t *ufuncs,
-                                                                                 hb_codepoint_t      unicode,
-                                                                                 void               *user_data);
 typedef hb_unicode_general_category_t   (*hb_unicode_general_category_func_t)   (hb_unicode_funcs_t *ufuncs,
                                                                                  hb_codepoint_t      unicode,
                                                                                  void               *user_data);
@@ -246,32 +251,6 @@
                                                                                  hb_codepoint_t     *b,
                                                                                  void               *user_data);
 
-/**
- * hb_unicode_decompose_compatibility_func_t:
- * @ufuncs: a Unicode function structure
- * @u: codepoint to decompose
- * @decomposed: address of codepoint array (of length %HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into
- * @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func()
- *
- * Fully decompose @u to its Unicode compatibility decomposition. The codepoints of the decomposition will be written to @decomposed.
- * The complete length of the decomposition will be returned.
- *
- * If @u has no compatibility decomposition, zero should be returned.
- *
- * The Unicode standard guarantees that a buffer of length %HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any
- * compatibility decomposition plus an terminating value of 0.  Consequently, @decompose must be allocated by the caller to be at least this length.  Implementations
- * of this function type must ensure that they do not write past the provided array.
- *
- * Return value: number of codepoints in the full compatibility decomposition of @u, or 0 if no decomposition available.
- */
-typedef unsigned int                    (*hb_unicode_decompose_compatibility_func_t)    (hb_unicode_funcs_t *ufuncs,
-                                                                                         hb_codepoint_t      u,
-                                                                                         hb_codepoint_t     *decomposed,
-                                                                                         void               *user_data);
-
-/* See Unicode 6.1 for details on the maximum decomposition length. */
-#define HB_UNICODE_MAX_DECOMPOSITION_LEN (18+1) /* codepoints */
-
 /* setters */
 
 /**
@@ -291,22 +270,6 @@
                                            void *user_data, hb_destroy_func_t destroy);
 
 /**
- * hb_unicode_funcs_set_eastasian_width_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- *
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
-                                           hb_unicode_eastasian_width_func_t func,
-                                           void *user_data, hb_destroy_func_t destroy);
-
-/**
  * hb_unicode_funcs_set_general_category_func:
  * @ufuncs: a Unicode function structure
  * @func: (closure user_data) (destroy destroy) (scope notified):
@@ -386,22 +349,6 @@
                                      hb_unicode_decompose_func_t func,
                                      void *user_data, hb_destroy_func_t destroy);
 
-/**
- * hb_unicode_funcs_set_decompose_compatibility_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- *
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs,
-                                                   hb_unicode_decompose_compatibility_func_t func,
-                                                   void *user_data, hb_destroy_func_t destroy);
-
 /* accessors */
 
 /**
@@ -414,15 +361,6 @@
                             hb_codepoint_t unicode);
 
 /**
- * hb_unicode_eastasian_width:
- *
- * Since: 0.9.2
- **/
-HB_EXTERN unsigned int
-hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
-                            hb_codepoint_t unicode);
-
-/**
  * hb_unicode_general_category:
  *
  * Since: 0.9.2
@@ -461,11 +399,6 @@
                       hb_codepoint_t     *a,
                       hb_codepoint_t     *b);
 
-HB_EXTERN unsigned int
-hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
-                                    hb_codepoint_t      u,
-                                    hb_codepoint_t     *decomposed);
-
 HB_END_DECLS
 
 #endif /* HB_UNICODE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,394 @@
+/*
+ * Copyright © 2009  Red Hat, Inc.
+ * Copyright © 2011  Codethink Limited
+ * Copyright © 2010,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): Behdad Esfahbod
+ * Codethink Author(s): Ryan Lortie
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_UNICODE_HH
+#define HB_UNICODE_HH
+
+#include "hb.hh"
+
+
+extern HB_INTERNAL const uint8_t _hb_modified_combining_class[256];
+
+/*
+ * hb_unicode_funcs_t
+ */
+
+#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS \
+  HB_UNICODE_FUNC_IMPLEMENT (combining_class) \
+  HB_UNICODE_FUNC_IMPLEMENT (eastasian_width) \
+  HB_UNICODE_FUNC_IMPLEMENT (general_category) \
+  HB_UNICODE_FUNC_IMPLEMENT (mirroring) \
+  HB_UNICODE_FUNC_IMPLEMENT (script) \
+  HB_UNICODE_FUNC_IMPLEMENT (compose) \
+  HB_UNICODE_FUNC_IMPLEMENT (decompose) \
+  HB_UNICODE_FUNC_IMPLEMENT (decompose_compatibility) \
+  /* ^--- Add new callbacks here */
+
+/* Simple callbacks are those taking a hb_codepoint_t and returning a hb_codepoint_t */
+#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE \
+  HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_combining_class_t, combining_class) \
+  HB_UNICODE_FUNC_IMPLEMENT (unsigned int, eastasian_width) \
+  HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_general_category_t, general_category) \
+  HB_UNICODE_FUNC_IMPLEMENT (hb_codepoint_t, mirroring) \
+  HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \
+  /* ^--- Add new simple callbacks here */
+
+struct hb_unicode_funcs_t
+{
+  hb_object_header_t header;
+
+  hb_unicode_funcs_t *parent;
+
+#define HB_UNICODE_FUNC_IMPLEMENT(return_type, name) \
+  return_type name (hb_codepoint_t unicode) { return func.name (this, unicode, user_data.name); }
+HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
+#undef HB_UNICODE_FUNC_IMPLEMENT
+
+  hb_bool_t compose (hb_codepoint_t a, hb_codepoint_t b,
+                     hb_codepoint_t *ab)
+  {
+    *ab = 0;
+    if (unlikely (!a || !b)) return false;
+    return func.compose (this, a, b, ab, user_data.compose);
+  }
+
+  hb_bool_t decompose (hb_codepoint_t ab,
+                       hb_codepoint_t *a, hb_codepoint_t *b)
+  {
+    *a = ab; *b = 0;
+    return func.decompose (this, ab, a, b, user_data.decompose);
+  }
+
+  unsigned int decompose_compatibility (hb_codepoint_t  u,
+                                        hb_codepoint_t *decomposed)
+  {
+    unsigned int ret = func.decompose_compatibility (this, u, decomposed, user_data.decompose_compatibility);
+    if (ret == 1 && u == decomposed[0]) {
+      decomposed[0] = 0;
+      return 0;
+    }
+    decomposed[ret] = 0;
+    return ret;
+  }
+
+  unsigned int
+  modified_combining_class (hb_codepoint_t u)
+  {
+    /* XXX This hack belongs to the Myanmar shaper. */
+    if (unlikely (u == 0x1037u)) u = 0x103Au;
+
+    /* XXX This hack belongs to the USE shaper (for Tai Tham):
+     * Reorder SAKOT to ensure it comes after any tone marks. */
+    if (unlikely (u == 0x1A60u)) return 254;
+
+    /* XXX This hack belongs to the Tibetan shaper:
+     * Reorder PADMA to ensure it comes after any vowel marks. */
+    if (unlikely (u == 0x0FC6u)) return 254;
+    /* Reorder TSA -PHRU to reorder before U+0F74 */
+    if (unlikely (u == 0x0F39u)) return 127;
+
+    return _hb_modified_combining_class[combining_class (u)];
+  }
+
+  static hb_bool_t
+  is_variation_selector (hb_codepoint_t unicode)
+  {
+    /* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the
+     * Arabic shaper.  No need to match them here. */
+    return unlikely (hb_in_ranges<hb_codepoint_t> (unicode,
+                                                   0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */
+                                                   0xE0100u, 0xE01EFu));  /* VARIATION SELECTOR-17..256 */
+  }
+
+  /* Default_Ignorable codepoints:
+   *
+   * Note: While U+115F, U+1160, U+3164 and U+FFA0 are Default_Ignorable,
+   * we do NOT want to hide them, as the way Uniscribe has implemented them
+   * is with regular spacing glyphs, and that's the way fonts are made to work.
+   * As such, we make exceptions for those four.
+   * Also ignoring U+1BCA0..1BCA3. https://github.com/harfbuzz/harfbuzz/issues/503
+   *
+   * Unicode 7.0:
+   * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
+   * 00AD          # Cf       SOFT HYPHEN
+   * 034F          # Mn       COMBINING GRAPHEME JOINER
+   * 061C          # Cf       ARABIC LETTER MARK
+   * 115F..1160    # Lo   [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
+   * 17B4..17B5    # Mn   [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
+   * 180B..180D    # Mn   [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
+   * 180E          # Cf       MONGOLIAN VOWEL SEPARATOR
+   * 200B..200F    # Cf   [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
+   * 202A..202E    # Cf   [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
+   * 2060..2064    # Cf   [5] WORD JOINER..INVISIBLE PLUS
+   * 2065          # Cn       <reserved-2065>
+   * 2066..206F    # Cf  [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
+   * 3164          # Lo       HANGUL FILLER
+   * FE00..FE0F    # Mn  [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
+   * FEFF          # Cf       ZERO WIDTH NO-BREAK SPACE
+   * FFA0          # Lo       HALFWIDTH HANGUL FILLER
+   * FFF0..FFF8    # Cn   [9] <reserved-FFF0>..<reserved-FFF8>
+   * 1BCA0..1BCA3  # Cf   [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
+   * 1D173..1D17A  # Cf   [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
+   * E0000         # Cn       <reserved-E0000>
+   * E0001         # Cf       LANGUAGE TAG
+   * E0002..E001F  # Cn  [30] <reserved-E0002>..<reserved-E001F>
+   * E0020..E007F  # Cf  [96] TAG SPACE..CANCEL TAG
+   * E0080..E00FF  # Cn [128] <reserved-E0080>..<reserved-E00FF>
+   * E0100..E01EF  # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
+   * E01F0..E0FFF  # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
+   */
+  static hb_bool_t
+  is_default_ignorable (hb_codepoint_t ch)
+  {
+    hb_codepoint_t plane = ch >> 16;
+    if (likely (plane == 0))
+    {
+      /* BMP */
+      hb_codepoint_t page = ch >> 8;
+      switch (page) {
+        case 0x00: return unlikely (ch == 0x00ADu);
+        case 0x03: return unlikely (ch == 0x034Fu);
+        case 0x06: return unlikely (ch == 0x061Cu);
+        case 0x17: return hb_in_range<hb_codepoint_t> (ch, 0x17B4u, 0x17B5u);
+        case 0x18: return hb_in_range<hb_codepoint_t> (ch, 0x180Bu, 0x180Eu);
+        case 0x20: return hb_in_ranges<hb_codepoint_t> (ch, 0x200Bu, 0x200Fu,
+                                            0x202Au, 0x202Eu,
+                                            0x2060u, 0x206Fu);
+        case 0xFE: return hb_in_range<hb_codepoint_t> (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu;
+        case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0u, 0xFFF8u);
+        default: return false;
+      }
+    }
+    else
+    {
+      /* Other planes */
+      switch (plane) {
+        case 0x01: return hb_in_range<hb_codepoint_t> (ch, 0x1D173u, 0x1D17Au);
+        case 0x0E: return hb_in_range<hb_codepoint_t> (ch, 0xE0000u, 0xE0FFFu);
+        default: return false;
+      }
+    }
+  }
+
+  /* Space estimates based on:
+   * https://unicode.org/charts/PDF/U2000.pdf
+   * https://docs.microsoft.com/en-us/typography/develop/character-design-standards/whitespace
+   */
+  enum space_t {
+    NOT_SPACE = 0,
+    SPACE_EM   = 1,
+    SPACE_EM_2 = 2,
+    SPACE_EM_3 = 3,
+    SPACE_EM_4 = 4,
+    SPACE_EM_5 = 5,
+    SPACE_EM_6 = 6,
+    SPACE_EM_16 = 16,
+    SPACE_4_EM_18,      /* 4/18th of an EM! */
+    SPACE,
+    SPACE_FIGURE,
+    SPACE_PUNCTUATION,
+    SPACE_NARROW,
+  };
+  static space_t
+  space_fallback_type (hb_codepoint_t u)
+  {
+    switch (u)
+    {
+      /* All GC=Zs chars that can use a fallback. */
+      default:      return NOT_SPACE;   /* U+1680 OGHAM SPACE MARK */
+      case 0x0020u: return SPACE;       /* U+0020 SPACE */
+      case 0x00A0u: return SPACE;       /* U+00A0 NO-BREAK SPACE */
+      case 0x2000u: return SPACE_EM_2;  /* U+2000 EN QUAD */
+      case 0x2001u: return SPACE_EM;    /* U+2001 EM QUAD */
+      case 0x2002u: return SPACE_EM_2;  /* U+2002 EN SPACE */
+      case 0x2003u: return SPACE_EM;    /* U+2003 EM SPACE */
+      case 0x2004u: return SPACE_EM_3;  /* U+2004 THREE-PER-EM SPACE */
+      case 0x2005u: return SPACE_EM_4;  /* U+2005 FOUR-PER-EM SPACE */
+      case 0x2006u: return SPACE_EM_6;  /* U+2006 SIX-PER-EM SPACE */
+      case 0x2007u: return SPACE_FIGURE;        /* U+2007 FIGURE SPACE */
+      case 0x2008u: return SPACE_PUNCTUATION;   /* U+2008 PUNCTUATION SPACE */
+      case 0x2009u: return SPACE_EM_5;          /* U+2009 THIN SPACE */
+      case 0x200Au: return SPACE_EM_16;         /* U+200A HAIR SPACE */
+      case 0x202Fu: return SPACE_NARROW;        /* U+202F NARROW NO-BREAK SPACE */
+      case 0x205Fu: return SPACE_4_EM_18;       /* U+205F MEDIUM MATHEMATICAL SPACE */
+      case 0x3000u: return SPACE_EM;            /* U+3000 IDEOGRAPHIC SPACE */
+    }
+  }
+
+  struct {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_func_t name;
+    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+  } func;
+
+  struct {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) void *name;
+    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+  } user_data;
+
+  struct {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
+    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+  } destroy;
+};
+DECLARE_NULL_INSTANCE (hb_unicode_funcs_t);
+
+
+/*
+ * Modified combining marks
+ */
+
+/* Hebrew
+ *
+ * We permute the "fixed-position" classes 10-26 into the order
+ * described in the SBL Hebrew manual:
+ *
+ * https://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf
+ *
+ * (as recommended by:
+ *  https://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering/msg22823/)
+ *
+ * More details here:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=662055
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC10 22 /* sheva */
+#define HB_MODIFIED_COMBINING_CLASS_CCC11 15 /* hataf segol */
+#define HB_MODIFIED_COMBINING_CLASS_CCC12 16 /* hataf patah */
+#define HB_MODIFIED_COMBINING_CLASS_CCC13 17 /* hataf qamats */
+#define HB_MODIFIED_COMBINING_CLASS_CCC14 23 /* hiriq */
+#define HB_MODIFIED_COMBINING_CLASS_CCC15 18 /* tsere */
+#define HB_MODIFIED_COMBINING_CLASS_CCC16 19 /* segol */
+#define HB_MODIFIED_COMBINING_CLASS_CCC17 20 /* patah */
+#define HB_MODIFIED_COMBINING_CLASS_CCC18 21 /* qamats */
+#define HB_MODIFIED_COMBINING_CLASS_CCC19 14 /* holam */
+#define HB_MODIFIED_COMBINING_CLASS_CCC20 24 /* qubuts */
+#define HB_MODIFIED_COMBINING_CLASS_CCC21 12 /* dagesh */
+#define HB_MODIFIED_COMBINING_CLASS_CCC22 25 /* meteg */
+#define HB_MODIFIED_COMBINING_CLASS_CCC23 13 /* rafe */
+#define HB_MODIFIED_COMBINING_CLASS_CCC24 10 /* shin dot */
+#define HB_MODIFIED_COMBINING_CLASS_CCC25 11 /* sin dot */
+#define HB_MODIFIED_COMBINING_CLASS_CCC26 26 /* point varika */
+
+/*
+ * Arabic
+ *
+ * Modify to move Shadda (ccc=33) before other marks.  See:
+ * https://unicode.org/faq/normalization.html#8
+ * https://unicode.org/faq/normalization.html#9
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC27 28 /* fathatan */
+#define HB_MODIFIED_COMBINING_CLASS_CCC28 29 /* dammatan */
+#define HB_MODIFIED_COMBINING_CLASS_CCC29 30 /* kasratan */
+#define HB_MODIFIED_COMBINING_CLASS_CCC30 31 /* fatha */
+#define HB_MODIFIED_COMBINING_CLASS_CCC31 32 /* damma */
+#define HB_MODIFIED_COMBINING_CLASS_CCC32 33 /* kasra */
+#define HB_MODIFIED_COMBINING_CLASS_CCC33 27 /* shadda */
+#define HB_MODIFIED_COMBINING_CLASS_CCC34 34 /* sukun */
+#define HB_MODIFIED_COMBINING_CLASS_CCC35 35 /* superscript alef */
+
+/* Syriac */
+#define HB_MODIFIED_COMBINING_CLASS_CCC36 36 /* superscript alaph */
+
+/* Telugu
+ *
+ * Modify Telugu length marks (ccc=84, ccc=91).
+ * These are the only matras in the main Indic scripts range that have
+ * a non-zero ccc.  That makes them reorder with the Halant that is
+ * ccc=9.  Just zero them, we don't need them in our Indic shaper.
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC84 0 /* length mark */
+#define HB_MODIFIED_COMBINING_CLASS_CCC91 0 /* ai length mark */
+
+/* Thai
+ *
+ * Modify U+0E38 and U+0E39 (ccc=103) to be reordered before U+0E3A (ccc=9).
+ * Assign 3, which is unassigned otherwise.
+ * Uniscribe does this reordering too.
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC103 3 /* sara u / sara uu */
+#define HB_MODIFIED_COMBINING_CLASS_CCC107 107 /* mai * */
+
+/* Lao */
+#define HB_MODIFIED_COMBINING_CLASS_CCC118 118 /* sign u / sign uu */
+#define HB_MODIFIED_COMBINING_CLASS_CCC122 122 /* mai * */
+
+/* Tibetan
+ *
+ * In case of multiple vowel-signs, use u first (but after achung)
+ * this allows Dzongkha multi-vowel shortcuts to render correctly
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC129 129 /* sign aa */
+#define HB_MODIFIED_COMBINING_CLASS_CCC130 132 /* sign i */
+#define HB_MODIFIED_COMBINING_CLASS_CCC132 131 /* sign u */
+
+/* Misc */
+
+#define HB_UNICODE_GENERAL_CATEGORY_IS_MARK(gen_cat) \
+        (FLAG_UNSAFE (gen_cat) & \
+         (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
+          FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
+          FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
+
+
+/*
+ * Ranges, used for bsearch tables.
+ */
+
+struct hb_unicode_range_t
+{
+  static int
+  cmp (const void *_key, const void *_item)
+  {
+    hb_codepoint_t cp = *((hb_codepoint_t *) _key);
+    const hb_unicode_range_t *range = (hb_unicode_range_t *) _item;
+
+    if (cp < range->start)
+      return -1;
+    else if (cp <= range->end)
+      return 0;
+    else
+      return +1;
+  }
+
+  hb_codepoint_t start;
+  hb_codepoint_t end;
+};
+
+/*
+ * Emoji.
+ */
+
+HB_INTERNAL bool
+_hb_unicode_is_emoji_Extended_Pictographic (hb_codepoint_t cp);
+
+
+#endif /* HB_UNICODE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-utf-private.hh	Wed Feb 27 18:46:55 2019 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,282 +0,0 @@
-/*
- * Copyright © 2011,2012,2014  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_UTF_PRIVATE_HH
-#define HB_UTF_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-struct hb_utf8_t
-{
-  typedef uint8_t codepoint_t;
-
-  static inline const uint8_t *
-  next (const uint8_t *text,
-        const uint8_t *end,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement)
-  {
-    /* Written to only accept well-formed sequences.
-     * Based on ideas from ICU's U8_NEXT.
-     * Generates one "replacement" for each ill-formed byte. */
-
-    hb_codepoint_t c = *text++;
-
-    if (c > 0x7Fu)
-    {
-      if (hb_in_range<hb_codepoint_t> (c, 0xC2u, 0xDFu)) /* Two-byte */
-      {
-        unsigned int t1;
-        if (likely (text < end &&
-                    (t1 = text[0] - 0x80u) <= 0x3Fu))
-        {
-          c = ((c&0x1Fu)<<6) | t1;
-          text++;
-        }
-        else
-          goto error;
-      }
-      else if (hb_in_range<hb_codepoint_t> (c, 0xE0u, 0xEFu)) /* Three-byte */
-      {
-        unsigned int t1, t2;
-        if (likely (1 < end - text &&
-                    (t1 = text[0] - 0x80u) <= 0x3Fu &&
-                    (t2 = text[1] - 0x80u) <= 0x3Fu))
-        {
-          c = ((c&0xFu)<<12) | (t1<<6) | t2;
-          if (unlikely (c < 0x0800u || hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
-            goto error;
-          text += 2;
-        }
-        else
-          goto error;
-      }
-      else if (hb_in_range<hb_codepoint_t> (c, 0xF0u, 0xF4u)) /* Four-byte */
-      {
-        unsigned int t1, t2, t3;
-        if (likely (2 < end - text &&
-                    (t1 = text[0] - 0x80u) <= 0x3Fu &&
-                    (t2 = text[1] - 0x80u) <= 0x3Fu &&
-                    (t3 = text[2] - 0x80u) <= 0x3Fu))
-        {
-          c = ((c&0x7u)<<18) | (t1<<12) | (t2<<6) | t3;
-          if (unlikely (!hb_in_range<hb_codepoint_t> (c, 0x10000u, 0x10FFFFu)))
-            goto error;
-          text += 3;
-        }
-        else
-          goto error;
-      }
-      else
-        goto error;
-    }
-
-    *unicode = c;
-    return text;
-
-  error:
-    *unicode = replacement;
-    return text;
-  }
-
-  static inline const uint8_t *
-  prev (const uint8_t *text,
-        const uint8_t *start,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement)
-  {
-    const uint8_t *end = text--;
-    while (start < text && (*text & 0xc0) == 0x80 && end - text < 4)
-      text--;
-
-    if (likely (next (text, end, unicode, replacement) == end))
-      return text;
-
-    *unicode = replacement;
-    return end - 1;
-  }
-
-  static inline unsigned int
-  strlen (const uint8_t *text)
-  {
-    return ::strlen ((const char *) text);
-  }
-};
-
-
-struct hb_utf16_t
-{
-  typedef uint16_t codepoint_t;
-
-  static inline const uint16_t *
-  next (const uint16_t *text,
-        const uint16_t *end,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *text++;
-
-    if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
-    {
-      *unicode = c;
-      return text;
-    }
-
-    if (likely (c <= 0xDBFFu && text < end))
-    {
-      /* High-surrogate in c */
-      hb_codepoint_t l = *text;
-      if (likely (hb_in_range<hb_codepoint_t> (l, 0xDC00u, 0xDFFFu)))
-      {
-        /* Low-surrogate in l */
-        *unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u);
-         text++;
-         return text;
-      }
-    }
-
-    /* Lonely / out-of-order surrogate. */
-    *unicode = replacement;
-    return text;
-  }
-
-  static inline const uint16_t *
-  prev (const uint16_t *text,
-        const uint16_t *start,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *--text;
-
-    if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
-    {
-      *unicode = c;
-      return text;
-    }
-
-    if (likely (c >= 0xDC00u && start < text))
-    {
-      /* Low-surrogate in c */
-      hb_codepoint_t h = text[-1];
-      if (likely (hb_in_range<hb_codepoint_t> (h, 0xD800u, 0xDBFFu)))
-      {
-        /* High-surrogate in h */
-        *unicode = (h << 10) + c - ((0xD800u << 10) - 0x10000u + 0xDC00u);
-        text--;
-        return text;
-      }
-    }
-
-    /* Lonely / out-of-order surrogate. */
-    *unicode = replacement;
-    return text;
-  }
-
-
-  static inline unsigned int
-  strlen (const uint16_t *text)
-  {
-    unsigned int l = 0;
-    while (*text++) l++;
-    return l;
-  }
-};
-
-
-template <bool validate=true>
-struct hb_utf32_t
-{
-  typedef uint32_t codepoint_t;
-
-  static inline const uint32_t *
-  next (const uint32_t *text,
-        const uint32_t *end HB_UNUSED,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *unicode = *text++;
-    if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
-      *unicode = replacement;
-    return text;
-  }
-
-  static inline const uint32_t *
-  prev (const uint32_t *text,
-        const uint32_t *start HB_UNUSED,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *unicode = *--text;
-    if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
-      *unicode = replacement;
-    return text;
-  }
-
-  static inline unsigned int
-  strlen (const uint32_t *text)
-  {
-    unsigned int l = 0;
-    while (*text++) l++;
-    return l;
-  }
-};
-
-
-struct hb_latin1_t
-{
-  typedef uint8_t codepoint_t;
-
-  static inline const uint8_t *
-  next (const uint8_t *text,
-        const uint8_t *end HB_UNUSED,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement HB_UNUSED)
-  {
-    *unicode = *text++;
-    return text;
-  }
-
-  static inline const uint8_t *
-  prev (const uint8_t *text,
-        const uint8_t *start HB_UNUSED,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement)
-  {
-    *unicode = *--text;
-    return text;
-  }
-
-  static inline unsigned int
-  strlen (const uint8_t *text)
-  {
-    unsigned int l = 0;
-    while (*text++) l++;
-    return l;
-  }
-};
-
-#endif /* HB_UTF_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-utf.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,453 @@
+/*
+ * Copyright © 2011,2012,2014  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_UTF_HH
+#define HB_UTF_HH
+
+#include "hb.hh"
+
+#include "hb-open-type.hh"
+
+
+struct hb_utf8_t
+{
+  typedef uint8_t codepoint_t;
+
+  static const codepoint_t *
+  next (const codepoint_t *text,
+        const codepoint_t *end,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement)
+  {
+    /* Written to only accept well-formed sequences.
+     * Based on ideas from ICU's U8_NEXT.
+     * Generates one "replacement" for each ill-formed byte. */
+
+    hb_codepoint_t c = *text++;
+
+    if (c > 0x7Fu)
+    {
+      if (hb_in_range<hb_codepoint_t> (c, 0xC2u, 0xDFu)) /* Two-byte */
+      {
+        unsigned int t1;
+        if (likely (text < end &&
+                    (t1 = text[0] - 0x80u) <= 0x3Fu))
+        {
+          c = ((c&0x1Fu)<<6) | t1;
+          text++;
+        }
+        else
+          goto error;
+      }
+      else if (hb_in_range<hb_codepoint_t> (c, 0xE0u, 0xEFu)) /* Three-byte */
+      {
+        unsigned int t1, t2;
+        if (likely (1 < end - text &&
+                    (t1 = text[0] - 0x80u) <= 0x3Fu &&
+                    (t2 = text[1] - 0x80u) <= 0x3Fu))
+        {
+          c = ((c&0xFu)<<12) | (t1<<6) | t2;
+          if (unlikely (c < 0x0800u || hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
+            goto error;
+          text += 2;
+        }
+        else
+          goto error;
+      }
+      else if (hb_in_range<hb_codepoint_t> (c, 0xF0u, 0xF4u)) /* Four-byte */
+      {
+        unsigned int t1, t2, t3;
+        if (likely (2 < end - text &&
+                    (t1 = text[0] - 0x80u) <= 0x3Fu &&
+                    (t2 = text[1] - 0x80u) <= 0x3Fu &&
+                    (t3 = text[2] - 0x80u) <= 0x3Fu))
+        {
+          c = ((c&0x7u)<<18) | (t1<<12) | (t2<<6) | t3;
+          if (unlikely (!hb_in_range<hb_codepoint_t> (c, 0x10000u, 0x10FFFFu)))
+            goto error;
+          text += 3;
+        }
+        else
+          goto error;
+      }
+      else
+        goto error;
+    }
+
+    *unicode = c;
+    return text;
+
+  error:
+    *unicode = replacement;
+    return text;
+  }
+
+  static const codepoint_t *
+  prev (const codepoint_t *text,
+        const codepoint_t *start,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement)
+  {
+    const codepoint_t *end = text--;
+    while (start < text && (*text & 0xc0) == 0x80 && end - text < 4)
+      text--;
+
+    if (likely (next (text, end, unicode, replacement) == end))
+      return text;
+
+    *unicode = replacement;
+    return end - 1;
+  }
+
+  static unsigned int
+  strlen (const codepoint_t *text)
+  { return ::strlen ((const char *) text); }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode)
+  {
+    if (unicode <   0x0080u) return 1;
+    if (unicode <   0x0800u) return 2;
+    if (unicode <  0x10000u) return 3;
+    if (unicode < 0x110000u) return 4;
+    return 3;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+          const codepoint_t *end,
+          hb_codepoint_t unicode)
+  {
+    if (unlikely (unicode >= 0xD800u && (unicode <= 0xDFFFu || unicode > 0x10FFFFu)))
+      unicode = 0xFFFDu;
+    if (unicode < 0x0080u)
+     *text++ = unicode;
+    else if (unicode < 0x0800u)
+    {
+      if (end - text >= 2)
+      {
+        *text++ =  0xC0u + (0x1Fu & (unicode >>  6));
+        *text++ =  0x80u + (0x3Fu & (unicode      ));
+      }
+    }
+    else if (unicode < 0x10000u)
+    {
+      if (end - text >= 3)
+      {
+        *text++ =  0xE0u + (0x0Fu & (unicode >> 12));
+        *text++ =  0x80u + (0x3Fu & (unicode >>  6));
+        *text++ =  0x80u + (0x3Fu & (unicode      ));
+      }
+    }
+    else
+    {
+      if (end - text >= 4)
+      {
+        *text++ =  0xF0u + (0x07u & (unicode >> 18));
+        *text++ =  0x80u + (0x3Fu & (unicode >> 12));
+        *text++ =  0x80u + (0x3Fu & (unicode >>  6));
+        *text++ =  0x80u + (0x3Fu & (unicode      ));
+      }
+    }
+    return text;
+  }
+};
+
+
+template <typename TCodepoint>
+struct hb_utf16_xe_t
+{
+  static_assert (sizeof (TCodepoint) == 2, "");
+  typedef TCodepoint codepoint_t;
+
+  static const codepoint_t *
+  next (const codepoint_t *text,
+        const codepoint_t *end,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement)
+  {
+    hb_codepoint_t c = *text++;
+
+    if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
+    {
+      *unicode = c;
+      return text;
+    }
+
+    if (likely (c <= 0xDBFFu && text < end))
+    {
+      /* High-surrogate in c */
+      hb_codepoint_t l = *text;
+      if (likely (hb_in_range<hb_codepoint_t> (l, 0xDC00u, 0xDFFFu)))
+      {
+        /* Low-surrogate in l */
+        *unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u);
+         text++;
+         return text;
+      }
+    }
+
+    /* Lonely / out-of-order surrogate. */
+    *unicode = replacement;
+    return text;
+  }
+
+  static const codepoint_t *
+  prev (const codepoint_t *text,
+        const codepoint_t *start,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement)
+  {
+    hb_codepoint_t c = *--text;
+
+    if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
+    {
+      *unicode = c;
+      return text;
+    }
+
+    if (likely (c >= 0xDC00u && start < text))
+    {
+      /* Low-surrogate in c */
+      hb_codepoint_t h = text[-1];
+      if (likely (hb_in_range<hb_codepoint_t> (h, 0xD800u, 0xDBFFu)))
+      {
+        /* High-surrogate in h */
+        *unicode = (h << 10) + c - ((0xD800u << 10) - 0x10000u + 0xDC00u);
+        text--;
+        return text;
+      }
+    }
+
+    /* Lonely / out-of-order surrogate. */
+    *unicode = replacement;
+    return text;
+  }
+
+
+  static unsigned int
+  strlen (const codepoint_t *text)
+  {
+    unsigned int l = 0;
+    while (*text++) l++;
+    return l;
+  }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode)
+  {
+    return unicode < 0x10000 ? 1 : 2;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+          const codepoint_t *end,
+          hb_codepoint_t unicode)
+  {
+    if (unlikely (unicode >= 0xD800u && (unicode <= 0xDFFFu || unicode > 0x10FFFFu)))
+      unicode = 0xFFFDu;
+    if (unicode < 0x10000u)
+     *text++ = unicode;
+    else if (end - text >= 2)
+    {
+      unicode -= 0x10000u;
+      *text++ =  0xD800u + (unicode >> 10);
+      *text++ =  0xDC00u + (unicode & 0x03FFu);
+    }
+    return text;
+  }
+};
+
+typedef hb_utf16_xe_t<uint16_t> hb_utf16_t;
+typedef hb_utf16_xe_t<OT::HBUINT16> hb_utf16_be_t;
+
+
+template <typename TCodepoint, bool validate=true>
+struct hb_utf32_xe_t
+{
+  static_assert (sizeof (TCodepoint) == 4, "");
+  typedef TCodepoint codepoint_t;
+
+  static const TCodepoint *
+  next (const TCodepoint *text,
+        const TCodepoint *end HB_UNUSED,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement)
+  {
+    hb_codepoint_t c = *unicode = *text++;
+    if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
+      *unicode = replacement;
+    return text;
+  }
+
+  static const TCodepoint *
+  prev (const TCodepoint *text,
+        const TCodepoint *start HB_UNUSED,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement)
+  {
+    hb_codepoint_t c = *unicode = *--text;
+    if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
+      *unicode = replacement;
+    return text;
+  }
+
+  static unsigned int
+  strlen (const TCodepoint *text)
+  {
+    unsigned int l = 0;
+    while (*text++) l++;
+    return l;
+  }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode HB_UNUSED)
+  {
+    return 1;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+          const codepoint_t *end HB_UNUSED,
+          hb_codepoint_t unicode)
+  {
+    if (validate && unlikely (unicode >= 0xD800u && (unicode <= 0xDFFFu || unicode > 0x10FFFFu)))
+      unicode = 0xFFFDu;
+    *text++ = unicode;
+    return text;
+  }
+};
+
+typedef hb_utf32_xe_t<uint32_t> hb_utf32_t;
+typedef hb_utf32_xe_t<uint32_t, false> hb_utf32_novalidate_t;
+
+
+struct hb_latin1_t
+{
+  typedef uint8_t codepoint_t;
+
+  static const codepoint_t *
+  next (const codepoint_t *text,
+        const codepoint_t *end HB_UNUSED,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement HB_UNUSED)
+  {
+    *unicode = *text++;
+    return text;
+  }
+
+  static const codepoint_t *
+  prev (const codepoint_t *text,
+        const codepoint_t *start HB_UNUSED,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement HB_UNUSED)
+  {
+    *unicode = *--text;
+    return text;
+  }
+
+  static unsigned int
+  strlen (const codepoint_t *text)
+  {
+    unsigned int l = 0;
+    while (*text++) l++;
+    return l;
+  }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode HB_UNUSED)
+  {
+    return 1;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+          const codepoint_t *end HB_UNUSED,
+          hb_codepoint_t unicode)
+  {
+    if (unlikely (unicode >= 0x0100u))
+      unicode = '?';
+    *text++ = unicode;
+    return text;
+  }
+};
+
+
+struct hb_ascii_t
+{
+  typedef uint8_t codepoint_t;
+
+  static const codepoint_t *
+  next (const codepoint_t *text,
+        const codepoint_t *end HB_UNUSED,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement HB_UNUSED)
+  {
+    *unicode = *text++;
+    if (*unicode >= 0x0080u)
+      *unicode = replacement;
+    return text;
+  }
+
+  static const codepoint_t *
+  prev (const codepoint_t *text,
+        const codepoint_t *start HB_UNUSED,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement)
+  {
+    *unicode = *--text;
+    if (*unicode >= 0x0080u)
+      *unicode = replacement;
+    return text;
+  }
+
+  static unsigned int
+  strlen (const codepoint_t *text)
+  {
+    unsigned int l = 0;
+    while (*text++) l++;
+    return l;
+  }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode HB_UNUSED)
+  {
+    return 1;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+          const codepoint_t *end HB_UNUSED,
+          hb_codepoint_t unicode)
+  {
+    if (unlikely (unicode >= 0x0080u))
+      unicode = '?';
+    *text++ = unicode;
+    return text;
+  }
+};
+
+#endif /* HB_UTF_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-vector.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,260 @@
+/*
+ * Copyright © 2017,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_VECTOR_HH
+#define HB_VECTOR_HH
+
+#include "hb.hh"
+#include "hb-array.hh"
+#include "hb-null.hh"
+
+
+template <typename Type>
+struct hb_vector_t
+{
+  typedef Type item_t;
+  static constexpr unsigned item_size = hb_static_size (Type);
+
+  HB_NO_COPY_ASSIGN_TEMPLATE (hb_vector_t, Type);
+  hb_vector_t ()  { init (); }
+  ~hb_vector_t () { fini (); }
+
+  unsigned int length;
+  private:
+  int allocated; /* == -1 means allocation failed. */
+  Type *arrayZ_;
+  public:
+
+  void init ()
+  {
+    allocated = length = 0;
+    arrayZ_ = nullptr;
+  }
+
+  void fini ()
+  {
+    if (arrayZ_)
+      free (arrayZ_);
+    init ();
+  }
+  void fini_deep ()
+  {
+    Type *array = arrayZ();
+    unsigned int count = length;
+    for (unsigned int i = 0; i < count; i++)
+      array[i].fini ();
+    fini ();
+  }
+
+  const Type * arrayZ () const { return arrayZ_; }
+        Type * arrayZ ()       { return arrayZ_; }
+
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= length))
+      return Crap (Type);
+    return arrayZ()[i];
+  }
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= length))
+      return Null(Type);
+    return arrayZ()[i];
+  }
+
+  explicit_operator bool () const { return length; }
+
+  hb_array_t<Type> as_array ()
+  { return hb_array (arrayZ(), length); }
+  hb_array_t<const Type> as_array () const
+  { return hb_array (arrayZ(), length); }
+
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
+  { return as_array ().sub_array (start_offset, count);}
+
+  hb_sorted_array_t<Type> as_sorted_array ()
+  { return hb_sorted_array (arrayZ(), length); }
+  hb_sorted_array_t<const Type> as_sorted_array () const
+  { return hb_sorted_array (arrayZ(), length); }
+
+  hb_array_t<const Type> sorted_sub_array (unsigned int start_offset, unsigned int count) const
+  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
+  hb_array_t<const Type> sorted_sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
+  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
+  hb_array_t<Type> sorted_sub_array (unsigned int start_offset, unsigned int count)
+  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
+  hb_array_t<Type> sorted_sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
+  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
+
+  template <typename T> explicit_operator T * () { return arrayZ(); }
+  template <typename T> explicit_operator const T * () const { return arrayZ(); }
+  operator hb_array_t<Type> ()             { return as_array (); }
+  operator hb_array_t<const Type> () const { return as_array (); }
+
+  Type * operator  + (unsigned int i) { return arrayZ() + i; }
+  const Type * operator  + (unsigned int i) const { return arrayZ() + i; }
+
+  Type *push ()
+  {
+    if (unlikely (!resize (length + 1)))
+      return &Crap(Type);
+    return &arrayZ()[length - 1];
+  }
+  Type *push (const Type& v)
+  {
+    Type *p = push ();
+    *p = v;
+    return p;
+  }
+
+  bool in_error () const { return allocated < 0; }
+
+  /* Allocate for size but don't adjust length. */
+  bool alloc (unsigned int size)
+  {
+    if (unlikely (allocated < 0))
+      return false;
+
+    if (likely (size <= (unsigned) allocated))
+      return true;
+
+    /* Reallocate */
+
+    unsigned int new_allocated = allocated;
+    while (size >= new_allocated)
+      new_allocated += (new_allocated >> 1) + 8;
+
+    Type *new_array = nullptr;
+    bool overflows =
+      (int) new_allocated < 0 ||
+      (new_allocated < (unsigned) allocated) ||
+      hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
+    if (likely (!overflows))
+      new_array = (Type *) realloc (arrayZ_, new_allocated * sizeof (Type));
+
+    if (unlikely (!new_array))
+    {
+      allocated = -1;
+      return false;
+    }
+
+    arrayZ_ = new_array;
+    allocated = new_allocated;
+
+    return true;
+  }
+
+  bool resize (int size_)
+  {
+    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
+    if (!alloc (size))
+      return false;
+
+    if (size > length)
+      memset (arrayZ() + length, 0, (size - length) * sizeof (*arrayZ()));
+
+    length = size;
+    return true;
+  }
+
+  void pop ()
+  {
+    if (!length) return;
+    length--;
+  }
+
+  void remove (unsigned int i)
+  {
+    if (unlikely (i >= length))
+      return;
+    Type *array = arrayZ();
+    memmove (static_cast<void *> (&array[i]),
+             static_cast<void *> (&array[i + 1]),
+             (length - i - 1) * sizeof (Type));
+    length--;
+  }
+
+  void shrink (int size_)
+  {
+    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
+     if (size < length)
+       length = size;
+  }
+
+  template <typename T>
+  Type *find (T v)
+  {
+    Type *array = arrayZ();
+    for (unsigned int i = 0; i < length; i++)
+      if (array[i] == v)
+        return &array[i];
+    return nullptr;
+  }
+  template <typename T>
+  const Type *find (T v) const
+  {
+    const Type *array = arrayZ();
+    for (unsigned int i = 0; i < length; i++)
+      if (array[i] == v)
+        return &array[i];
+    return nullptr;
+  }
+
+  void qsort (int (*cmp)(const void*, const void*))
+  { as_array ().qsort (cmp); }
+  void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
+  { as_array ().qsort (start, end); }
+
+  template <typename T>
+  Type *lsearch (const T &x, Type *not_found = nullptr)
+  { return as_array ().lsearch (x, not_found); }
+  template <typename T>
+  const Type *lsearch (const T &x, const Type *not_found = nullptr) const
+  { return as_array ().lsearch (x, not_found); }
+
+  template <typename T>
+  Type *bsearch (const T &x, Type *not_found = nullptr)
+  { return as_sorted_array ().bsearch (x, not_found); }
+  template <typename T>
+  const Type *bsearch (const T &x, const Type *not_found = nullptr) const
+  { return as_sorted_array ().bsearch (x, 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
+  { return as_sorted_array ().bfind (x, i, not_found, to_store); }
+};
+
+
+#endif /* HB_VECTOR_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-version.h	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-version.h	Fri Mar 01 16:59:19 2019 -0800
@@ -36,11 +36,11 @@
 HB_BEGIN_DECLS
 
 
-#define HB_VERSION_MAJOR 1
-#define HB_VERSION_MINOR 8
-#define HB_VERSION_MICRO 2
+#define HB_VERSION_MAJOR 2
+#define HB_VERSION_MINOR 3
+#define HB_VERSION_MICRO 1
 
-#define HB_VERSION_STRING "1.8.2"
+#define HB_VERSION_STRING "2.3.1"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
         ((major)*10000+(minor)*100+(micro) <= \
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-warning.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-warning.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -24,16 +24,14 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-atomic-private.hh"
-#include "hb-mutex-private.hh"
-
+#include "hb.hh"
 
 #if defined(HB_ATOMIC_INT_NIL)
 #error "Could not find any system to define atomic_int macros, library WILL NOT be thread-safe"
-#error "Check hb-atomic-private.hh for possible resolutions."
+#error "Check hb-atomic.hh for possible resolutions."
 #endif
 
 #if defined(HB_MUTEX_IMPL_NIL)
 #error "Could not find any system to define mutex macros, library WILL NOT be thread-safe"
-#error "Check hb-mutex-private.hh for possible resolutions."
+#error "Check hb-mutex.hh for possible resolutions."
 #endif
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb.h	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb.h	Fri Mar 01 16:59:19 2019 -0800
@@ -28,10 +28,6 @@
 #define HB_H
 #define HB_H_IN
 
-#ifndef HB_EXTERN
-#define HB_EXTERN extern
-#endif
-
 #include "hb-blob.h"
 #include "hb-buffer.h"
 #include "hb-common.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb.hh	Fri Mar 01 16:59:19 2019 -0800
@@ -0,0 +1,658 @@
+/*
+ * Copyright © 2007,2008,2009  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): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_HH
+#define HB_HH
+
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC
+#if defined(_MSC_VER)
+#pragma warning( disable: 4068 ) /* Unknown pragma */
+#endif
+#if defined(__GNUC__) || defined(__clang__)
+/* Rules:
+ *
+ * - All pragmas are declared GCC even if they are clang ones.  Otherwise GCC
+ *   nags, even though we instruct it to ignore -Wunknown-pragmas. ¯\_(ツ)_/¯
+ *
+ * - Within each category, keep sorted.
+ *
+ * - Warnings whose scope can be expanded in future compiler versions shall
+ *   be declared as "warning".  Otherwise, either ignored or error.
+ */
+
+/* Setup.  Don't sort order within this category. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
+#pragma GCC diagnostic warning "-Wall"
+#pragma GCC diagnostic warning "-Wextra"
+#endif
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
+#pragma GCC diagnostic ignored "-Wpragmas"
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#pragma GCC diagnostic ignored "-Wunknown-warning-option"
+#endif
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
+//#pragma GCC diagnostic warning "-Weverything"
+#endif
+
+/* Error.  Should never happen. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR
+#pragma GCC diagnostic error   "-Wc++11-narrowing"
+#pragma GCC diagnostic error   "-Wcast-align"
+#pragma GCC diagnostic error   "-Wcast-function-type"
+#pragma GCC diagnostic error   "-Wdelete-non-virtual-dtor"
+#pragma GCC diagnostic error   "-Wformat-security"
+#pragma GCC diagnostic error   "-Wimplicit-function-declaration"
+#pragma GCC diagnostic error   "-Winit-self"
+#pragma GCC diagnostic error   "-Wmissing-braces"
+#pragma GCC diagnostic error   "-Wmissing-declarations"
+#pragma GCC diagnostic error   "-Wmissing-prototypes"
+#pragma GCC diagnostic error   "-Wnested-externs"
+#pragma GCC diagnostic error   "-Wold-style-definition"
+#pragma GCC diagnostic error   "-Wpointer-arith"
+#pragma GCC diagnostic error   "-Wredundant-decls"
+#pragma GCC diagnostic error   "-Wreorder"
+#pragma GCC diagnostic error   "-Wsign-compare"
+#pragma GCC diagnostic error   "-Wstrict-prototypes"
+#pragma GCC diagnostic error   "-Wstring-conversion"
+#pragma GCC diagnostic error   "-Wswitch-enum"
+#pragma GCC diagnostic error   "-Wtautological-overlap-compare"
+#pragma GCC diagnostic error   "-Wunneeded-internal-declaration"
+#pragma GCC diagnostic error   "-Wunused"
+#pragma GCC diagnostic error   "-Wunused-local-typedefs"
+#pragma GCC diagnostic error   "-Wunused-value"
+#pragma GCC diagnostic error   "-Wunused-variable"
+#pragma GCC diagnostic error   "-Wvla"
+#pragma GCC diagnostic error   "-Wwrite-strings"
+#endif
+
+/* Warning.  To be investigated if happens. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
+#pragma GCC diagnostic warning "-Wbuiltin-macro-redefined"
+#pragma GCC diagnostic warning "-Wdisabled-optimization"
+#pragma GCC diagnostic warning "-Wformat=2"
+#pragma GCC diagnostic warning "-Wignored-pragma-optimize"
+#pragma GCC diagnostic warning "-Wlogical-op"
+#pragma GCC diagnostic warning "-Wmaybe-uninitialized"
+#pragma GCC diagnostic warning "-Wmissing-format-attribute"
+#pragma GCC diagnostic warning "-Wundef"
+#endif
+
+/* Ignored currently, but should be fixed at some point. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
+#pragma GCC diagnostic ignored "-Wconversion"                   // TODO fix
+#pragma GCC diagnostic ignored "-Wformat-signedness"            // TODO fix
+#pragma GCC diagnostic ignored "-Wshadow"                       // TODO fix
+#pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"    // TODO fix
+#pragma GCC diagnostic ignored "-Wunused-parameter"             // TODO fix
+#endif
+
+/* Ignored intentionally. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#pragma GCC diagnostic ignored "-Wformat-zero-length"
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#pragma GCC diagnostic ignored "-Wpacked" // Erratic impl in clang
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
+
+#endif
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Following added based on what AC_USE_SYSTEM_EXTENSIONS adds to
+ * config.h.in.  Copied here for the convenience of those embedding
+ * HarfBuzz and not using our build system.
+ */
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# define _ALL_SOURCE 1
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# define _TANDEM_SOURCE 1
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__ 1
+#endif
+
+#if defined (_MSC_VER) && defined (HB_DLL_EXPORT)
+#define HB_EXTERN __declspec (dllexport) extern
+#endif
+
+#include "hb.h"
+#define HB_H_IN
+#include "hb-ot.h"
+#define HB_OT_H_IN
+#include "hb-aat.h"
+#define HB_AAT_H_IN
+
+#include "hb-aat.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
+#include <intrin.h>
+#endif
+
+#define HB_PASTE1(a,b) a##b
+#define HB_PASTE(a,b) HB_PASTE1(a,b)
+
+
+/* Compile-time custom allocator support. */
+
+#if defined(hb_malloc_impl) \
+ && defined(hb_calloc_impl) \
+ && defined(hb_realloc_impl) \
+ && defined(hb_free_impl)
+extern "C" void* hb_malloc_impl(size_t size);
+extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
+extern "C" void* hb_realloc_impl(void *ptr, size_t size);
+extern "C" void  hb_free_impl(void *ptr);
+#define malloc hb_malloc_impl
+#define calloc hb_calloc_impl
+#define realloc hb_realloc_impl
+#define free hb_free_impl
+
+#if defined(hb_memalign_impl)
+extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size);
+#define posix_memalign hb_memalign_impl
+#else
+#undef HAVE_POSIX_MEMALIGN
+#endif
+
+#endif
+
+
+/*
+ * Compiler attributes
+ */
+
+#if __cplusplus < 201103L
+
+#ifndef nullptr
+#define nullptr NULL
+#endif
+
+#ifndef constexpr
+#define constexpr const
+#endif
+
+#ifndef static_assert
+#define static_assert(e, msg) \
+        HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
+#endif // static_assert
+
+#if defined(__GNUC__)
+#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
+#define thread_local __thread
+#endif
+#else
+#define thread_local
+#endif
+
+template <typename T>
+struct _hb_alignof
+{
+  struct s
+  {
+    char c;
+    T t;
+  };
+  static constexpr size_t value = offsetof (s, t);
+};
+#ifndef alignof
+#define alignof(x) (_hb_alignof<x>::value)
+#endif
+
+/* https://github.com/harfbuzz/harfbuzz/issues/1127 */
+#ifndef explicit_operator
+#define explicit_operator operator
+#endif
+
+#else /* __cplusplus >= 201103L */
+
+/* https://github.com/harfbuzz/harfbuzz/issues/1127 */
+#ifndef explicit_operator
+#define explicit_operator explicit operator
+#endif
+
+#endif /* __cplusplus < 201103L */
+
+
+#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
+#define likely(expr) (__builtin_expect (!!(expr), 1))
+#define unlikely(expr) (__builtin_expect (!!(expr), 0))
+#else
+#define likely(expr) (expr)
+#define unlikely(expr) (expr)
+#endif
+
+#if !defined(__GNUC__) && !defined(__clang__)
+#undef __attribute__
+#define __attribute__(x)
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#define HB_PURE_FUNC    __attribute__((pure))
+#define HB_CONST_FUNC   __attribute__((const))
+#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
+#else
+#define HB_PURE_FUNC
+#define HB_CONST_FUNC
+#define HB_PRINTF_FUNC(format_idx, arg_idx)
+#endif
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+#define HB_UNUSED       __attribute__((unused))
+#elif defined(_MSC_VER) /* https://github.com/harfbuzz/harfbuzz/issues/635 */
+#define HB_UNUSED __pragma(warning(suppress: 4100 4101))
+#else
+#define HB_UNUSED
+#endif
+
+#ifndef HB_INTERNAL
+# if !defined(HB_NO_VISIBILITY) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_MSC_VER) && !defined(__SUNPRO_CC)
+#  define HB_INTERNAL __attribute__((__visibility__("hidden")))
+# elif defined(__MINGW32__)
+   /* We use -export-symbols on mingw32, since it does not support visibility attributes. */
+#  define HB_INTERNAL
+# elif defined (_MSC_VER) && defined (HB_DLL_EXPORT)
+   /* We do not try to export internal symbols on Visual Studio */
+#  define HB_INTERNAL
+#else
+#  define HB_INTERNAL
+#  define HB_NO_VISIBILITY 1
+# endif
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#define HB_FUNC __PRETTY_FUNCTION__
+#elif defined(_MSC_VER)
+#define HB_FUNC __FUNCSIG__
+#else
+#define HB_FUNC __func__
+#endif
+
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5140)
+/* https://github.com/harfbuzz/harfbuzz/issues/630 */
+#define __restrict
+#endif
+
+/*
+ * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
+ * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
+ * cases that fall through without a break or return statement. HB_FALLTHROUGH
+ * is only needed on cases that have code:
+ *
+ * switch (foo) {
+ *   case 1: // These cases have no code. No fallthrough annotations are needed.
+ *   case 2:
+ *   case 3:
+ *     foo = 4; // This case has code, so a fallthrough annotation is needed:
+ *     HB_FALLTHROUGH;
+ *   default:
+ *     return foo;
+ * }
+ */
+#if defined(__clang__) && __cplusplus >= 201103L
+   /* clang's fallthrough annotations are only available starting in C++11. */
+#  define HB_FALLTHROUGH [[clang::fallthrough]]
+#elif defined(__GNUC__) && (__GNUC__ >= 7)
+   /* GNU fallthrough attribute is available from GCC7 */
+#  define HB_FALLTHROUGH __attribute__((fallthrough))
+#elif defined(_MSC_VER)
+   /*
+    * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
+    * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
+    */
+#  include <sal.h>
+#  define HB_FALLTHROUGH __fallthrough
+#else
+#  define HB_FALLTHROUGH /* FALLTHROUGH */
+#endif
+
+#if defined(__clang__)
+/* Disable certain sanitizer errors. */
+/* https://github.com/harfbuzz/harfbuzz/issues/1247 */
+#define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW __attribute__((no_sanitize("signed-integer-overflow")))
+#else
+#define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW
+#endif
+
+
+#ifdef _WIN32
+   /* We need Windows Vista for both Uniscribe backend and for
+    * MemoryBarrier.  We don't support compiling on Windows XP,
+    * though we run on it fine. */
+#  if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
+#    undef _WIN32_WINNT
+#  endif
+#  ifndef _WIN32_WINNT
+#    if !defined(WINAPI_FAMILY) || !(WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+#      define _WIN32_WINNT 0x0600
+#    endif
+#  endif
+#  ifndef WIN32_LEAN_AND_MEAN
+#    define WIN32_LEAN_AND_MEAN 1
+#  endif
+#  ifndef STRICT
+#    define STRICT 1
+#  endif
+
+#  if defined(_WIN32_WCE)
+     /* Some things not defined on Windows CE. */
+#    define vsnprintf _vsnprintf
+#    define getenv(Name) nullptr
+#    if _WIN32_WCE < 0x800
+#      define setlocale(Category, Locale) "C"
+static int errno = 0; /* Use something better? */
+#    endif
+#  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+#    define getenv(Name) nullptr
+#  endif
+#  if defined(_MSC_VER) && _MSC_VER < 1900
+#    define snprintf _snprintf
+#  endif
+#endif
+
+#if defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT)
+/* atexit() is only safe to be called from shared libraries on certain
+ * platforms.  Whitelist.
+ * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
+#  if defined(__linux) && defined(__GLIBC_PREREQ)
+#    if __GLIBC_PREREQ(2,3)
+/* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
+#      define HB_USE_ATEXIT 1
+#    endif
+#  elif defined(_MSC_VER) || defined(__MINGW32__)
+/* For MSVC:
+ * https://msdn.microsoft.com/en-us/library/tze57ck3.aspx
+ * https://msdn.microsoft.com/en-us/library/zk17ww08.aspx
+ * mingw32 headers say atexit is safe to use in shared libraries.
+ */
+#    define HB_USE_ATEXIT 1
+#  elif defined(__ANDROID__)
+/* This is available since Android NKD r8 or r8b:
+ * https://issuetracker.google.com/code/p/android/issues/detail?id=6455
+ */
+#    define HB_USE_ATEXIT 1
+#  elif defined(__APPLE__)
+/* For macOS and related platforms, the atexit man page indicates
+ * that it will be invoked when the library is unloaded, not only
+ * at application exit.
+ */
+#    define HB_USE_ATEXIT 1
+#  endif
+#endif
+#ifdef HB_NO_ATEXIT
+#  undef HB_USE_ATEXIT
+#endif
+#ifndef HB_USE_ATEXIT
+#  define HB_USE_ATEXIT 0
+#endif
+
+#define HB_STMT_START do
+#define HB_STMT_END   while (0)
+
+/* Static-assert as expression. */
+template <unsigned int cond> class hb_assert_constant_t;
+template <> class hb_assert_constant_t<1> {};
+#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
+
+/* Lets assert int types.  Saves trouble down the road. */
+static_assert ((sizeof (int8_t) == 1), "");
+static_assert ((sizeof (uint8_t) == 1), "");
+static_assert ((sizeof (int16_t) == 2), "");
+static_assert ((sizeof (uint16_t) == 2), "");
+static_assert ((sizeof (int32_t) == 4), "");
+static_assert ((sizeof (uint32_t) == 4), "");
+static_assert ((sizeof (int64_t) == 8), "");
+static_assert ((sizeof (uint64_t) == 8), "");
+static_assert ((sizeof (hb_codepoint_t) == 4), "");
+static_assert ((sizeof (hb_position_t) == 4), "");
+static_assert ((sizeof (hb_mask_t) == 4), "");
+static_assert ((sizeof (hb_var_int_t) == 4), "");
+
+
+#if __cplusplus >= 201103L
+
+/* We only enable these with C++11 or later, since earlier language
+ * does not allow structs with constructors in unions, and we need
+ * those. */
+
+#define HB_NO_COPY_ASSIGN(TypeName) \
+  TypeName(const TypeName&); \
+  void operator=(const TypeName&)
+#define HB_NO_COPY_ASSIGN_TEMPLATE(TypeName, T) \
+  TypeName(const TypeName<T>&); \
+  void operator=(const TypeName<T>&)
+#define HB_NO_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) \
+  TypeName(const TypeName<T1, T2>&); \
+  void operator=(const TypeName<T1, T2>&)
+#define HB_NO_CREATE_COPY_ASSIGN(TypeName) \
+  TypeName(); \
+  TypeName(const TypeName&); \
+  void operator=(const TypeName&)
+#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE(TypeName, T) \
+  TypeName(); \
+  TypeName(const TypeName<T>&); \
+  void operator=(const TypeName<T>&)
+#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) \
+  TypeName(); \
+  TypeName(const TypeName<T1, T2>&); \
+  void operator=(const TypeName<T1, T2>&)
+
+#else /* __cpluspplus >= 201103L */
+
+#define HB_NO_COPY_ASSIGN(TypeName) static_assert (true, "")
+#define HB_NO_COPY_ASSIGN_TEMPLATE(TypeName, T) static_assert (true, "")
+#define HB_NO_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) static_assert (true, "")
+#define HB_NO_CREATE_COPY_ASSIGN(TypeName) static_assert (true, "")
+#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE(TypeName, T) static_assert (true, "")
+#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) static_assert (true, "")
+
+#endif /* __cpluspplus >= 201103L */
+
+
+/*
+ * Compiler-assisted vectorization parameters.
+ */
+
+/*
+ * Disable vectorization for now.  To correctly use them, we should
+ * use posix_memalign() to allocate in hb_vector_t.  Otherwise, can
+ * cause misaligned access.
+ *
+ * https://bugs.chromium.org/p/chromium/issues/detail?id=860184
+ */
+#if !defined(HB_VECTOR_SIZE)
+#  define HB_VECTOR_SIZE 0
+#endif
+
+/* The `vector_size' attribute was introduced in gcc 3.1. */
+#if !defined(HB_VECTOR_SIZE)
+#  if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
+#    define HB_VECTOR_SIZE 128
+#  else
+#    define HB_VECTOR_SIZE 0
+#  endif
+#endif
+static_assert (0 == (HB_VECTOR_SIZE & (HB_VECTOR_SIZE - 1)), "HB_VECTOR_SIZE is not power of 2.");
+static_assert (0 == (HB_VECTOR_SIZE % 64), "HB_VECTOR_SIZE is not multiple of 64.");
+#if HB_VECTOR_SIZE
+typedef uint64_t hb_vector_size_impl_t __attribute__((vector_size (HB_VECTOR_SIZE / 8)));
+#else
+typedef uint64_t hb_vector_size_impl_t;
+#endif
+
+
+/* HB_NDEBUG disables some sanity checks that are very safe to disable and
+ * should be disabled in production systems.  If NDEBUG is defined, enable
+ * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
+ * light-weight) to be enabled, then HB_DEBUG can be defined to disable
+ * the costlier checks. */
+#ifdef NDEBUG
+#define HB_NDEBUG 1
+#endif
+
+
+/* Flags */
+
+/* Enable bitwise ops on enums marked as flags_t */
+/* To my surprise, looks like the function resolver is happy to silently cast
+ * one enum to another...  So this doesn't provide the type-checking that I
+ * originally had in mind... :(.
+ *
+ * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
+ */
+#ifdef _MSC_VER
+# pragma warning(disable:4200)
+# pragma warning(disable:4800)
+#endif
+#define HB_MARK_AS_FLAG_T(T) \
+        extern "C++" { \
+          static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
+          static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
+          static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
+          static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
+          static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
+          static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
+          static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
+        } \
+        static_assert (true, "")
+
+/* Useful for set-operations on small enums.
+ * For example, for testing "x ∈ {x1, x2, x3}" use:
+ * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
+ */
+#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x)))
+#define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0)
+#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
+#define FLAG64(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x)))
+#define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0)
+
+
+/* Size signifying variable-sized array */
+#define VAR 1
+
+
+/* fallback for round() */
+static inline double
+_hb_round (double x)
+{
+  if (x >= 0)
+    return floor (x + 0.5);
+  else
+    return ceil (x - 0.5);
+}
+#if !defined (HAVE_ROUND) && !defined (HAVE_DECL_ROUND)
+#define round(x) _hb_round(x)
+#endif
+
+
+/* fallback for posix_memalign() */
+static inline int
+_hb_memalign(void **memptr, size_t alignment, size_t size)
+{
+  if (unlikely (0 != (alignment & (alignment - 1)) ||
+                !alignment ||
+                0 != (alignment & (sizeof (void *) - 1))))
+    return EINVAL;
+
+  char *p = (char *) malloc (size + alignment - 1);
+  if (unlikely (!p))
+    return ENOMEM;
+
+  size_t off = (size_t) p & (alignment - 1);
+  if (off)
+    p += alignment - off;
+
+  *memptr = (void *) p;
+
+  return 0;
+}
+#if !defined(posix_memalign) && !defined(HAVE_POSIX_MEMALIGN)
+#define posix_memalign _hb_memalign
+#endif
+
+
+/*
+ * For lack of a better place, put Zawgyi script hack here.
+ * https://github.com/harfbuzz/harfbuzz/issues/1162
+ */
+
+#define HB_SCRIPT_MYANMAR_ZAWGYI        ((hb_script_t) HB_TAG ('Q','a','a','g'))
+
+
+/* Some really basic things everyone wants. */
+template <typename T> struct hb_remove_const { typedef T value; };
+template <typename T> struct hb_remove_const<const T> { typedef T value; };
+#define hb_remove_const(T) hb_remove_const<T>::value
+template <typename T> struct hb_remove_reference { typedef T value; };
+template <typename T> struct hb_remove_reference<T &> { typedef T value; };
+#define hb_remove_reference(T) hb_remove_reference<T>::value
+template <typename T> struct hb_remove_pointer { typedef T value; };
+template <typename T> struct hb_remove_pointer<T *> { typedef T value; };
+#define hb_remove_pointer(T) hb_remove_pointer<T>::value
+
+
+/* Headers we include for everyone.  Keep topologically sorted by dependency.
+ * They express dependency amongst themselves, but no other file should include
+ * them directly.*/
+#include "hb-atomic.hh"
+#include "hb-mutex.hh"
+#include "hb-null.hh"
+#include "hb-dsalgs.hh" // Requires: hb-null
+#include "hb-iter.hh"   // Requires: hb-null
+#include "hb-debug.hh"  // Requires: hb-atomic hb-dsalgs
+#include "hb-array.hh"  // Requires: hb-dsalgs hb-iter hb-null
+#include "hb-vector.hh" // Requires: hb-array hb-null
+#include "hb-object.hh" // Requires: hb-atomic hb-mutex hb-vector
+
+#endif /* HB_HH */
--- a/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc	Wed Feb 27 18:46:55 2019 -0800
+++ b/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc	Fri Mar 01 16:59:19 2019 -0800
@@ -36,8 +36,32 @@
 #define HB_UNUSED
 #endif
 
+
 static hb_bool_t
-hb_jdk_get_glyph (hb_font_t *font HB_UNUSED,
+hb_jdk_get_nominal_glyph (hb_font_t *font HB_UNUSED,
+		          void *font_data,
+		          hb_codepoint_t unicode,
+		          hb_codepoint_t *glyph,
+		          void *user_data HB_UNUSED)
+{
+
+    JDKFontInfo *jdkFontInfo = (JDKFontInfo*)font_data;
+    JNIEnv* env = jdkFontInfo->env;
+    jobject font2D = jdkFontInfo->font2D;
+    *glyph = (hb_codepoint_t)env->CallIntMethod(
+              font2D, sunFontIDs.f2dCharToGlyphMID, unicode);
+    if (env->ExceptionOccurred())
+    {
+        env->ExceptionClear();
+    }
+    if ((int)*glyph < 0) {
+        *glyph = 0;
+    }
+    return (*glyph != 0);
+}
+
+static hb_bool_t
+hb_jdk_get_variation_glyph (hb_font_t *font HB_UNUSED,
 		 void *font_data,
 		 hb_codepoint_t unicode,
 		 hb_codepoint_t variation_selector,
@@ -48,14 +72,9 @@
     JDKFontInfo *jdkFontInfo = (JDKFontInfo*)font_data;
     JNIEnv* env = jdkFontInfo->env;
     jobject font2D = jdkFontInfo->font2D;
-    if (variation_selector == 0) {
-        *glyph = (hb_codepoint_t)env->CallIntMethod(
-                     font2D, sunFontIDs.f2dCharToGlyphMID, unicode);
-    } else {
-        *glyph = (hb_codepoint_t)env->CallIntMethod(
-                     font2D, sunFontIDs.f2dCharToVariationGlyphMID, 
-                     unicode, variation_selector);
-    }
+    *glyph = (hb_codepoint_t)env->CallIntMethod(
+              font2D, sunFontIDs.f2dCharToVariationGlyphMID, 
+              unicode, variation_selector);
     if (env->ExceptionOccurred())
     {
         env->ExceptionClear();
@@ -251,7 +270,8 @@
   if (!jdk_ffuncs) {
       ff = hb_font_funcs_create();
 
-      hb_font_funcs_set_glyph_func(ff, hb_jdk_get_glyph, NULL, NULL);
+      hb_font_funcs_set_nominal_glyph_func(ff, hb_jdk_get_nominal_glyph, NULL, NULL);
+      hb_font_funcs_set_variation_glyph_func(ff, hb_jdk_get_variation_glyph, NULL, NULL);
       hb_font_funcs_set_glyph_h_advance_func(ff,
                     hb_jdk_get_glyph_h_advance, NULL, NULL);
       hb_font_funcs_set_glyph_v_advance_func(ff,