texlive[52560] Build/source/libs: harfbuzz-2.6.3

commits+kakuto at tug.org commits+kakuto at tug.org
Tue Oct 29 00:44:54 CET 2019


Revision: 52560
          http://tug.org/svn/texlive?view=revision&revision=52560
Author:   kakuto
Date:     2019-10-29 00:44:53 +0100 (Tue, 29 Oct 2019)
Log Message:
-----------
harfbuzz-2.6.3

Modified Paths:
--------------
    trunk/Build/source/libs/README
    trunk/Build/source/libs/harfbuzz/ChangeLog
    trunk/Build/source/libs/harfbuzz/Makefile.am
    trunk/Build/source/libs/harfbuzz/Makefile.in
    trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog
    trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes
    trunk/Build/source/libs/harfbuzz/configure
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/README
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/TESTING.md
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-mutex.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-sbix-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-kern-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic-fallback.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use-table.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.h
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc
    trunk/Build/source/libs/harfbuzz/version.ac

Added Paths:
-----------
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh

Removed Paths:
-------------
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-warning.cc

Modified: trunk/Build/source/libs/README
===================================================================
--- trunk/Build/source/libs/README	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/README	2019-10-28 23:44:53 UTC (rev 52560)
@@ -25,7 +25,7 @@
   http://sourceforge.net/projects/silgraphite/files/graphite2/
   (requires C++11)
 
-harfbuzz 2.6.2 - checked 01oct19
+harfbuzz 2.6.3 - checked 29oct19
   http://www.freedesktop.org/software/harfbuzz/release/
 
 icu 63.1 - checked 8jan19

Modified: trunk/Build/source/libs/harfbuzz/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/ChangeLog	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/ChangeLog	2019-10-28 23:44:53 UTC (rev 52560)
@@ -1,3 +1,8 @@
+2019-10-29  Akira Kakuto  <kakuto at w32tex.org>
+
+	Import harfbuzz-2.6.3.
+	* Makefile.am, version.ac: Adjusted.
+
 2019-10-01  Akira Kakuto  <kakuto at w32tex.org>
 
 	Import harfbuzz-2.6.2.

Modified: trunk/Build/source/libs/harfbuzz/Makefile.am
===================================================================
--- trunk/Build/source/libs/harfbuzz/Makefile.am	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/Makefile.am	2019-10-28 23:44:53 UTC (rev 52560)
@@ -129,7 +129,6 @@
 	@HARFBUZZ_TREE@/src/hb-unicode-emoji-table.hh \
 	@HARFBUZZ_TREE@/src/hb-vector.hh \
 	@HARFBUZZ_TREE@/src/hb-utf.hh \
-	@HARFBUZZ_TREE@/src/hb-warning.cc \
 	@HARFBUZZ_TREE@/src/hb-buffer-deserialize-json.hh \
 	@HARFBUZZ_TREE@/src/hb-buffer-deserialize-text.hh \
 	@HARFBUZZ_TREE@/src/hb-fallback-shape.cc \
@@ -208,6 +207,7 @@
 	@HARFBUZZ_TREE@/src/hb-ot-var.cc \
 	@HARFBUZZ_TREE@/src/hb-ot-var-avar-table.hh \
 	@HARFBUZZ_TREE@/src/hb-ot-var-fvar-table.hh \
+	@HARFBUZZ_TREE@/src/hb-ot-var-gvar-table.hh \
 	@HARFBUZZ_TREE@/src/hb-ot-var-hvar-table.hh \
 	@HARFBUZZ_TREE@/src/hb-ot-var-mvar-table.hh \
 	@HARFBUZZ_TREE@/src/hb-ot-vorg-table.hh \

Modified: trunk/Build/source/libs/harfbuzz/Makefile.in
===================================================================
--- trunk/Build/source/libs/harfbuzz/Makefile.in	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/Makefile.in	2019-10-28 23:44:53 UTC (rev 52560)
@@ -142,7 +142,6 @@
 	@HARFBUZZ_TREE@/src/hb-subset-cff2.$(OBJEXT) \
 	@HARFBUZZ_TREE@/src/hb-ucd.$(OBJEXT) \
 	@HARFBUZZ_TREE@/src/hb-unicode.$(OBJEXT) \
-	@HARFBUZZ_TREE@/src/hb-warning.$(OBJEXT) \
 	@HARFBUZZ_TREE@/src/hb-fallback-shape.$(OBJEXT) \
 	@HARFBUZZ_TREE@/src/hb-aat-layout.$(OBJEXT) \
 	@HARFBUZZ_TREE@/src/hb-aat-map.$(OBJEXT) \
@@ -243,8 +242,7 @@
 	@HARFBUZZ_TREE@/src/$(DEPDIR)/hb-subset-cff1.Po \
 	@HARFBUZZ_TREE@/src/$(DEPDIR)/hb-subset-cff2.Po \
 	@HARFBUZZ_TREE@/src/$(DEPDIR)/hb-ucd.Po \
-	@HARFBUZZ_TREE@/src/$(DEPDIR)/hb-unicode.Po \
-	@HARFBUZZ_TREE@/src/$(DEPDIR)/hb-warning.Po
+	@HARFBUZZ_TREE@/src/$(DEPDIR)/hb-unicode.Po
 am__mv = mv -f
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
@@ -798,7 +796,6 @@
 	@HARFBUZZ_TREE@/src/hb-unicode.cc \
 	@HARFBUZZ_TREE@/src/hb-unicode-emoji-table.hh \
 	@HARFBUZZ_TREE@/src/hb-vector.hh @HARFBUZZ_TREE@/src/hb-utf.hh \
-	@HARFBUZZ_TREE@/src/hb-warning.cc \
 	@HARFBUZZ_TREE@/src/hb-buffer-deserialize-json.hh \
 	@HARFBUZZ_TREE@/src/hb-buffer-deserialize-text.hh \
 	@HARFBUZZ_TREE@/src/hb-fallback-shape.cc \
@@ -874,6 +871,7 @@
 	@HARFBUZZ_TREE@/src/hb-ot-var.cc \
 	@HARFBUZZ_TREE@/src/hb-ot-var-avar-table.hh \
 	@HARFBUZZ_TREE@/src/hb-ot-var-fvar-table.hh \
+	@HARFBUZZ_TREE@/src/hb-ot-var-gvar-table.hh \
 	@HARFBUZZ_TREE@/src/hb-ot-var-hvar-table.hh \
 	@HARFBUZZ_TREE@/src/hb-ot-var-mvar-table.hh \
 	@HARFBUZZ_TREE@/src/hb-ot-vorg-table.hh \
@@ -1036,9 +1034,6 @@
 @HARFBUZZ_TREE@/src/hb-unicode.$(OBJEXT):  \
 	@HARFBUZZ_TREE@/src/$(am__dirstamp) \
 	@HARFBUZZ_TREE@/src/$(DEPDIR)/$(am__dirstamp)
- at HARFBUZZ_TREE@/src/hb-warning.$(OBJEXT):  \
-	@HARFBUZZ_TREE@/src/$(am__dirstamp) \
-	@HARFBUZZ_TREE@/src/$(DEPDIR)/$(am__dirstamp)
 @HARFBUZZ_TREE@/src/hb-fallback-shape.$(OBJEXT):  \
 	@HARFBUZZ_TREE@/src/$(am__dirstamp) \
 	@HARFBUZZ_TREE@/src/$(DEPDIR)/$(am__dirstamp)
@@ -1189,7 +1184,6 @@
 @AMDEP_TRUE@@am__include@ @am__quote@@HARFBUZZ_TREE@/src/$(DEPDIR)/hb-subset-cff2.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@@HARFBUZZ_TREE@/src/$(DEPDIR)/hb-ucd.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@@HARFBUZZ_TREE@/src/$(DEPDIR)/hb-unicode.Po at am__quote@ # am--include-marker
- at AMDEP_TRUE@@am__include@ @am__quote@@HARFBUZZ_TREE@/src/$(DEPDIR)/hb-warning.Po at am__quote@ # am--include-marker
 
 $(am__depfiles_remade):
 	@$(MKDIR_P) $(@D)
@@ -1833,7 +1827,6 @@
 	-rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-subset-cff2.Po
 	-rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-ucd.Po
 	-rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-unicode.Po
-	-rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-warning.Po
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-hdr distclean-tags
@@ -1933,7 +1926,6 @@
 	-rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-subset-cff2.Po
 	-rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-ucd.Po
 	-rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-unicode.Po
-	-rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-warning.Po
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 

Modified: trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog	2019-10-28 23:44:53 UTC (rev 52560)
@@ -1,3 +1,8 @@
+2019-10-29  Akira Kakuto  <kakuto at w32tex.org>
+
+	Imported harfbuzz-2.6.3 source tree from:
+	  http://www.freedesktop.org/software/harfbuzz/release/
+
 2019-10-01  Akira Kakuto  <kakuto at w32tex.org>
 
 	Imported harfbuzz-2.6.2 source tree from:

Modified: trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes
===================================================================
--- trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes	2019-10-28 23:44:53 UTC (rev 52560)
@@ -1,4 +1,4 @@
-Changes applied to the harfbuzz-2.6.2/ tree as obtained from:
+Changes applied to the harfbuzz-2.6.3/ tree as obtained from:
 	http://www.freedesktop.org/software/harfbuzz/release/
 
 Removed:

Modified: trunk/Build/source/libs/harfbuzz/configure
===================================================================
--- trunk/Build/source/libs/harfbuzz/configure	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/configure	2019-10-28 23:44:53 UTC (rev 52560)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for harfbuzz (TeX Live) 2.6.2.
+# Generated by GNU Autoconf 2.69 for harfbuzz (TeX Live) 2.6.3.
 #
 # Report bugs to <tex-k at tug.org>.
 #
@@ -580,8 +580,8 @@
 # Identity of this package.
 PACKAGE_NAME='harfbuzz (TeX Live)'
 PACKAGE_TARNAME='harfbuzz--tex-live-'
-PACKAGE_VERSION='2.6.2'
-PACKAGE_STRING='harfbuzz (TeX Live) 2.6.2'
+PACKAGE_VERSION='2.6.3'
+PACKAGE_STRING='harfbuzz (TeX Live) 2.6.3'
 PACKAGE_BUGREPORT='tex-k at tug.org'
 PACKAGE_URL=''
 
@@ -1311,7 +1311,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures harfbuzz (TeX Live) 2.6.2 to adapt to many kinds of systems.
+\`configure' configures harfbuzz (TeX Live) 2.6.3 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1382,7 +1382,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of harfbuzz (TeX Live) 2.6.2:";;
+     short | recursive ) echo "Configuration of harfbuzz (TeX Live) 2.6.3:";;
    esac
   cat <<\_ACEOF
 
@@ -1487,7 +1487,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-harfbuzz (TeX Live) configure 2.6.2
+harfbuzz (TeX Live) configure 2.6.3
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2123,7 +2123,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by harfbuzz (TeX Live) $as_me 2.6.2, which was
+It was created by harfbuzz (TeX Live) $as_me 2.6.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4047,7 +4047,7 @@
 
 # Define the identity of the package.
  PACKAGE='harfbuzz--tex-live-'
- VERSION='2.6.2'
+ VERSION='2.6.3'
 
 
 # Some tools Automake needs.
@@ -4241,8 +4241,8 @@
 
 HB_VERSION_MAJOR=2
 HB_VERSION_MINOR=6
-HB_VERSION_MICRO=2
-HB_VERSION=2.6.2
+HB_VERSION_MICRO=3
+HB_VERSION=2.6.3
 
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
@@ -7919,7 +7919,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by harfbuzz (TeX Live) $as_me 2.6.2, which was
+This file was extended by harfbuzz (TeX Live) $as_me 2.6.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -7985,7 +7985,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-harfbuzz (TeX Live) config.status 2.6.2
+harfbuzz (TeX Live) config.status 2.6.3
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog	2019-10-28 23:44:53 UTC (rev 52560)
@@ -1,3 +1,831 @@
+commit ce11df1b5b8e49712bef249de19bc4768f3a691c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Oct 28 14:45:31 2019 -0700
+
+    2.6.3
+
+ NEWS             | 8 ++++++++
+ configure.ac     | 2 +-
+ src/hb-font.cc   | 2 +-
+ src/hb-version.h | 4 ++--
+ 4 files changed, 12 insertions(+), 4 deletions(-)
+
+commit 5a59de2b983ed7a1c639ea3e4d23c341134cd6d5
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Oct 28 14:02:47 2019 -0700
+
+    Actually add +hb_font_get_nominal_glyphs()
+    
+    New API:
+    +hb_font_get_nominal_glyphs()
+
+ src/hb-font.cc | 23 +++++++++++++++++++++++
+ src/hb-font.h  |  8 ++++++++
+ 2 files changed, 31 insertions(+)
+
+commit 03028a5fe512978a8f8e2396001cf8e425b44f72
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Oct 28 13:46:56 2019 -0700
+
+    Revert "Don't include codepoint 0 in the results of collect_unicodes."
+    
+    This reverts commit 14ad96ffbf77c33d8d33d2686d17c2375381989e.
+    
+    This was wrong.  My bad!
+    
+    https://github.com/harfbuzz/harfbuzz/issues/2031
+
+ src/hb-ot-cmap-table.hh | 8 +-------
+ 1 file changed, 1 insertion(+), 7 deletions(-)
+
+commit 2714dc31b8d0ffe3c043935dd7619be0dd7b7635
+Merge: aca63902 14ad96ff
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Oct 28 13:01:34 2019 -0700
+
+    Merge pull request #2032 from googlefonts/collect_unicodes
+    
+    Don't include codepoint 0 in the results of collect_unicodes.
+
+commit 14ad96ffbf77c33d8d33d2686d17c2375381989e
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Oct 28 12:56:04 2019 -0700
+
+    Don't include codepoint 0 in the results of collect_unicodes.
+    It is always assumed to be the notdef glyph.
+
+ src/hb-ot-cmap-table.hh | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+commit aca63902814748b36bf6939421cfa95eed3a1ca7
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Tue Oct 22 00:06:46 2019 +0330
+
+    [gpos] Don't move pointer when match_glyph_data is not set
+
+ src/hb-ot-layout-gsubgpos.hh | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+commit defe9b6da018bc85750c999454c51fde0cadb9b2
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Fri Oct 25 10:07:26 2019 -0700
+
+    crash fix : Heap-buffer-overflow READ 2
+    https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=18513
+
+ src/hb-ot-layout-gpos-table.hh                            |  12 ++++++------
+ ...z-testcase-minimized-hb-subset-fuzzer-5677906231033856 | Bin 0 -> 938 bytes
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+commit b2fcca6e14afc8085cc1c2491b2d7c780dad1450
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Oct 24 15:15:26 2019 -0700
+
+     fuzzer crash fix
+     https://oss-fuzz.com/testcase-detail/5643107869917184
+
+ src/hb-ot-layout-gsubgpos.hh                             |  11 +++++++----
+ ...-testcase-minimized-hb-subset-fuzzer-5643107869917184 | Bin 0 -> 3232 bytes
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+commit 9815ca0338b47c6ea4e82f2fbd39d70e3456aca1
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Thu Oct 24 21:05:38 2019 +0330
+
+    [ci] Use custom subset fuzzer timeout for failing sanitizer bots
+
+ .circleci/config.yml                    | 8 ++++----
+ test/fuzzing/run-shape-fuzzer-tests.py  | 3 ++-
+ test/fuzzing/run-subset-fuzzer-tests.py | 3 ++-
+ 3 files changed, 8 insertions(+), 6 deletions(-)
+
+commit b03b62cb304279195569180061cde745e0c9880a
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Wed Oct 23 12:18:21 2019 +0330
+
+    [ci] Add HB_NO_MT on non HB_TINY no-build-system builds
+
+ .circleci/config.yml | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 5e489670e15329f5eced16e5a76145c6149a265f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Oct 22 15:03:47 2019 -0700
+
+    Remove hb-warning.cc
+    
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/2005
+
+ src/Makefile.sources |  1 -
+ src/harfbuzz.cc      |  1 -
+ src/hb-atomic.hh     | 16 +++++-----------
+ src/hb-mutex.hh      | 25 ++++++-------------------
+ src/hb-warning.cc    | 37 -------------------------------------
+ 5 files changed, 11 insertions(+), 69 deletions(-)
+
+commit 05bcdb39d8648c49f7984c404aee096f2ad1d655
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Oct 21 16:10:06 2019 -0700
+
+    Add a specialization of array_t:hash for hb_bytes_t and hb_ubytes_t.
+
+ src/hb-array.hh              | 34 ++++++++++++++++++++++++----------
+ src/hb-ot-layout-gsubgpos.hh |  2 --
+ 2 files changed, 24 insertions(+), 12 deletions(-)
+
+commit 95ab110cd9a6083a854e538211618b2733aba643
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Oct 21 13:15:46 2019 -0700
+
+    Optimize intersects_array to fix fuzzer timeout.
+
+ src/hb-ot-layout-gsubgpos.hh                           |  10 +++++-----
+ ...estcase-minimized-hb-subset-fuzzer-5763024094232576 | Bin 0 -> 125681 bytes
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+commit be5cdcdfa21a2d956fc8c445452a78e77ede95fb
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Oct 22 11:55:04 2019 -0700
+
+    Store the hash value of a key in item_t in hb_map to reduce the number of hash computations.
+
+ src/hb-map.hh | 70 ++++++++++++++++++++++++++++++++++-------------------------
+ 1 file changed, 40 insertions(+), 30 deletions(-)
+
+commit b33a0d628e5e76992fdd02fd4178906137e6153c
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon Oct 21 13:24:52 2019 -0700
+
+    fuzzer crash fix: Null-dereference WRITE
+    https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=18363
+
+ src/hb-ot-layout-common.hh                                |   4 +++-
+ ...z-testcase-minimized-hb-subset-fuzzer-5659903036751872 | Bin 0 -> 781 bytes
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+commit cf414e361a99decd9c1710f1012236bffd067878
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Sep 27 09:55:17 2019 -0700
+
+    Added profiling instructions to TESTING.md
+
+ TESTING.md | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+commit 1f0a9d9be979de01527c05f4dbe6fbc62799597c
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue Sep 17 11:10:08 2019 -0700
+
+    [subset] GPOS Lookup Type 2: PairPos
+
+ src/hb-ot-layout-gpos-table.hh                     | 131 ++++++++++++++++++++-
+ test/subset/data/Makefile.am                       |   1 +
+ test/subset/data/Makefile.sources                  |   1 +
+ ...s2_1_font7.keep-layout-retain-gids.21,23,25.otf | Bin 0 -> 1764 bytes
+ ...gpos2_1_font7.keep-layout-retain-gids.21,23.otf | Bin 0 -> 1632 bytes
+ ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3688 bytes
+ .../gpos2_1_font7.keep-layout.21,23,25.otf         | Bin 0 -> 1428 bytes
+ .../gpos2_1_font7.keep-layout.21,23.otf            | Bin 0 -> 1308 bytes
+ ...s2_1_font7.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3688 bytes
+ ...s2_2_font5.keep-layout-retain-gids.21,23,25.otf | Bin 0 -> 1776 bytes
+ ...gpos2_2_font5.keep-layout-retain-gids.21,23.otf | Bin 0 -> 1644 bytes
+ ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3684 bytes
+ .../gpos2_2_font5.keep-layout.21,23,25.otf         | Bin 0 -> 1440 bytes
+ .../gpos2_2_font5.keep-layout.21,23.otf            | Bin 0 -> 1320 bytes
+ ...s2_2_font5.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3684 bytes
+ test/subset/data/fonts/gpos2_1_font7.otf           | Bin 0 -> 4584 bytes
+ test/subset/data/fonts/gpos2_2_font5.otf           | Bin 0 -> 4580 bytes
+ test/subset/data/tests/layout.gpos2.tests          |  12 ++
+ 18 files changed, 139 insertions(+), 6 deletions(-)
+
+commit e766783152b91fb20baf0c657586628fd7959b1b
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Mon Oct 21 22:17:06 2019 +0330
+
+    [fuzz] Add https://crbug.com/oss-fuzz/17898 testcase
+
+ ...sterfuzz-testcase-hb-subset-fuzzer-5717414645334016 | Bin 0 -> 310324 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit b66094ada0ae7e69d5d08ee8423554629eabccaf
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon Sep 30 16:19:18 2019 -0700
+
+    [subset] GSUB Lookup Type 6: ChainContextSubst
+
+ src/hb-ot-layout-common.hh                         | 260 ++++++++++++++-------
+ src/hb-ot-layout-gsubgpos.hh                       | 218 ++++++++++++++++-
+ test/subset/data/Makefile.am                       |   1 +
+ test/subset/data/Makefile.sources                  |   1 +
+ ...ules_f1.keep-layout-retain-gids.30,31,32,33.otf | Bin 0 -> 2380 bytes
+ ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3748 bytes
+ ...ultiple_subrules_f1.keep-layout.30,31,32,33.otf | Bin 0 -> 1916 bytes
+ ...ubrules_f1.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3748 bytes
+ ...ules_f1.keep-layout-retain-gids.30,31,32,33.otf | Bin 0 -> 2408 bytes
+ ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3780 bytes
+ ...ultiple_subrules_f1.keep-layout.30,31,32,33.otf | Bin 0 -> 1944 bytes
+ ...ubrules_f1.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3780 bytes
+ ...mple_f2.keep-layout-retain-gids.30,31,32,33.otf | Bin 0 -> 2368 bytes
+ ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3716 bytes
+ ...chaining3_simple_f2.keep-layout.30,31,32,33.otf | Bin 0 -> 1904 bytes
+ ..._simple_f2.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3716 bytes
+ .../fonts/gsub_chaining1_multiple_subrules_f1.otf  | Bin 0 -> 4700 bytes
+ .../fonts/gsub_chaining2_multiple_subrules_f1.otf  | Bin 0 -> 4780 bytes
+ .../subset/data/fonts/gsub_chaining3_simple_f2.otf | Bin 0 -> 4668 bytes
+ test/subset/data/tests/layout.gsub6.tests          |  12 +
+ 20 files changed, 405 insertions(+), 87 deletions(-)
+
+commit eff91bbb4b1e6f4cc8401b1915d5ddad64e053bb
+Author: Garret Rieger <grieger at google.com>
+Date:   Wed Oct 16 16:58:57 2019 -0700
+
+    Add missing pop() for the failure case of script subsetting.
+
+ src/hb-ot-layout-common.hh | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit eab191fd9c851cb7881163ddd5e11a2ebc58cef4
+Author: Garret Rieger <grieger at google.com>
+Date:   Wed Oct 2 14:28:53 2019 -0700
+
+    Rewrite hash and == function for hb_array_t as a plain loop.
+    
+    Profling showed that the current implementation were accounting for nearly all processing time in some cases. These implementations look to be about 10x faster.
+
+ src/hb-array.hh | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+commit 831daf4c76aed87d229b1edfb59a0a37caa8e581
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Oct 1 17:46:27 2019 -0700
+
+    Enforce HB_MAX_LANGSYS limit during layout subsetting.
+
+ src/hb-ot-layout-common.hh                         |  68 +++++++++++++--------
+ ...ase-minimized-hb-subset-fuzzer-5721073428987904 | Bin 0 -> 349561 bytes
+ 2 files changed, 41 insertions(+), 27 deletions(-)
+
+commit 9871461bce9a1557807f69615300e5df4f6ae322
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Oct 1 16:29:24 2019 -0700
+
+    Enforce HB_MAX_SCRIPTS during subsetting of the script table.
+
+ src/hb-ot-layout-common.hh | 46 +++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 41 insertions(+), 5 deletions(-)
+
+commit 029775bcbd0a25ee1cdb6c0653a2ce189774490a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Oct 9 11:00:09 2019 +0700
+
+    [buffer] Minor; improve HB_NO_BUFFER_MESSAGE
+
+ src/hb-buffer.cc | 2 ++
+ src/hb-buffer.hh | 2 +-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+commit 9a68e6b901967da14a5da5acb535c944794627b8
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Wed Oct 16 13:28:15 2019 +0330
+
+    [doc] minor
+    
+    Addresses https://github.com/harfbuzz/harfbuzz/pull/2013/files#r335196908
+
+ src/hb-common.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit b0b8551afc2ff86d027fdb380210601cb465af41
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sat Oct 12 21:12:19 2019 +0330
+
+    [glyf] Use range_checker_t in composite_iter_t
+
+ src/hb-ot-glyf-table.hh     | 12 +++++++-----
+ src/hb-ot-var-gvar-table.hh | 19 +++++++++----------
+ 2 files changed, 16 insertions(+), 15 deletions(-)
+
+commit 06e35ce052388e7ce079c0250db62428ae0c5bc8
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sat Oct 12 15:16:31 2019 +0330
+
+    [glyf] minor
+
+ src/hb-ot-glyf-table.hh | 128 +++++++++++++++++++++++++-----------------------
+ 1 file changed, 67 insertions(+), 61 deletions(-)
+
+commit d13bb4bd94a6ba8cdd4a03d40d8089a8f8b3a7ec
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sat Oct 12 12:13:57 2019 +0330
+
+    [glyf] other cleanups
+
+ src/hb-ot-glyf-table.hh | 338 +++++++++++++++++++++++-------------------------
+ 1 file changed, 160 insertions(+), 178 deletions(-)
+
+commit e7aa8c5d22b034f3d7bcf187a63cdec27732fa8a
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sat Oct 12 11:25:32 2019 +0330
+
+    [glyf] Introduce glyf::Glyph, a hb_bytes_t/GlyphHeader pair
+
+ src/hb-ot-glyf-table.hh | 177 +++++++++++++++++++++++++-----------------------
+ 1 file changed, 91 insertions(+), 86 deletions(-)
+
+commit 546ffc9faf869b4971765e9a4fd232cfe0eecaea
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sat Oct 12 09:51:57 2019 +0330
+
+    [glyf] minor
+
+ src/hb-ot-glyf-table.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 4299ea266e03b64db4e8a132983fed9fd0a967ee
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sat Oct 12 09:51:27 2019 +0330
+
+    [glyf] Move get_contour_points to GlyphHeader
+
+ src/hb-ot-glyf-table.hh | 260 ++++++++++++++++++++++++++----------------------
+ 1 file changed, 141 insertions(+), 119 deletions(-)
+
+commit b918cd8c76a6333e43b9be23178afc9e74e17024
+Author: Ben Wagner <bungeman at chromium.org>
+Date:   Thu Oct 10 15:30:48 2019 -0400
+
+    Document hb_feature_t.
+    
+    This documents hb_feature_t. This is motivated mostly by the ambiguity
+    of the units for 'start' and 'end' (clusters) and whether they are
+    inclusive or exclusive. This also documents that for lookup type 3 the
+    value is the one based index into the alternates and that in a list of
+    features later feature values override previous feature values with the
+    same tag.
+
+ src/hb-common.h | 15 +++++++++++++++
+ src/hb-shape.cc |  4 +++-
+ 2 files changed, 18 insertions(+), 1 deletion(-)
+
+commit e637a4b3de2fb8bdbc1b82e822f4a6cc579e794b
+Merge: 670fec23 e4464f44
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Oct 11 10:28:58 2019 +0700
+
+    Merge pull request #2012 from harfbuzz/lepcha-oo
+    
+    Reorder U+1C29 LEPCHA VOWEL SIGN OO
+
+commit 670fec231d31bf7417de590efd3485f337a7330f
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Thu Oct 10 09:21:08 2019 +0330
+
+    Minor, add a zero length tolerant memset, hb_memset
+
+ src/hb-algs.hh   | 10 +++++++++-
+ src/hb-buffer.cc |  3 +--
+ 2 files changed, 10 insertions(+), 3 deletions(-)
+
+commit e4464f4484009b4efe7144570384d836cb6bbac8
+Author: David Corbett <corbett.dav at husky.neu.edu>
+Date:   Wed Oct 9 20:55:52 2019 -0400
+
+    Reorder U+1C29 LEPCHA VOWEL SIGN OO
+
+ src/gen-use-table.py                 | 3 +++
+ src/hb-ot-shape-complex-use-table.cc | 2 +-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+commit e17e7443007fc0debc4a26e5cf37d5d76c747fbf
+Author: Garret Rieger <grieger at google.com>
+Date:   Wed Oct 9 11:45:42 2019 -0700
+
+    Convert existing uses of serialize_append in gsub subsetting to use subset_offset_array.
+
+ src/hb-ot-layout-gsub-table.hh | 44 +++---------------------------------------
+ 1 file changed, 3 insertions(+), 41 deletions(-)
+
+commit 36f18cecbbaf8635a2179a827242ca99d5283666
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Oct 7 14:02:31 2019 -0700
+
+    Add subset_offset_array helper function which simplifies subsetting offset arrays during stream operations.
+
+ src/hb-ot-layout-common.hh     | 54 ++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-layout-gsub-table.hh | 15 +-----------
+ 2 files changed, 55 insertions(+), 14 deletions(-)
+
+commit dc45f225212da7b8eca0ddcb3c9cd66e65983605
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Tue Oct 8 23:27:37 2019 +0330
+
+    [ot-metrics] Don't use mixed scaled and not scaled for generating extents
+
+ src/hb-ot-cff1-table.cc        | 4 ++--
+ src/hb-ot-cff2-table.cc        | 4 ++--
+ src/hb-ot-color-sbix-table.hh  | 7 +++++++
+ src/hb-ot-glyf-table.hh        | 6 +++---
+ test/api/test-ot-extents-cff.c | 6 +++---
+ 5 files changed, 17 insertions(+), 10 deletions(-)
+
+commit b068e25f8f89d9b07963dddd5d5e14f61539556f
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Tue Oct 8 16:29:15 2019 +0330
+
+    [glyf] Address Behdad's reviews
+    
+    Addresses https://github.com/harfbuzz/harfbuzz/pull/1999#issuecomment-539298559
+    * Don't check against Null pool
+    * Remove cryptic _tt suffix
+
+ src/hb-ot-font.cc       |  4 ++--
+ src/hb-ot-hmtx-table.hh | 16 ++++++++--------
+ 2 files changed, 10 insertions(+), 10 deletions(-)
+
+commit 6961766db2c53ea813079c61e4d996234ae8be4f
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Tue Oct 8 16:26:48 2019 +0330
+
+    [glyf] fix scaling direction
+
+ src/hb-ot-glyf-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 0527fda4c75e4354198df79275526d4726a3aacc
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Tue Oct 8 16:19:39 2019 +0330
+
+    minor
+
+ src/hb-subset-cff-common.cc | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit b2628f1a3e3a6875dcdf7cb89f5b10a4ae76e6f9
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Tue Oct 8 15:09:09 2019 +0330
+
+    [glyf] Move glyph bytes drop hints logic to GlyphHeader
+
+ src/hb-ot-glyf-table.hh | 92 ++++++++++++++++++++-----------------------------
+ 1 file changed, 37 insertions(+), 55 deletions(-)
+
+commit 1fb9c3b6463fdee9eb4dac697beab4d3d7a5fdcf
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Tue Oct 8 13:50:16 2019 +0330
+
+    [glyf] Implement depth limit for add_gid_and_children
+
+ src/hb-ot-glyf-table.hh | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+commit be0eddd41896824cb093024c2b4929b612ee1fae
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Tue Oct 8 13:46:55 2019 +0330
+
+    [glyf] Move add_gid_and_children to glyf table
+
+ src/hb-ot-glyf-table.hh | 14 ++++++++++++++
+ src/hb-subset-plan.cc   | 19 +------------------
+ 2 files changed, 15 insertions(+), 18 deletions(-)
+
+commit c7621cf21115aa563ee4fb9d2fcb601984848494
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Tue Oct 8 13:24:26 2019 +0330
+
+    Minor, replace hb_set_add with private API
+
+ src/hb-ot-map.cc            |  2 +-
+ src/hb-subset-cff-common.hh |  2 +-
+ src/hb-subset-cff1.cc       |  2 +-
+ src/hb-subset-cff2.cc       |  2 +-
+ src/hb-subset-plan.cc       | 10 +++++-----
+ 5 files changed, 9 insertions(+), 9 deletions(-)
+
+commit ad86806dcb702b25fac6a3364cf0f85e1b8f4b2a
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Tue Oct 8 12:14:14 2019 +0330
+
+    [glyf] Move subset related methods inside GlyphHeader
+
+ src/hb-ot-glyf-table.hh | 428 ++++++++++++++++++++++++------------------------
+ src/hb-subset-plan.cc   |   4 +-
+ 2 files changed, 214 insertions(+), 218 deletions(-)
+
+commit 7839e23558344f206175b5a798149e0f04f38266
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Mon Oct 7 11:14:26 2019 +0330
+
+    [glyf] minor
+
+ src/hb-ot-glyf-table.hh | 38 +++++++++++++++-----------------------
+ 1 file changed, 15 insertions(+), 23 deletions(-)
+
+commit cbefbb2439c1a2f4c20877e611f8986b3933234e
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Mon Oct 7 10:15:18 2019 +0330
+
+    [glyf] Move padding removal logic to GlyphHeader
+
+ src/hb-ot-glyf-table.hh | 219 +++++++++++++++++++++++-------------------------
+ 1 file changed, 105 insertions(+), 114 deletions(-)
+
+commit 1ab8f9aa7a182fa078f6c6a5a78ef95686b1ac54
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Mon Oct 7 08:24:12 2019 +0330
+
+    [glyf] minor
+
+ src/hb-ot-glyf-table.hh | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+commit 13fb5612ad545b419ca217f031864dde1b71c43f
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sun Oct 6 23:24:06 2019 +0330
+
+    [glyf] Aggregate get_offsets uses
+
+ src/hb-ot-glyf-table.hh | 29 +++++++----------------------
+ 1 file changed, 7 insertions(+), 22 deletions(-)
+
+commit 5179b96958f2db71c315c1d8c224bab87e2f4ae8
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Tue Oct 8 11:09:12 2019 +0330
+
+    [cff] minor on number_t
+
+ src/hb-cff-interp-common.hh | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+commit d73cdcf3612ae6114a0f828e0f667d447ed1a964
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sun Oct 6 18:09:14 2019 +0330
+
+    [ot-font] Apply font scaling before turning to int
+
+ src/hb-ot-cff1-table.cc        | 12 ++++-----
+ src/hb-ot-cff1-table.hh        |  2 +-
+ src/hb-ot-cff2-table.cc        |  8 +++---
+ src/hb-ot-color-cbdt-table.hh  | 14 +++++-----
+ src/hb-ot-color-sbix-table.hh  |  8 +++---
+ src/hb-ot-font.cc              | 12 +++------
+ src/hb-ot-glyf-table.hh        | 58 ++++++++++++++++++++----------------------
+ src/hb-ot-hmtx-table.hh        |  2 +-
+ src/hb-ot-var-hvar-table.hh    |  5 ++--
+ test/api/test-ot-extents-cff.c | 20 +++++++--------
+ 10 files changed, 66 insertions(+), 75 deletions(-)
+
+commit f2339964b713815c8e0e33699bf34ee24db12215
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sun Oct 6 16:41:52 2019 +0330
+
+    [glyf] minor, remove GlyphHeader::simple_* helpers
+
+ src/hb-ot-glyf-table.hh | 16 +++-------------
+ 1 file changed, 3 insertions(+), 13 deletions(-)
+
+commit 2d7ca6a76a754a42ec09a66319ac3e4ab5efc618
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sun Oct 6 16:31:29 2019 +0330
+
+    [glyf] Move get_instruction_length inside GlyphHeader struct
+
+ src/hb-ot-glyf-table.hh | 153 ++++++++++++++++++++++++++----------------------
+ 1 file changed, 84 insertions(+), 69 deletions(-)
+
+commit 50aef4d7f80b6c8a19481ad3d0fa89c7c7f222c2
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sun Oct 6 14:00:07 2019 +0330
+
+    [glyf] cleanup
+
+ src/hb-ot-glyf-table.hh | 128 +++++++++++++++++++++---------------------------
+ 1 file changed, 55 insertions(+), 73 deletions(-)
+
+commit ee3f4630d70099c42fd9c84796b29a236f6135b6
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sun Oct 6 13:56:35 2019 +0330
+
+    [glyf] Remove get_composite_iter and refactor bytes_for_glyph for shape uses
+
+ src/hb-ot-glyf-table.hh | 42 ++++++++++++++++--------------------------
+ src/hb-subset-plan.cc   |  2 +-
+ 2 files changed, 17 insertions(+), 27 deletions(-)
+
+commit 8378ab96e28fa34f154583850ff1c2c672a4310d
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sun Oct 6 13:49:45 2019 +0330
+
+    [glyf] Rewrite composite iterator to new iterators convention
+
+ src/hb-ot-glyf-table.hh | 201 ++++++++++++++++++++----------------------------
+ src/hb-subset-plan.cc   |  10 +--
+ 2 files changed, 85 insertions(+), 126 deletions(-)
+
+commit b7684fa9f42dffa6bd81acfade163123b30800b8
+Merge: 79ec65ae 21c80d95
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sun Oct 6 09:00:48 2019 +0330
+
+    Merge pull request #1999 from ebraminio/glyf-var
+    
+    Implement gvar table and variable glyf
+
+commit 21c80d955f69c1242c77e0ec7ccd852360dd54dd
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sat Oct 5 23:58:52 2019 +0330
+
+    [gvar] minor
+
+ src/hb-ot-var-gvar-table.hh | 43 +++++++++++++++++++++----------------------
+ 1 file changed, 21 insertions(+), 22 deletions(-)
+
+commit 5752863640cf4292dec313edebb57aecd47496f3
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Sat Oct 5 23:51:50 2019 +0330
+
+    [glyf][gvar] Make HB_NO_VAR buildable
+
+ src/hb-ot-font.cc       | 2 ++
+ src/hb-ot-glyf-table.hh | 6 ++++++
+ src/hb-ot-hmtx-table.hh | 8 ++++++++
+ 3 files changed, 16 insertions(+)
+
+commit 8e33510343d151afe49730f3a0b263a2853822b8
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Fri Oct 4 01:11:03 2019 +0330
+
+    [gvar] minor
+
+ src/hb-ot-var-gvar-table.hh | 132 ++++++++++++++++++++++----------------------
+ 1 file changed, 66 insertions(+), 66 deletions(-)
+
+commit b3afa8164460d63031a80d399200bcaa769c0fa1
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Fri Oct 4 00:32:04 2019 +0330
+
+    [glyf] Use common convention of other tables access, format
+
+ src/hb-ot-face-table-list.hh |  1 +
+ src/hb-ot-glyf-table.hh      | 65 +++++++++++++++++++-------------------------
+ 2 files changed, 29 insertions(+), 37 deletions(-)
+
+commit 88bd342c0ff686daad88bb6b4f2968bbd8b01a24
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Thu Oct 3 22:45:37 2019 +0330
+
+    [glyf] minor
+
+ src/hb-ot-glyf-table.hh     | 247 +++++++++++++++++++++++---------------------
+ src/hb-ot-var-gvar-table.hh |  54 +++++-----
+ 2 files changed, 155 insertions(+), 146 deletions(-)
+
+commit ee7610181cee5bbc0b5dc291228fbe032097bde4
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Thu Oct 3 15:59:45 2019 +0330
+
+    [hmtx] Use more conventional internal API style
+
+ src/Makefile.sources    |  1 -
+ src/harfbuzz.cc         |  1 -
+ src/hb-ot-font.cc       | 12 ++++++++++++
+ src/hb-ot-hmtx-table.cc | 42 ------------------------------------------
+ src/hb-ot-hmtx-table.hh | 18 ++++++++++--------
+ 5 files changed, 22 insertions(+), 52 deletions(-)
+
+commit c9577a630fd5bd08482ee7b94bc03c91fcf366c7
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Thu Oct 3 15:48:35 2019 +0330
+
+    [hmtx] Use more optimal way to access glyf table
+
+ src/hb-ot-hmtx-table.cc | 20 ++++----------------
+ src/hb-ot-hmtx-table.hh |  4 ++--
+ 2 files changed, 6 insertions(+), 18 deletions(-)
+
+commit b9ff43c162e8f61cff8e48d3dcbf7c1fe263d625
+Author: Michiharu Ariza <ariza at typekit.com>
+Date:   Tue Oct 1 16:13:40 2019 +0330
+
+    Implement gvar table and variable glyf
+    
+    Split from Ariza's "[subset] TrueType/CFF2 variable font" work on #1594
+
+ src/Makefile.sources                               |   2 +
+ src/harfbuzz.cc                                    |   1 +
+ src/hb-ot-font.cc                                  |   4 +-
+ src/hb-ot-glyf-table.hh                            | 618 ++++++++++++++---
+ src/hb-ot-hmtx-table.cc                            |  54 ++
+ src/hb-ot-hmtx-table.hh                            |  33 +-
+ src/hb-ot-var-gvar-table.hh                        | 734 +++++++++++++++++++++
+ test/api/Makefile.am                               |   1 +
+ .../SourceSansVariable-Roman-nohvar-41,C1.ttf      | Bin 0 -> 4696 bytes
+ test/api/fonts/SourceSansVariable-Roman.anchor.ttf | Bin 0 -> 4708 bytes
+ .../api/fonts/SourceSansVariable-Roman.modcomp.ttf | Bin 0 -> 3252 bytes
+ .../fonts/SourceSerifVariable-Roman-VVAR.abc.ttf   | Bin 0 -> 5632 bytes
+ test/api/test-ot-metrics-tt-var.c                  | 250 +++++++
+ 13 files changed, 1588 insertions(+), 109 deletions(-)
+
+commit 79ec65ae10f959aeddaa1e39eba5226c604a8c87
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Thu Oct 3 14:27:51 2019 +0330
+
+    [ot-font] Use var vmtx side bearing in calculating v-origin
+
+ src/hb-ot-font.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 3fd555be543a3e9bf9fee509327dbbc9a7b51cdb
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Thu Oct 3 13:02:41 2019 +0330
+
+    [hmtx] Prepare to fix and minor fixes
+
+ src/hb-ot-hmtx-table.hh     | 41 ++++++++++++++++-------------------------
+ src/hb-ot-var-hvar-table.hh |  9 +++++----
+ 2 files changed, 21 insertions(+), 29 deletions(-)
+
+commit 6d09b5a8a0f6ed7a2a92d91ac3d027bd54c452be
+Author: Michiharu Ariza <ariza at typekit.com>
+Date:   Thu Oct 3 12:01:39 2019 +0330
+
+    Implement hmtx/vmtx metrics read from hvar/vvar
+
+ src/hb-ot-hmtx-table.hh     | 46 ++++++++++++++++++++++++++++++++++++++++-----
+ src/hb-ot-var-hvar-table.hh | 19 +++++++++++++------
+ 2 files changed, 54 insertions(+), 11 deletions(-)
+
+commit cfafee52e4ff0441a33530847533f1b1f6019006
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Wed Oct 2 09:22:46 2019 +0330
+
+    Add Repology badges by @luzpaz
+    
+    fixes #2002
+    to track downstream packaging of harfbuzz
+
+ README.md | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+commit 2d7221a0e3552b1d902629d4ab6c0ce22db983a6
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Tue Oct 1 15:05:02 2019 +0330
+
+    [cff] minor
+
+ src/hb-ot-cff-common.hh | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+commit 0558413f27e9a18188c0e3d55f5ee57ea42b1548
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Tue Oct 1 13:49:55 2019 +0330
+
+    Minor, tweak spaces
+
+ src/hb-aat-layout-kerx-table.hh    |  4 ++--
+ src/hb-array.hh                    |  4 ++--
+ src/hb-buffer.hh                   |  3 +--
+ src/hb-font.h                      |  4 ++--
+ src/hb-font.hh                     |  8 ++++----
+ src/hb-open-file.hh                |  2 +-
+ src/hb-open-type.hh                | 10 +++++-----
+ src/hb-ot-cff-common.hh            |  4 ++--
+ src/hb-ot-cff1-table.cc            | 11 +++++------
+ src/hb-ot-cff1-table.hh            | 24 ++++++++++++------------
+ src/hb-ot-cff2-table.cc            |  4 ++--
+ src/hb-ot-cmap-table.hh            |  6 ++----
+ src/hb-ot-color-cbdt-table.hh      |  2 +-
+ src/hb-ot-color-cpal-table.hh      |  2 +-
+ src/hb-ot-kern-table.hh            | 12 ++++++------
+ src/hb-ot-layout-common.hh         |  2 +-
+ src/hb-ot-layout-gpos-table.hh     | 14 +++++++-------
+ src/hb-ot-os2-table.hh             |  4 ++--
+ src/hb-ot-shape-complex-myanmar.cc |  4 ++--
+ src/hb-subset-cff-common.hh        |  2 +-
+ src/hb-unicode.cc                  |  8 ++++----
+ src/hb-unicode.h                   | 20 ++++++++++----------
+ src/hb-vector.hh                   |  4 ++--
+ src/main.cc                        | 37 +++++++++++++++++++++++--------------
+ src/test-iter.cc                   |  2 +-
+ 25 files changed, 101 insertions(+), 96 deletions(-)
+
+commit 51b720f686adf45bc1b6db3aa76b7d2e62ad1304
+Author: Ebrahim Byagowi <ebrahim at gnu.org>
+Date:   Tue Oct 1 12:06:22 2019 +0330
+
+    Fix -Wsizeof-array-div clang warning
+
+ src/hb-ot-shape-complex-arabic-fallback.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit faace9437ea09d89ef5f5f9c9fc3ce0dbc672142
+Merge: e48ef080 f0dd724c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Sep 30 13:34:05 2019 -0700
+
+    Merge pull request #1807 from harfbuzz/subset-varstore
+    
+    VariationStore serializer
+
 commit e48ef0804ad7e4abd35ff3646fa6ed10ad32f1ef
 Author: Behdad Esfahbod <behdad at behdad.org>
 Date:   Mon Sep 30 12:39:06 2019 -0700
@@ -2250,6 +3078,13 @@
  src/hb-aat-layout-lcar-table.hh | 16 ++++++++++------
  1 file changed, 10 insertions(+), 6 deletions(-)
 
+commit f0dd724c1e091f42f289efbebd2c50e830e59c6e
+Merge: 68ac767e 4e1da6bb
+Author: blueshade7 <ariza at typekit.com>
+Date:   Mon Jul 29 14:21:05 2019 -0700
+
+    Merge branch 'master' into subset-varstore
+
 commit 4e1da6bb612b0c6386ab143dbb4ca19ff25bc2ba
 Author: Ebrahim Byagowi <ebrahim at gnu.org>
 Date:   Mon Jul 29 22:03:56 2019 +0430
@@ -3050,6 +3885,16 @@
  util/options.cc                                    |  44 ++++++++++++---------
  14 files changed, 48 insertions(+), 24 deletions(-)
 
+commit 68ac767e430c4dfe4c556b2c4f962cc3dfc5d3e4
+Author: blueshade7 <ariza at typekit.com>
+Date:   Fri Jul 12 23:02:29 2019 -0700
+
+    added skip(), get_next_value() to inc_bimap to subset VarStore with retain-gids
+
+ src/hb-bimap.hh            | 25 ++++++++++++++++++++++++-
+ src/hb-ot-layout-common.hh | 14 +++++++-------
+ 2 files changed, 31 insertions(+), 8 deletions(-)
+
 commit 4730b350b7ee90338caf3e962343af42412ce3df
 Author: Behdad Esfahbod <behdad at behdad.org>
 Date:   Fri Jul 12 15:38:35 2019 -0700
@@ -3455,6 +4300,15 @@
  src/gen-ucd-table.py |  8 +++++---
  2 files changed, 20 insertions(+), 11 deletions(-)
 
+commit 634390ecaf600176245e3354edd8dfdcb7f64cc5
+Author: blueshade7 <ariza at typekit.com>
+Date:   Mon Jul 1 18:52:57 2019 -0700
+
+    added VariationStore serializer to be used by HVAR/VVAR subsetters
+
+ src/hb-ot-layout-common.hh | 165 ++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 163 insertions(+), 2 deletions(-)
+
 commit 040b261deeed8924edcb087e27a61392d1f85023
 Author: Michiharu Ariza <ariza at typekit.com>
 Date:   Sun Jun 30 16:13:07 2019 -0700

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS	2019-10-28 23:44:53 UTC (rev 52560)
@@ -1,3 +1,11 @@
+Overview of changes leading to 2.6.3
+Monday, October 28, 2019
+====================================
+- Misc small fixes, mostly to build-related issues.
+- New API:
++hb_font_get_nominal_glyphs()
+
+
 Overview of changes leading to 2.6.2
 Monday, September 30, 2019
 ====================================

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/README
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/README	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/README	2019-10-28 23:44:53 UTC (rev 52560)
@@ -6,6 +6,7 @@
 [![Codacy Code Health](https://api.codacy.com/project/badge/Grade/f17f1708783c447488bc8dd317150eaa)](https://app.codacy.com/app/behdad/harfbuzz)
 [![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/master/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz)
 [![Coverals Code Coverage](https://img.shields.io/coveralls/harfbuzz/harfbuzz.svg)](https://coveralls.io/r/harfbuzz/harfbuzz)
+[![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions)
 [ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
 
 This is HarfBuzz, a text shaping library.
@@ -23,3 +24,11 @@
 For test execution, see [TESTING.md](TESTING.md).
 
 Documentation: https://harfbuzz.github.io
+
+
+<details>
+  <summary>Packaging status of HarfBuzz</summary
+
+[![Packaging status](https://repology.org/badge/vertical-allrepos/harfbuzz.svg?header=harfbuzz)](https://repology.org/project/harfbuzz/versions)  
+
+</details>

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md	2019-10-28 23:44:53 UTC (rev 52560)
@@ -6,6 +6,7 @@
 [![Codacy Code Health](https://api.codacy.com/project/badge/Grade/f17f1708783c447488bc8dd317150eaa)](https://app.codacy.com/app/behdad/harfbuzz)
 [![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/master/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz)
 [![Coverals Code Coverage](https://img.shields.io/coveralls/harfbuzz/harfbuzz.svg)](https://coveralls.io/r/harfbuzz/harfbuzz)
+[![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions)
 [ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
 
 This is HarfBuzz, a text shaping library.
@@ -23,3 +24,11 @@
 For test execution, see [TESTING.md](TESTING.md).
 
 Documentation: https://harfbuzz.github.io
+
+
+<details>
+  <summary>Packaging status of HarfBuzz</summary
+
+[![Packaging status](https://repology.org/badge/vertical-allrepos/harfbuzz.svg?header=harfbuzz)](https://repology.org/project/harfbuzz/versions)  
+
+</details>

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/TESTING.md
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/TESTING.md	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/TESTING.md	2019-10-28 23:44:53 UTC (rev 52560)
@@ -73,3 +73,14 @@
 sudo python infra/helper.py build_fuzzers --sanitizer address harfbuzz
 sudo python infra/helper.py run_fuzzer harfbuzz hb-subset-fuzzer
 ```
+
+## Profiling
+
+```
+make clean
+./configure CXXFLAGS="-fno-omit-frame-pointer -g"
+make
+perf record -o <perf output file> -g <command to run>
+perf report -i<perf output file>
+```
+

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac	2019-10-28 23:44:53 UTC (rev 52560)
@@ -1,6 +1,6 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [2.6.2],
+        [2.6.3],
         [https://github.com/harfbuzz/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources	2019-10-28 23:44:53 UTC (rev 52560)
@@ -136,6 +136,7 @@
 	hb-ot-tag.cc \
 	hb-ot-var-avar-table.hh \
 	hb-ot-var-fvar-table.hh \
+	hb-ot-var-gvar-table.hh \
 	hb-ot-var-hvar-table.hh \
 	hb-ot-var-mvar-table.hh \
 	hb-ot-var.cc \
@@ -162,7 +163,6 @@
 	hb-unicode.hh \
 	hb-utf.hh \
 	hb-vector.hh \
-	hb-warning.cc \
 	hb.hh \
 	$(NULL)
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py	2019-10-28 23:44:53 UTC (rev 52560)
@@ -383,6 +383,9 @@
 		# TODO: In USE's override list but not in Unicode 12.0
 		if U == 0x103C: UIPC = Left
 
+		# TODO: https://github.com/harfbuzz/harfbuzz/pull/2012
+		if U == 0x1C29: UIPC = Left
+
 		# TODO: These are not in USE's override list that we have, nor are they in Unicode 12.0
 		if 0xA926 <= U <= 0xA92A: UIPC = Top
 		# TODO: https://github.com/harfbuzz/harfbuzz/pull/1037

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -44,7 +44,6 @@
 #include "hb-static.cc"
 #include "hb-ucd.cc"
 #include "hb-unicode.cc"
-#include "hb-warning.cc"
 #include "hb-glib.cc"
 #include "hb-ft.cc"
 #include "hb-graphite2.cc"

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -733,8 +733,8 @@
 {
   typedef ExtendedTypes Types;
 
-  unsigned int tuple_count () const { return tupleCount; }
-  bool is_horizontal () const       { return !(coverage & Vertical); }
+  unsigned   tuple_count () const { return tupleCount; }
+  bool     is_horizontal () const { return !(coverage & Vertical); }
 
   enum Coverage
   {

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -588,10 +588,18 @@
   /* 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;
+  if (unlikely (!len)) return 0;
   return memcmp (a, b, len);
 }
 
+static inline void *
+hb_memset (void *s, int c, unsigned int n)
+{
+  /* It's illegal to pass NULL to memset(), even if n is zero. */
+  if (unlikely (!n)) return 0;
+  return memset (s, c, n);
+}
+
 static inline bool
 hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
 {

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -99,8 +99,15 @@
   template <typename T> operator T * () const { return arrayZ; }
 
   HB_INTERNAL bool operator == (const hb_array_t &o) const;
-  HB_INTERNAL uint32_t hash () const;
 
+  uint32_t hash () const {
+    uint32_t current = 0;
+    for (unsigned int i = 0; i < this->length; i++) {
+      current = current * 31 + hb_hash (this->arrayZ[i]);
+    }
+    return current;
+  }
+
   /*
    * Compare, Sort, and Search.
    */
@@ -281,8 +288,8 @@
   }
   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
+	      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;
@@ -332,27 +339,35 @@
 template <typename T>
 bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
 {
-  return length == o.length &&
-  + hb_zip (*this, o)
-  | hb_map ([] (hb_pair_t<T&, T&> &&_) { return _.first == _.second; })
-  | hb_all
-  ;
+  if (o.length != this->length) return false;
+  for (unsigned int i = 0; i < this->length; i++) {
+    if (this->arrayZ[i] != o.arrayZ[i]) return false;
+  }
+  return true;
 }
-template <typename T>
-uint32_t hb_array_t<T>::hash () const
-{
-  return
-  + hb_iter (*this)
-  | hb_map (hb_hash)
-  | hb_reduce ([] (uint32_t a, uint32_t b) { return a * 31 + b; }, 0)
-  ;
+
+/* TODO Specialize opeator== for hb_bytes_t and hb_ubytes_t. */
+
+template <>
+inline uint32_t hb_array_t<const char>::hash () const {
+  uint32_t current = 0;
+  for (unsigned int i = 0; i < this->length; i++)
+    current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u);
+  return current;
 }
 
+template <>
+inline uint32_t hb_array_t<const unsigned char>::hash () const {
+  uint32_t current = 0;
+  for (unsigned int i = 0; i < this->length; i++)
+    current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u);
+  return current;
+}
+
+
 typedef hb_array_t<const char> hb_bytes_t;
 typedef hb_array_t<const unsigned char> hb_ubytes_t;
 
-/* TODO Specialize opeator==/hash() for hb_bytes_t and hb_ubytes_t. */
-//template <>
-//uint32_t hb_array_t<const char>::hash () const { return 0; }
 
+
 #endif /* HB_ARRAY_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -212,26 +212,20 @@
 static_assert ((sizeof (long) == sizeof (void *)), "");
 
 
-#elif !defined(HB_NO_MT)
+#elif defined(HB_NO_MT)
 
-#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
+#define hb_atomic_int_impl_add(AI, V)		((*(AI) += (V)) - (V))
 
 #define _hb_memory_barrier()			do {} while (0)
 
-#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 */
+#else
 
-#define hb_atomic_int_impl_add(AI, V)		((*(AI) += (V)) - (V))
+#error "Could not find any system to define atomic_int macros."
+#error "Check hb-atomic.hh for possible resolutions."
 
-#define _hb_memory_barrier()			do {} while (0)
-
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)	(* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
-
-
 #endif
 
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -94,6 +94,14 @@
 /* Inremental bimap: only lhs is given, rhs is incrementally assigned */
 struct hb_inc_bimap_t : hb_bimap_t
 {
+  hb_inc_bimap_t () { init (); }
+
+  void init ()
+  {
+    hb_bimap_t::init ();
+    next_value = 0;
+  }
+
   /* Add a mapping from lhs to rhs with a unique value if lhs is unknown.
    * Return the rhs value as the result.
    */
@@ -102,12 +110,24 @@
     hb_codepoint_t  rhs = forw_map[lhs];
     if (rhs == HB_MAP_VALUE_INVALID)
     {
-      rhs = get_population ();
+      rhs = next_value++;
       set (lhs, rhs);
     }
     return rhs;
   }
 
+  hb_codepoint_t skip ()
+  { return next_value++; }
+
+  hb_codepoint_t get_next_value () const
+  { return next_value; }
+
+  void add_set (const hb_set_t *set)
+  {
+    hb_codepoint_t i = HB_SET_VALUE_INVALID;
+    while (hb_set_next (set, &i)) add (i);
+  }
+
   /* Create an identity map. */
   bool identity (unsigned int size)
   {
@@ -138,6 +158,9 @@
     for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
       set (work[rhs], rhs);
   }
+
+  protected:
+  unsigned int	next_value;
 };
 
 #endif /* HB_BIMAP_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -324,8 +324,7 @@
   out_len = 0;
   out_info = info;
 
-  if (likely (len))
-    memset (pos, 0, sizeof (pos[0]) * len);
+  hb_memset (pos, 0, sizeof (pos[0]) * len);
 }
 
 void
@@ -777,8 +776,10 @@
 
   free (buffer->info);
   free (buffer->pos);
+#ifndef HB_NO_BUFFER_MESSAGE
   if (buffer->message_destroy)
     buffer->message_destroy (buffer->message_data);
+#endif
 
   free (buffer);
 }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -126,9 +126,9 @@
   /* Debugging API */
 #ifndef HB_NO_BUFFER_MESSAGE
   hb_buffer_message_func_t message_func;
-#endif
   void *message_data;
   hb_destroy_func_t message_destroy;
+#endif
 
   /* Internal debugging. */
   /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
@@ -408,8 +408,7 @@
       }
   }
 
-  void unsafe_to_break_all ()
-  { unsafe_to_break_impl (0, len); }
+  void unsafe_to_break_all () { unsafe_to_break_impl (0, len); }
   void safe_to_break_all ()
   {
     for (unsigned int i = 0; i < len; i++)

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -220,18 +220,15 @@
   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_int (int v)       { value = v; }
+  int to_int () const        { return value; }
 
   void set_fixed (int32_t v) { value = v / 65536.0; }
-  int32_t to_fixed () const  { return (int32_t) (value * 65536.0); }
+  int32_t to_fixed () const  { return 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); }
 
@@ -248,7 +245,7 @@
   }
 
   protected:
-  double	value;
+  double value;
 };
 
 /* byte string */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h	2019-10-28 23:44:53 UTC (rev 52560)
@@ -425,6 +425,21 @@
  */
 #define HB_FEATURE_GLOBAL_END	((unsigned int) -1)
 
+/**
+ * hb_feature_t:
+ * @tag: a feature tag
+ * @value: 0 disables the feature, non-zero (usually 1) enables the feature.
+ * For features implemented as lookup type 3 (like 'salt') the @value is a one
+ * based index into the alternates.
+ * @start: the cluster to start applying this feature setting (inclusive).
+ * @end: the cluster to end applying this feature setting (exclusive).
+ *
+ * The #hb_feature_t is the structure that holds information about requested
+ * feature application. The feature will be applied with the given value to all
+ * glyphs which are in clusters between @start (inclusive) and @end (exclusive).
+ * Setting start to @HB_FEATURE_GLOBAL_START and end to @HB_FEATURE_GLOBAL_END
+ * specifies that the feature always applies to the entire buffer.
+ */
 typedef struct hb_feature_t {
   hb_tag_t      tag;
   uint32_t      value;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -792,6 +792,29 @@
 }
 
 /**
+ * hb_font_get_nominal_glyphs:
+ * @font: a font.
+ *
+ *
+ *
+ * Return value:
+ *
+ * Since: 2.6.3
+ **/
+unsigned int
+hb_font_get_nominal_glyphs (hb_font_t *font,
+			    unsigned int count,
+			    const hb_codepoint_t *first_unicode,
+			    unsigned int unicode_stride,
+			    hb_codepoint_t *first_glyph,
+			    unsigned int glyph_stride)
+{
+  return font->get_nominal_glyphs (count,
+				   first_unicode, unicode_stride,
+				   first_glyph, glyph_stride);
+}
+
+/**
  * hb_font_get_variation_glyph:
  * @font: a font.
  * @unicode:

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h	2019-10-28 23:44:53 UTC (rev 52560)
@@ -459,6 +459,14 @@
 			     hb_codepoint_t unicode, hb_codepoint_t variation_selector,
 			     hb_codepoint_t *glyph);
 
+HB_EXTERN unsigned int
+hb_font_get_nominal_glyphs (hb_font_t *font,
+			    unsigned int count,
+			    const hb_codepoint_t *first_unicode,
+			    unsigned int unicode_stride,
+			    hb_codepoint_t *first_glyph,
+			    unsigned int glyph_stride);
+
 HB_EXTERN hb_position_t
 hb_font_get_glyph_h_advance (hb_font_t *font,
 			     hb_codepoint_t glyph);
@@ -649,8 +657,8 @@
 /* Be *very* careful with this function! */
 HB_EXTERN void
 hb_font_set_funcs_data (hb_font_t         *font,
-		        void              *font_data,
-		        hb_destroy_func_t  destroy);
+			void              *font_data,
+			hb_destroy_func_t  destroy);
 
 
 HB_EXTERN void

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -216,7 +216,7 @@
   }
 
   hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
-				      hb_codepoint_t *glyph)
+			       hb_codepoint_t *glyph)
   {
     *glyph = 0;
     return klass->get.f.nominal_glyph (this, user_data,
@@ -286,7 +286,7 @@
   }
 
   hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
-				       hb_position_t *x, hb_position_t *y)
+			        hb_position_t *x, hb_position_t *y)
   {
     *x = *y = 0;
     return klass->get.f.glyph_h_origin (this, user_data,
@@ -328,7 +328,7 @@
   }
 
   hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
-				      hb_glyph_extents_t *extents)
+			       hb_glyph_extents_t *extents)
   {
     memset (extents, 0, sizeof (*extents));
     return klass->get.f.glyph_extents (this, user_data,
@@ -499,7 +499,7 @@
   }
 
   void subtract_glyph_h_origin (hb_codepoint_t glyph,
-			        hb_position_t *x, hb_position_t *y)
+				hb_position_t *x, hb_position_t *y)
   {
     hb_position_t origin_x, origin_y;
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -46,16 +46,13 @@
   static_assert (hb_is_integral (K) || hb_is_pointer (K), "");
   static_assert (hb_is_integral (V) || hb_is_pointer (V), "");
 
-  /* TODO If key type is a pointer, keep hash in item_t and use to:
-   * 1. avoid rehashing when resizing table, and
-   * 2. compare hash before comparing keys, for speed.
-   */
   struct item_t
   {
     K key;
     V value;
+    uint32_t hash;
 
-    void clear () { key = kINVALID; value = vINVALID; }
+    void clear () { key = kINVALID; value = vINVALID; hash = 0; }
 
     bool operator == (K o) { return hb_deref (key) == hb_deref (o); }
     bool operator == (const item_t &o) { return *this == o.key; }
@@ -137,7 +134,9 @@
     if (old_items)
       for (unsigned int i = 0; i < old_size; i++)
 	if (old_items[i].is_real ())
-	  set (old_items[i].key, old_items[i].value);
+	  set_with_hash (old_items[i].key,
+                         old_items[i].hash,
+                         old_items[i].value);
 
     free (old_items);
 
@@ -146,29 +145,9 @@
 
   void set (K key, V value)
   {
-    if (unlikely (!successful)) return;
-    if (unlikely (key == kINVALID)) return;
-    if ((occupancy + occupancy / 2) >= mask && !resize ()) return;
-    unsigned int i = bucket_for (key);
+    set_with_hash (key, hb_hash (key), value);
+  }
 
-    if (value == vINVALID && 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++;
-
-  }
   V get (K key) const
   {
     if (unlikely (!items)) return vINVALID;
@@ -237,14 +216,45 @@
 
   protected:
 
+  void set_with_hash (K key, uint32_t hash, V value)
+  {
+    if (unlikely (!successful)) return;
+    if (unlikely (key == kINVALID)) return;
+    if ((occupancy + occupancy / 2) >= mask && !resize ()) return;
+    unsigned int i = bucket_for_hash (key, hash);
+
+    if (value == vINVALID && 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;
+    items[i].hash = hash;
+
+    occupancy++;
+    if (!items[i].is_tombstone ())
+      population++;
+  }
+
   unsigned int bucket_for (K key) const
   {
-    unsigned int i = hb_hash (key) % prime;
+    return bucket_for_hash (key, hb_hash (key));
+  }
+
+  unsigned int bucket_for_hash (K key, uint32_t hash) const
+  {
+    unsigned int i = hash % prime;
     unsigned int step = 0;
     unsigned int tombstone = (unsigned) -1;
     while (!items[i].is_unused ())
     {
-      if (items[i] == key)
+      if (items[i].hash == hash && items[i] == key)
 	return i;
       if (tombstone == (unsigned) -1 && items[i].is_tombstone ())
 	tombstone = i;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-mutex.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-mutex.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-mutex.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -92,26 +92,8 @@
 #define hb_mutex_impl_finish(M)	HB_STMT_START {} HB_STMT_END
 
 
-#elif !defined(HB_NO_MT)
+#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
@@ -120,6 +102,11 @@
 #define hb_mutex_impl_finish(M)	HB_STMT_START {} HB_STMT_END
 
 
+#else
+
+#error "Could not find any system to define mutex macros."
+#error "Check hb-mutex.hh for possible resolutions."
+
 #endif
 
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -287,7 +287,7 @@
   { return CastR<OpenTypeFontFace> ((data_base+offset).arrayZ); }
 
   bool sanitize (hb_sanitize_context_t *c,
-			const void *data_base) const
+		 const void *data_base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -264,8 +264,8 @@
 template <typename Type>
 struct _hb_has_null<Type, true>
 {
-  static const Type *get_null () { return &Null(Type); }
-  static Type *get_crap ()       { return &Crap(Type); }
+  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>
@@ -423,7 +423,7 @@
   { 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<      Type> ()       { return as_array (); }
   operator hb_array_t<const Type> () const { return as_array (); }
 
   template <typename T>
@@ -902,8 +902,8 @@
   { 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
+	      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); }
 };
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -564,13 +564,13 @@
       if (glyph < ranges[i].first)
 	break;
 
-    return (hb_codepoint_t)ranges[i - 1].fd;
+    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]); }
+  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 */
@@ -608,8 +608,8 @@
 
   hb_codepoint_t get_fd (hb_codepoint_t glyph) const
   {
-    if (this == &Null (FDSelect))
-      return 0;
+    if (this == &Null (FDSelect)) return 0;
+
     switch (format)
     {
     case 0: return u.format0.get_fd (glyph);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -203,8 +203,7 @@
     }
   }
 
-  bool empty () const
-  { return (min.x >= max.x) || (min.y >= max.y); }
+  bool empty () const { return (min.x >= max.x) || (min.y >= max.y); }
 
   point_t min;
   point_t max;
@@ -219,12 +218,12 @@
     bounds.init ();
   }
 
-  void start_path ()         { path_open = true; }
-  void end_path ()           { path_open = false; }
+  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;
+  bool path_open;
+  bounds_t bounds;
 
   const OT::cff1::accelerator_t *cff;
 };
@@ -307,7 +306,7 @@
   return true;
 }
 
-bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
 {
 #ifdef HB_NO_OT_FONT_CFF
   /* XXX Remove check when this code moves to .hh file. */
@@ -314,7 +313,7 @@
   return true;
 #endif
 
-  bounds_t  bounds;
+  bounds_t bounds;
 
   if (!_get_bounds (this, glyph, bounds))
     return false;
@@ -326,8 +325,8 @@
   }
   else
   {
-    extents->x_bearing = (int32_t)bounds.min.x.floor ();
-    extents->width = (int32_t)bounds.max.x.ceil () - extents->x_bearing;
+    extents->x_bearing = font->em_scalef_x (bounds.min.x.to_real ());
+    extents->width = font->em_scalef_x (bounds.max.x.to_real () - bounds.min.x.to_real ());
   }
   if (bounds.min.y >= bounds.max.y)
   {
@@ -336,8 +335,8 @@
   }
   else
   {
-    extents->y_bearing = (int32_t)bounds.max.y.ceil ();
-    extents->height = (int32_t)bounds.min.y.floor () - extents->y_bearing;
+    extents->y_bearing = font->em_scalef_y (bounds.max.y.to_real ());
+    extents->height = font->em_scalef_x (bounds.min.y.to_real () - bounds.max.y.to_real ());
   }
 
   return true;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -1155,7 +1155,7 @@
     }
 
     bool is_valid () const { return blob != nullptr; }
-    bool is_CID () const { return topDict.is_CID (); }
+    bool   is_CID () const { return topDict.is_CID (); }
 
     bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
 
@@ -1196,7 +1196,7 @@
 
   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_extents (hb_font_t *font, 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;
   };
 
@@ -1225,25 +1225,25 @@
 
     bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
 
-    hb_codepoint_t  glyph_to_code (hb_codepoint_t glyph) const
+    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);
+	hb_codepoint_t sid = glyph_to_sid (glyph);
 	if (sid == 0) return 0;
-	hb_codepoint_t  code = 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;
+	case StandardEncoding:
+	  code = lookup_standard_encoding_for_code (sid);
+	  break;
+	case ExpertEncoding:
+	  code = lookup_expert_encoding_for_code (sid);
+	  break;
+	default:
+	  break;
 	}
 	return code;
       }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -44,8 +44,8 @@
     max_y.set_int (INT_MIN);
   }
 
-  void start_path ()         { path_open = true; }
-  void end_path ()           { path_open = false; }
+  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)
@@ -125,8 +125,8 @@
   }
   else
   {
-    extents->x_bearing = (int32_t)param.min_x.floor ();
-    extents->width = (int32_t)param.max_x.ceil () - extents->x_bearing;
+    extents->x_bearing = font->em_scalef_x (param.min_x.to_real ());
+    extents->width = font->em_scalef_x (param.max_x.to_real () - param.min_x.to_real ());
   }
   if (param.min_y >= param.max_y)
   {
@@ -135,8 +135,8 @@
   }
   else
   {
-    extents->y_bearing = (int32_t)param.max_y.ceil ();
-    extents->height = (int32_t)param.min_y.floor () - extents->y_bearing;
+    extents->y_bearing = font->em_scalef_y (param.max_y.to_real ());
+    extents->height = font->em_scalef_y (param.min_y.to_real () - param.max_y.to_real ());
   }
 
   return true;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -736,9 +736,7 @@
 struct UVSMapping
 {
   int cmp (const hb_codepoint_t &codepoint) const
-  {
-    return unicodeValue.cmp (codepoint);
-  }
+  { return unicodeValue.cmp (codepoint); }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -1170,7 +1168,7 @@
 		    return true;
 
 		  return false;
-	        })
+		})
     ;
 
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -51,12 +51,12 @@
     return_trace (c->check_struct (this));
   }
 
-  void get_extents (hb_glyph_extents_t *extents) const
+  void get_extents (hb_font_t *font, hb_glyph_extents_t *extents) const
   {
-    extents->x_bearing = bearingX;
-    extents->y_bearing = bearingY;
-    extents->width = width;
-    extents->height = - (hb_position_t) height;
+    extents->x_bearing = font->em_scale_x (bearingX);
+    extents->y_bearing = font->em_scale_y (bearingY);
+    extents->width = font->em_scale_x (width);
+    extents->height = font->em_scale_y (-height);
   }
 
   HBUINT8	height;
@@ -424,7 +424,7 @@
 	      return false;
 	    const GlyphBitmapDataFormat17& glyphFormat17 =
 		StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
-	    glyphFormat17.glyphMetrics.get_extents (extents);
+	    glyphFormat17.glyphMetrics.get_extents (font, extents);
 	    break;
 	  }
 	  case 18: {
@@ -432,7 +432,7 @@
 	      return false;
 	    const GlyphBitmapDataFormat18& glyphFormat18 =
 		StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
-	    glyphFormat18.glyphMetrics.get_extents (extents);
+	    glyphFormat18.glyphMetrics.get_extents (font, extents);
 	    break;
 	  }
 	  default:
@@ -453,7 +453,7 @@
     }
 
     hb_blob_t* reference_png (hb_font_t      *font,
-				     hb_codepoint_t  glyph) const
+			      hb_codepoint_t  glyph) const
     {
       const void *base;
       const BitmapSizeTable &strike = this->cblc->choose_strike (font);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -115,7 +115,7 @@
   { return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); }
 
   unsigned int get_palette_count () const { return numPalettes; }
-  unsigned int get_color_count () const   { return numColors; }
+  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); }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-sbix-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-sbix-table.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-sbix-table.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -243,11 +243,18 @@
       if (strike_ppem)
       {
 	float scale = font->face->get_upem () / (float) strike_ppem;
-	extents->x_bearing = roundf (extents->x_bearing * scale);
-	extents->y_bearing = roundf (extents->y_bearing * scale);
-	extents->width = roundf (extents->width * scale);
-	extents->height = roundf (extents->height * scale);
+	extents->x_bearing = font->em_scalef_x (extents->x_bearing * scale);
+	extents->y_bearing = font->em_scalef_y (extents->y_bearing * scale);
+	extents->width = font->em_scalef_x (extents->width * scale);
+	extents->height = font->em_scalef_y (extents->height * scale);
       }
+      else
+      {
+	extents->x_bearing = font->em_scale_x (extents->x_bearing);
+	extents->y_bearing = font->em_scale_y (extents->y_bearing);
+	extents->width = font->em_scale_x (extents->width);
+	extents->height = font->em_scale_y (extents->height);
+      }
 
       hb_blob_destroy (blob);
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -84,6 +84,7 @@
 #ifndef HB_NO_VAR
 HB_OT_TABLE (OT, fvar)
 HB_OT_TABLE (OT, avar)
+HB_OT_ACCELERATOR (OT, gvar)
 HB_OT_TABLE (OT, MVAR)
 #endif
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -160,11 +160,11 @@
 #endif
 
   hb_glyph_extents_t extents = {0};
-  if (ot_face->glyf->get_extents (glyph, &extents))
+  if (ot_face->glyf->get_extents (font, 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);
+    hb_position_t tsb = vmtx.get_side_bearing (font, glyph);
+    *y = extents.y_bearing + font->em_scale_y (tsb);
     return true;
   }
 
@@ -188,9 +188,9 @@
 #if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
   if (!ret) ret = ot_face->sbix->get_extents (font, glyph, extents);
 #endif
-  if (!ret) ret = ot_face->glyf->get_extents (glyph, extents);
+  if (!ret) ret = ot_face->glyf->get_extents (font, glyph, extents);
 #ifndef HB_NO_OT_FONT_CFF
-  if (!ret) ret = ot_face->cff1->get_extents (glyph, extents);
+  if (!ret) ret = ot_face->cff1->get_extents (font, glyph, extents);
   if (!ret) ret = ot_face->cff2->get_extents (font, glyph, extents);
 #endif
 #if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
@@ -198,10 +198,6 @@
 #endif
 
   // TODO Hook up side-bearings variations.
-  extents->x_bearing = font->em_scale_x (extents->x_bearing);
-  extents->y_bearing = font->em_scale_y (extents->y_bearing);
-  extents->width     = font->em_scale_x (extents->width);
-  extents->height    = font->em_scale_y (extents->height);
   return ret;
 }
 
@@ -315,5 +311,19 @@
 		     nullptr);
 }
 
+#ifndef HB_NO_VAR
+int
+_glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
+{
+  return font->face->table.glyf->get_side_bearing_var (font, glyph, is_vertical);
+}
 
+unsigned
+_glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
+{
+  return font->face->table.glyf->get_advance_var (font, glyph, is_vertical);
+}
 #endif
+
+
+#endif

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2015  Google, Inc.
+ * Copyright © 2019  Adobe Inc.
  * Copyright © 2019  Ebrahim Byagowi
  *
  *  This is part of HarfBuzz, a text shaping library.
@@ -23,6 +24,7 @@
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * Google Author(s): Behdad Esfahbod, Garret Rieger, Roderick Sheeter
+ * Adobe Author(s): Michiharu Ariza
  */
 
 #ifndef HB_OT_GLYF_TABLE_HH
@@ -30,7 +32,11 @@
 
 #include "hb-open-type.hh"
 #include "hb-ot-head-table.hh"
+#include "hb-ot-hmtx-table.hh"
+#include "hb-ot-var-gvar-table.hh"
 
+#include <float.h>
+
 namespace OT {
 
 
@@ -57,7 +63,7 @@
   UnsizedArrayOf<HBUINT8>
 		dataZ;	/* Location data. */
   public:
-  DEFINE_SIZE_MIN (0);  /* In reality, this is UNBOUNDED() type; but since we always
+  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. */
 };
@@ -77,8 +83,7 @@
   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
-     * struct do all the hard work... */
+    /* Runtime checks as eager sanitizing each glyph is costy */
     return_trace (true);
   }
 
@@ -111,7 +116,7 @@
 					    free);
 
     bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
-		  && _add_head_and_set_loca_version(plan, use_short_loca);
+		  && _add_head_and_set_loca_version (plan, use_short_loca);
 
     hb_blob_destroy (loca_blob);
     return result;
@@ -136,7 +141,7 @@
     ;
   }
 
-  // requires source of SubsetGlyph complains the identifier isn't declared
+  /* requires source of SubsetGlyph complains the identifier isn't declared */
   template <typename Iterator>
   bool serialize (hb_serialize_context_t *c,
 		  Iterator it,
@@ -147,6 +152,9 @@
     return_trace (true);
   }
 
+  /* Byte region(s) per glyph to output
+     unpadded, hints removed if so requested
+     If we fail to process a glyph we produce an empty (0-length) glyph */
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
@@ -154,9 +162,6 @@
     glyf *glyf_prime = c->serializer->start_embed <glyf> ();
     if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
 
-    // Byte region(s) per glyph to output
-    // unpadded, hints removed if so requested
-    // If we fail to process a glyph we produce an empty (0-length) glyph
     hb_vector_t<SubsetGlyph> glyphs;
     _populate_subset_glyphs (c->plan, &glyphs);
 
@@ -174,8 +179,8 @@
 
   template <typename SubsetGlyph>
   void
-  _populate_subset_glyphs (const hb_subset_plan_t * plan,
-			   hb_vector_t<SubsetGlyph> * glyphs /* OUT */) const
+  _populate_subset_glyphs (const hb_subset_plan_t   *plan,
+			   hb_vector_t<SubsetGlyph> *glyphs /* OUT */) const
   {
     OT::glyf::accelerator_t glyf;
     glyf.init (plan->source);
@@ -186,14 +191,13 @@
 		SubsetGlyph subset_glyph = {0};
 		subset_glyph.new_gid = new_gid;
 
-		// should never fail: all old gids should be mapped
+		/* should never fail: all old gids should be mapped */
 		if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
 		  return subset_glyph;
 
-		subset_glyph.source_glyph = glyf.bytes_for_glyph ((const char *) this,
-								  subset_glyph.old_gid);
-		if (plan->drop_hints) subset_glyph.drop_hints (glyf);
-		else subset_glyph.dest_start = subset_glyph.source_glyph;
+		subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
+		if (plan->drop_hints) subset_glyph.drop_hints_bytes ();
+		else subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
 
 		return subset_glyph;
 	      })
@@ -203,58 +207,6 @@
     glyf.fini ();
   }
 
-  static void
-  _fix_component_gids (const hb_subset_plan_t *plan,
-		       hb_bytes_t glyph)
-  {
-    OT::glyf::CompositeGlyphHeader::Iterator iterator;
-    if (OT::glyf::CompositeGlyphHeader::get_iterator (&glyph,
-						      glyph.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 = new_gid;
-      } while (iterator.move_to_next ());
-    }
-  }
-
-  static void
-  _zero_instruction_length (hb_bytes_t glyph)
-  {
-    const GlyphHeader &glyph_header = *glyph.as<GlyphHeader> ();
-    if (!glyph_header.is_simple_glyph ()) return;  // only for simple glyphs
-
-    unsigned int instruction_len_offset = glyph_header.simple_instruction_len_offset ();
-    const HBUINT16 &instruction_len = StructAtOffset<HBUINT16> (&glyph,
-								instruction_len_offset);
-    (HBUINT16 &) instruction_len = 0;
-  }
-
-  static bool _remove_composite_instruction_flag (hb_bytes_t glyph)
-  {
-    const GlyphHeader &glyph_header = *glyph.as<GlyphHeader> ();
-    if (!glyph_header.is_composite_glyph ()) return true;  // only for composites
-
-    /* remove WE_HAVE_INSTRUCTIONS from flags in dest */
-    OT::glyf::CompositeGlyphHeader::Iterator composite_it;
-    if (unlikely (!OT::glyf::CompositeGlyphHeader::get_iterator (&glyph, glyph.length,
-								 &composite_it)))
-      return false;
-    const OT::glyf::CompositeGlyphHeader *composite_header;
-    do
-    {
-      composite_header = composite_it.current;
-      OT::HBUINT16 *flags = const_cast<OT::HBUINT16 *> (&composite_header->flags);
-      *flags = (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS;
-    } while (composite_it.move_to_next ());
-    return true;
-  }
-
   static bool
   _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
   {
@@ -273,42 +225,8 @@
     return success;
   }
 
-  struct GlyphHeader
+  struct CompositeGlyphChain
   {
-    unsigned int simple_instruction_len_offset () const
-    { return static_size + 2 * numberOfContours; }
-
-    unsigned int simple_length (unsigned int instruction_len) const
-    { return simple_instruction_len_offset () + 2 + instruction_len; }
-
-    bool is_composite_glyph () const { return numberOfContours < 0; }
-    bool is_simple_glyph () const    { return numberOfContours > 0; }
-
-    void get_extents (hb_glyph_extents_t *extents) const
-    {
-      extents->x_bearing = hb_min (xMin, xMax);
-      extents->y_bearing = hb_max (yMin, yMax);
-      extents->width     = hb_max (xMin, xMax) - extents->x_bearing;
-      extents->height    = hb_min (yMin, yMax) - extents->y_bearing;
-    }
-
-    bool has_data () const { return numberOfContours; }
-
-    protected:
-    HBINT16	numberOfContours;/* If the number of contours is
-				  * greater than or equal to zero,
-				  * this is a simple glyph; if negative,
-				  * this is a composite glyph. */
-    FWORD	xMin;		 /* Minimum x for coordinate data. */
-    FWORD	yMin;		 /* Minimum y for coordinate data. */
-    FWORD	xMax;		 /* Maximum x for coordinate data. */
-    FWORD	yMax;		 /* Maximum y for coordinate data. */
-    public:
-    DEFINE_SIZE_STATIC (10);
-  };
-
-  struct CompositeGlyphHeader
-  {
     enum composite_glyph_flag_t
     {
       ARG_1_AND_2_ARE_WORDS =      0x0001,
@@ -325,180 +243,248 @@
       UNSCALED_COMPONENT_OFFSET =  0x1000
     };
 
-    HBUINT16 flags;
-    HBGlyphID  glyphIndex;
-
     unsigned int get_size () const
     {
       unsigned int size = min_size;
-      // arg1 and 2 are int16
+      /* arg1 and 2 are int16 */
       if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
-      // arg1 and 2 are int8
+      /* arg1 and 2 are int8 */
       else size += 2;
 
-      // One x 16 bit (scale)
+      /* One x 16 bit (scale) */
       if (flags & WE_HAVE_A_SCALE) size += 2;
-      // Two x 16 bit (xscale, yscale)
+      /* 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)
+      /* Four x 16 bit (xscale, scale01, scale10, yscale) */
       else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8;
 
       return size;
     }
 
-    // TODO rewrite using new iterator framework if possible
-    struct Iterator
+    bool is_use_my_metrics () const { return   flags & USE_MY_METRICS; }
+    bool is_anchored ()       const { return !(flags & ARGS_ARE_XY_VALUES); }
+    void get_anchor_points (unsigned int &point1, unsigned int &point2) const
     {
-      const char *glyph_start;
-      const char *glyph_end;
-      const CompositeGlyphHeader *current;
+      const HBUINT8 *p = &StructAfter<const HBUINT8> (glyphIndex);
+      if (flags & ARG_1_AND_2_ARE_WORDS)
+      {
+	point1 = ((const HBUINT16 *) p)[0];
+	point2 = ((const HBUINT16 *) p)[1];
+      }
+      else
+      {
+	point1 = p[0];
+	point2 = p[1];
+      }
+    }
 
-      bool move_to_next ()
+    void transform_points (contour_point_vector_t &points) const
+    {
+      float matrix[4];
+      contour_point_t trans;
+      if (get_transformation (matrix, trans))
       {
-	if (current->flags & CompositeGlyphHeader::MORE_COMPONENTS)
+	if (scaled_offsets ())
 	{
-	  const CompositeGlyphHeader *possible =
-	    &StructAfter<CompositeGlyphHeader, CompositeGlyphHeader> (*current);
-	  if (!in_range (possible))
-	    return false;
-	  current = possible;
-	  return true;
+	  points.translate (trans);
+	  points.transform (matrix);
 	}
-	return false;
+	else
+	{
+	  points.transform (matrix);
+	  points.translate (trans);
+	}
       }
+    }
 
-      bool in_range (const CompositeGlyphHeader *composite) const
+    protected:
+    bool scaled_offsets () const
+    { return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
+
+    bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
+    {
+      matrix[0] = matrix[3] = 1.f;
+      matrix[1] = matrix[2] = 0.f;
+
+      int tx, ty;
+      const HBINT8 *p = &StructAfter<const HBINT8> (glyphIndex);
+      if (flags & ARG_1_AND_2_ARE_WORDS)
       {
-	return (const char *) composite >= glyph_start
-	    && ((const char *) composite + CompositeGlyphHeader::min_size) <= glyph_end
-	    && ((const char *) composite + composite->get_size ()) <= glyph_end;
+	tx = *(const HBINT16 *) p;
+	p += HBINT16::static_size;
+	ty = *(const HBINT16 *) p;
+	p += HBINT16::static_size;
       }
-    };
+      else
+      {
+	tx = *p++;
+	ty = *p++;
+      }
+      if (is_anchored ()) tx = ty = 0;
 
-    static bool get_iterator (const char * glyph_data,
-			      unsigned int length,
-			      CompositeGlyphHeader::Iterator *iterator /* OUT */)
-    {
-      const GlyphHeader &glyph_header = *hb_bytes_t (glyph_data, length).as<GlyphHeader> ();
-      if (!glyph_header.has_data ()) return false; /* Empty glyph; zero extents. */
+      trans.init ((float) tx, (float) ty);
 
-      if (glyph_header.is_composite_glyph ())
       {
-	const CompositeGlyphHeader *possible =
-	  &StructAfter<CompositeGlyphHeader, GlyphHeader> (glyph_header);
-
-	iterator->glyph_start = glyph_data;
-	iterator->glyph_end = (const char *) glyph_data + length;
-	if (!iterator->in_range (possible))
-	  return false;
-	iterator->current = possible;
-	return true;
+	const F2DOT14 *points = (const F2DOT14 *) p;
+	if (flags & WE_HAVE_A_SCALE)
+	{
+	  matrix[0] = matrix[3] = points[0].to_float ();
+	  return true;
+	}
+	else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
+	{
+	  matrix[0] = points[0].to_float ();
+	  matrix[3] = points[1].to_float ();
+	  return true;
+	}
+	else if (flags & WE_HAVE_A_TWO_BY_TWO)
+	{
+	  matrix[0] = points[0].to_float ();
+	  matrix[1] = points[1].to_float ();
+	  matrix[2] = points[2].to_float ();
+	  matrix[3] = points[3].to_float ();
+	  return true;
+	}
       }
-
-      return false;
+      return tx || ty;
     }
 
+    public:
+    HBUINT16	flags;
+    HBGlyphID	glyphIndex;
+    public:
     DEFINE_SIZE_MIN (4);
   };
 
-  struct accelerator_t
+  struct composite_iter_t : hb_iter_with_fallback_t<composite_iter_t, const CompositeGlyphChain &>
   {
-    void init (hb_face_t *face)
+    typedef const CompositeGlyphChain *__item_t__;
+    composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
+      glyph (glyph_), current (current_), checker (range_checker_t (glyph.arrayZ, glyph.length))
+    { if (!in_range (current)) current = nullptr; }
+    composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), checker (range_checker_t (nullptr, 0)) {}
+
+    const CompositeGlyphChain &__item__ () const { return *current; }
+    bool __more__ () const { return current; }
+    void __next__ ()
     {
-      memset (this, 0, sizeof (accelerator_t));
+      if (!(current->flags & CompositeGlyphChain::MORE_COMPONENTS)) { current = nullptr; return; }
 
-      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.indexToLocFormat;
-
-      loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
-      glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
-
-      num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
+      const CompositeGlyphChain *possible = &StructAfter<CompositeGlyphChain,
+							 CompositeGlyphChain> (*current);
+      if (!in_range (possible)) { current = nullptr; return; }
+      current = possible;
     }
+    bool operator != (const composite_iter_t& o) const
+    { return glyph != o.glyph || current != o.current; }
 
-    void fini ()
+    bool in_range (const CompositeGlyphChain *composite) const
     {
-      loca_table.destroy ();
-      glyf_table.destroy ();
+      return checker.in_range (composite, CompositeGlyphChain::min_size)
+	  && checker.in_range (composite, composite->get_size ());
     }
 
-    /*
-     * Returns true if the referenced glyph is a valid glyph and a composite glyph.
-     * If true is returned a pointer to the composite glyph will be written into
-     * composite.
-     */
-    bool get_composite (hb_codepoint_t glyph,
-			CompositeGlyphHeader::Iterator *composite /* OUT */) const
+    private:
+    hb_bytes_t glyph;
+    __item_t__ current;
+    range_checker_t checker;
+  };
+
+  struct Glyph
+  {
+    private:
+    struct GlyphHeader
     {
-      if (unlikely (!num_glyphs))
-	return false;
+      bool has_data () const { return numberOfContours; }
 
-      unsigned int start_offset, end_offset;
-      if (!get_offsets (glyph, &start_offset, &end_offset))
-	return false; /* glyph not found */
+      bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
+      {
+	/* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */
+	/* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */
+	extents->x_bearing = font->em_scale_x (font->face->table.hmtx->get_side_bearing (gid));
+	extents->y_bearing = font->em_scale_y (hb_max (yMin, yMax));
+	extents->width     = font->em_scale_x (hb_max (xMin, xMax) - hb_min (xMin, xMax));
+	extents->height    = font->em_scale_y (hb_min (yMin, yMax) - hb_max (yMin, yMax));
 
-      return CompositeGlyphHeader::get_iterator ((const char *) this->glyf_table + start_offset,
-						 end_offset - start_offset,
-						 composite);
-    }
+	return true;
+      }
 
-    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_RESERVED1 = 0x40,
-      FLAG_RESERVED2 = 0x80
+      HBINT16	numberOfContours;
+			/* If the number of contours is
+			 * greater than or equal to zero,
+			 * this is a simple glyph; if negative,
+			 * this is a composite glyph. */
+      FWORD	xMin;	/* Minimum x for coordinate data. */
+      FWORD	yMin;	/* Minimum y for coordinate data. */
+      FWORD	xMax;	/* Maximum x for coordinate data. */
+      FWORD	yMax;	/* Maximum y for coordinate data. */
+      public:
+      DEFINE_SIZE_STATIC (10);
     };
 
-    /* based on FontTools _g_l_y_f.py::trim */
-    bool remove_padding (unsigned int start_offset,
-			 unsigned int *end_offset) const
+    struct SimpleGlyph
     {
-      const char *glyph = ((const char *) glyf_table) + start_offset;
-      unsigned int glyph_length = *end_offset - start_offset;
-      const GlyphHeader &glyph_header = *hb_bytes_t (glyph, glyph_length).as<GlyphHeader> ();
-      if (!glyph_header.has_data ()) return true;
+      const GlyphHeader &header;
+      hb_bytes_t bytes;
+      SimpleGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
+	header (header_), bytes (bytes_) {}
 
-      const char *glyph_end = glyph + glyph_length;
-      if (glyph_header.is_composite_glyph ())
-	/* Trimming for composites not implemented.
-	 * If removing hints it falls out of that. */
-	return true;
-      else
+      unsigned int instruction_len_offset () const
+      { return GlyphHeader::static_size + 2 * header.numberOfContours; }
+
+      unsigned int length (unsigned int instruction_len) const
+      { return instruction_len_offset () + 2 + instruction_len; }
+
+      unsigned int instructions_length () const
       {
+	unsigned int instruction_length_offset = instruction_len_offset ();
+	if (unlikely (instruction_length_offset + 2 > bytes.length)) return 0;
+
+	const HBUINT16 &instructionLength = StructAtOffset<HBUINT16> (&bytes, instruction_length_offset);
+	/* Out of bounds of the current glyph */
+	if (unlikely (length (instructionLength) > bytes.length)) return 0;
+	return instructionLength;
+      }
+
+      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_RESERVED1 = 0x40,
+	FLAG_RESERVED2 = 0x80
+      };
+
+      const Glyph trim_padding () const
+      {
+	/* based on FontTools _g_l_y_f.py::trim */
+	const char *glyph = bytes.arrayZ;
+	const char *glyph_end = glyph + bytes.length;
 	/* simple glyph w/contours, possibly trimmable */
-	glyph += glyph_header.simple_instruction_len_offset ();
+	glyph += instruction_len_offset ();
 
-	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);
+	if (unlikely (glyph + 2 >= glyph_end)) return Glyph ();
+	unsigned int num_coordinates = StructAtOffset<HBUINT16> (glyph - 2, 0) + 1;
+	unsigned int num_instructions = StructAtOffset<HBUINT16> (glyph, 0);
 
-	glyph += 2 + nInstructions;
-	if (unlikely (glyph + 2 >= glyph_end)) return false;
+	glyph += 2 + num_instructions;
+	if (unlikely (glyph + 2 >= glyph_end)) return Glyph ();
 
-	unsigned int coordBytes = 0;
-	unsigned int coordsWithFlags = 0;
+	unsigned int coord_bytes = 0;
+	unsigned int coords_with_flags = 0;
 	while (glyph < glyph_end)
 	{
-	  uint8_t flag = (uint8_t) *glyph;
+	  uint8_t flag = *glyph;
 	  glyph++;
 
 	  unsigned int repeat = 1;
 	  if (flag & FLAG_REPEAT)
 	  {
-	    if (glyph >= glyph_end)
-	    {
-	      DEBUG_MSG (SUBSET, nullptr, "Bad flag");
-	      return false;
-	    }
-	    repeat = ((uint8_t) *glyph) + 1;
+	    if (unlikely (glyph >= glyph_end)) return Glyph ();
+	    repeat = *glyph + 1;
 	    glyph++;
 	  }
 
@@ -510,148 +496,561 @@
 	  if (flag & FLAG_Y_SHORT) yBytes = 1;
 	  else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2;
 
-	  coordBytes += (xBytes + yBytes) * repeat;
-	  coordsWithFlags += repeat;
-	  if (coordsWithFlags >= nCoordinates)
-	    break;
+	  coord_bytes += (xBytes + yBytes) * repeat;
+	  coords_with_flags += repeat;
+	  if (coords_with_flags >= num_coordinates) break;
 	}
 
-	if (coordsWithFlags != nCoordinates)
+	if (unlikely (coords_with_flags != num_coordinates)) return Glyph ();
+	return Glyph (bytes.sub_array (0, bytes.length + coord_bytes - (glyph_end - glyph)));
+      }
+
+      /* zero instruction length */
+      void drop_hints ()
+      {
+	GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
+	(HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
+      }
+
+      void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
+      {
+	unsigned int instructions_len = instructions_length ();
+	unsigned int glyph_length = length (instructions_len);
+	dest_start = bytes.sub_array (0, glyph_length - instructions_len);
+	dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length);
+      }
+
+      struct x_setter_t
+      {
+	void set (contour_point_t &point, float v) const { point.x = v; }
+	bool is_short (uint8_t flag) const { return flag & FLAG_X_SHORT; }
+	bool is_same  (uint8_t flag) const { return flag & FLAG_X_SAME; }
+      };
+
+      struct y_setter_t
+      {
+	void set (contour_point_t &point, float v) const { point.y = v; }
+	bool is_short (uint8_t flag) const { return flag & FLAG_Y_SHORT; }
+	bool is_same  (uint8_t flag) const { return flag & FLAG_Y_SAME; }
+      };
+
+      template <typename T>
+      static bool read_points (const HBUINT8 *&p /* IN/OUT */,
+			       contour_point_vector_t &points_ /* IN/OUT */,
+			       const range_checker_t &checker)
+      {
+	T coord_setter;
+	float v = 0;
+	for (unsigned int i = 0; i < points_.length - PHANTOM_COUNT; i++)
 	{
-	  DEBUG_MSG (SUBSET, nullptr, "Expect %d coords to have flags, got flags for %d",
-		     nCoordinates, coordsWithFlags);
-	  return false;
+	  uint8_t flag = points_[i].flag;
+	  if (coord_setter.is_short (flag))
+	  {
+	    if (unlikely (!checker.in_range (p))) return false;
+	    if (coord_setter.is_same (flag))
+	      v += *p++;
+	    else
+	      v -= *p++;
+	  }
+	  else
+	  {
+	    if (!coord_setter.is_same (flag))
+	    {
+	      if (unlikely (!checker.in_range ((const HBUINT16 *) p))) return false;
+	      v += *(const HBINT16 *) p;
+	      p += HBINT16::static_size;
+	    }
+	  }
+	  coord_setter.set (points_[i], v);
 	}
-	glyph += coordBytes;
+	return true;
+      }
 
-	if (glyph < glyph_end)
-	  *end_offset -= glyph_end - glyph;
+      bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
+			       hb_vector_t<unsigned int> &end_points_ /* OUT */,
+			       const bool phantom_only=false) const
+      {
+	const HBUINT16 *endPtsOfContours = &StructAfter<HBUINT16> (header);
+	range_checker_t checker (bytes.arrayZ, bytes.length);
+	int num_contours = header.numberOfContours;
+	if (unlikely (!checker.in_range (&endPtsOfContours[num_contours + 1]))) return false;
+	unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
+
+	points_.resize (num_points + PHANTOM_COUNT);
+	for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
+	if (phantom_only) return true;
+
+	/* Read simple glyph points if !phantom_only */
+	end_points_.resize (num_contours);
+
+	for (int i = 0; i < num_contours; i++)
+	  end_points_[i] = endPtsOfContours[i];
+
+	/* Skip instructions */
+	const HBUINT8 *p = &StructAtOffset<HBUINT8> (&endPtsOfContours[num_contours + 1],
+						     endPtsOfContours[num_contours]);
+
+	/* Read flags */
+	for (unsigned int i = 0; i < num_points; i++)
+	{
+	  if (unlikely (!checker.in_range (p))) return false;
+	  uint8_t flag = *p++;
+	  points_[i].flag = flag;
+	  if (flag & FLAG_REPEAT)
+	  {
+	    if (unlikely (!checker.in_range (p))) return false;
+	    unsigned int repeat_count = *p++;
+	    while ((repeat_count-- > 0) && (++i < num_points))
+	      points_[i].flag = flag;
+	  }
+	}
+
+	/* Read x & y coordinates */
+	return (read_points<x_setter_t> (p, points_, checker) &&
+		read_points<y_setter_t> (p, points_, checker));
       }
-      return true;
-    }
+    };
 
-    bool get_offsets (hb_codepoint_t  glyph,
-		      unsigned int   *start_offset /* OUT */,
-		      unsigned int   *end_offset   /* OUT */) const
+    struct CompositeGlyph
     {
-      if (unlikely (glyph >= num_glyphs))
-	return false;
+      const GlyphHeader &header;
+      hb_bytes_t bytes;
+      CompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
+	header (header_), bytes (bytes_) {}
 
-      if (short_offset)
+      composite_iter_t get_iterator () const
+      { return composite_iter_t (bytes, &StructAfter<CompositeGlyphChain, GlyphHeader> (header)); }
+
+      unsigned int instructions_length (hb_bytes_t bytes) const
       {
-	const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
-	*start_offset = 2 * offsets[glyph];
-	*end_offset   = 2 * offsets[glyph + 1];
+	unsigned int start = bytes.length;
+	unsigned int end = bytes.length;
+	const CompositeGlyphChain *last = nullptr;
+	for (auto &item : get_iterator ())
+	  last = &item;
+	if (unlikely (!last)) return 0;
+
+	if ((uint16_t) last->flags & CompositeGlyphChain::WE_HAVE_INSTRUCTIONS)
+	  start = (char *) last - &bytes + last->get_size ();
+	if (unlikely (start > end)) return 0;
+	return end - start;
       }
-      else
+
+      /* Trimming for composites not implemented.
+       * If removing hints it falls out of that. */
+      const Glyph trim_padding () const { return Glyph (bytes); }
+
+      /* remove WE_HAVE_INSTRUCTIONS flag from composite glyph */
+      void drop_hints ()
       {
-	const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
+	for (const auto &_ : get_iterator ())
+	  *const_cast<OT::HBUINT16 *> (&_.flags) = (uint16_t) _.flags & ~OT::glyf::CompositeGlyphChain::WE_HAVE_INSTRUCTIONS;
+      }
 
-	*start_offset = offsets[glyph];
-	*end_offset   = offsets[glyph + 1];
+      /* Chop instructions off the end */
+      void drop_hints_bytes (hb_bytes_t &dest_start) const
+      { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
+
+      bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
+			       hb_vector_t<unsigned int> &end_points_ /* OUT */,
+			       const bool phantom_only=false) const
+      {
+	/* add one pseudo point for each component in composite glyph */
+	unsigned int num_points = hb_len (get_iterator ());
+	points_.resize (num_points + PHANTOM_COUNT);
+	for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
+	return true;
       }
+    };
 
-      if (*start_offset > *end_offset || *end_offset > glyf_table.get_length ())
-	return false;
+    enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
 
-      return true;
+    enum phantom_point_index_t
+    {
+      PHANTOM_LEFT   = 0,
+      PHANTOM_RIGHT  = 1,
+      PHANTOM_TOP    = 2,
+      PHANTOM_BOTTOM = 3,
+      PHANTOM_COUNT  = 4
+    };
+
+    public:
+    composite_iter_t get_composite_iterator () const
+    {
+      if (type != COMPOSITE) return composite_iter_t ();
+      return CompositeGlyph (*header, bytes).get_iterator ();
     }
 
-    bool get_instruction_length (hb_bytes_t glyph,
-				 unsigned int * length /* OUT */) const
+    const Glyph trim_padding () const
     {
-      const GlyphHeader &glyph_header = *glyph.as<GlyphHeader> ();
-      /* Empty glyph; no instructions. */
-      if (!glyph_header.has_data ())
+      switch (type) {
+      case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
+      case SIMPLE:    return SimpleGlyph (*header, bytes).trim_padding ();
+      default:        return bytes;
+      }
+    }
+
+    void drop_hints ()
+    {
+      switch (type) {
+      case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
+      case SIMPLE:    SimpleGlyph (*header, bytes).drop_hints (); return;
+      default:        return;
+      }
+    }
+
+    void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
+    {
+      switch (type) {
+      case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
+      case SIMPLE:    SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
+      default:        return;
+      }
+    }
+
+    /* for a simple glyph, return contour end points, flags, along with coordinate points
+     * for a composite glyph, return pseudo component points
+     * in both cases points trailed with four phantom points
+     */
+    bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
+			     hb_vector_t<unsigned int> &end_points_ /* OUT */,
+			     const bool phantom_only=false) const
+    {
+      switch (type) {
+      case COMPOSITE: return CompositeGlyph (*header, bytes).get_contour_points (points_, end_points_, phantom_only);
+      case SIMPLE:    return SimpleGlyph (*header, bytes).get_contour_points (points_, end_points_, phantom_only);
+      default:
+	/* empty glyph */
+	points_.resize (PHANTOM_COUNT);
+	for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
+	return true;
+      }
+    }
+
+    bool is_simple_glyph ()    const { return type == SIMPLE; }
+    bool is_composite_glyph () const { return type == COMPOSITE; }
+
+    bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
+    {
+      if (type == EMPTY) return true; /* Empty glyph; zero extents. */
+      return header->get_extents (font, gid, extents);
+    }
+
+    hb_bytes_t get_bytes ()          const { return bytes; }
+    const GlyphHeader &get_header () const { return *header; }
+
+    Glyph (hb_bytes_t bytes_ = hb_bytes_t ()) :
+      bytes (bytes_), header (bytes.as<GlyphHeader> ())
+    {
+      int num_contours = header->numberOfContours;
+      if (unlikely (num_contours == 0)) type = EMPTY;
+      else if (num_contours > 0) type = SIMPLE;
+      else type = COMPOSITE; /* negative numbers */
+    }
+
+    protected:
+    hb_bytes_t bytes;
+    const GlyphHeader *header;
+    unsigned type;
+  };
+
+  struct accelerator_t
+  {
+    void init (hb_face_t *face_)
+    {
+      short_offset = false;
+      num_glyphs = 0;
+      loca_table = nullptr;
+      glyf_table = nullptr;
+      face = face_;
+      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.indexToLocFormat;
+
+      loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
+      glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
+
+      num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
+    }
+
+    void fini ()
+    {
+      loca_table.destroy ();
+      glyf_table.destroy ();
+    }
+
+    enum phantom_point_index_t
+    {
+      PHANTOM_LEFT   = 0,
+      PHANTOM_RIGHT  = 1,
+      PHANTOM_TOP    = 2,
+      PHANTOM_BOTTOM = 3,
+      PHANTOM_COUNT  = 4
+    };
+
+    protected:
+
+    void init_phantom_points (hb_codepoint_t gid, hb_array_t<contour_point_t> &phantoms /* IN/OUT */) const
+    {
+      const Glyph &glyph = glyph_for_gid (gid);
+      int h_delta = (int) glyph.get_header ().xMin - face->table.hmtx->get_side_bearing (gid);
+      int v_orig  = (int) glyph.get_header ().yMax + face->table.vmtx->get_side_bearing (gid);
+      unsigned int h_adv = face->table.hmtx->get_advance (gid);
+      unsigned int v_adv = face->table.vmtx->get_advance (gid);
+
+      phantoms[PHANTOM_LEFT].x = h_delta;
+      phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
+      phantoms[PHANTOM_TOP].y = v_orig;
+      phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
+    }
+
+    struct contour_bounds_t
+    {
+      contour_bounds_t () { min.x = min.y = FLT_MAX; max.x = max.y = -FLT_MAX; }
+
+      void add (const contour_point_t &p)
       {
-	*length = 0;
-	// only 0 byte glyphs are healthy when missing GlyphHeader
-	return glyph.length == 0;
+	min.x = hb_min (min.x, p.x);
+	min.y = hb_min (min.y, p.y);
+	max.x = hb_max (max.x, p.x);
+	max.y = hb_max (max.y, p.y);
       }
-      if (glyph_header.is_composite_glyph ())
+
+      bool empty () const { return (min.x >= max.x) || (min.y >= max.y); }
+
+      contour_point_t	min;
+      contour_point_t	max;
+    };
+
+#ifndef HB_NO_VAR
+    /* Note: Recursively calls itself.
+     * all_points includes phantom points
+     */
+    bool get_points_var (hb_codepoint_t gid,
+			 const int *coords, unsigned int coord_count,
+			 contour_point_vector_t &all_points /* OUT */,
+			 unsigned int depth = 0) const
+    {
+      if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return false;
+      contour_point_vector_t points;
+      hb_vector_t<unsigned int> end_points;
+      const Glyph &glyph = glyph_for_gid (gid);
+      if (unlikely (!glyph.get_contour_points (points, end_points))) return false;
+      hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
+      init_phantom_points (gid, phantoms);
+      if (unlikely (!face->table.gvar->apply_deltas_to_points (gid, coords, coord_count, points.as_array (), end_points.as_array ()))) return false;
+
+      unsigned int comp_index = 0;
+      if (glyph.is_simple_glyph ())
+	all_points.extend (points.as_array ());
+      else if (glyph.is_composite_glyph ())
       {
-	unsigned int start = glyph.length;
-	unsigned int end = glyph.length;
-	unsigned int glyph_offset = &glyph - glyf_table;
-	CompositeGlyphHeader::Iterator composite_it;
-	if (unlikely (!CompositeGlyphHeader::get_iterator (&glyph, glyph.length,
-							   &composite_it)))
-	  return false;
-	const CompositeGlyphHeader *last;
-	do
+	for (auto &item : glyph.get_composite_iterator ())
 	{
-	  last = composite_it.current;
-	} while (composite_it.move_to_next ());
+	  contour_point_vector_t comp_points;
+	  if (unlikely (!get_points_var (item.glyphIndex, coords, coord_count,
+					 comp_points, depth))
+			|| comp_points.length < PHANTOM_COUNT)
+	    return false;
 
-	if ((uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
-	  start = ((char *) last - (char *) glyf_table->dataZ.arrayZ)
-		+ last->get_size () - glyph_offset;
-	if (unlikely (start > end))
-	{
-	  DEBUG_MSG (SUBSET, nullptr, "Invalid instruction offset, %d is outside "
-				      "%d byte buffer", start, glyph.length);
-	  return false;
+	  /* Copy phantom points from component if USE_MY_METRICS flag set */
+	  if (item.is_use_my_metrics ())
+	    for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
+	      phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
+
+	  /* Apply component transformation & translation */
+	  item.transform_points (comp_points);
+
+	  /* Apply translatation from gvar */
+	  comp_points.translate (points[comp_index]);
+
+	  if (item.is_anchored ())
+	  {
+	    unsigned int p1, p2;
+	    item.get_anchor_points (p1, p2);
+	    if (likely (p1 < all_points.length && p2 < comp_points.length))
+	    {
+	      contour_point_t delta;
+	      delta.init (all_points[p1].x - comp_points[p2].x,
+			  all_points[p1].y - comp_points[p2].y);
+
+	      comp_points.translate (delta);
+	    }
+	  }
+
+	  all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
+
+	  comp_index++;
 	}
-	*length = end - start;
+
+	all_points.extend (phantoms);
       }
-      else
+      else return false;
+
+      return true;
+    }
+
+    bool get_points_bearing_applied (hb_font_t *font, hb_codepoint_t gid, contour_point_vector_t &all_points) const
+    {
+      if (unlikely (!get_points_var (gid, font->coords, font->num_coords, all_points) ||
+		    all_points.length < PHANTOM_COUNT)) return false;
+
+      /* Undocumented rasterizer behavior:
+       * Shift points horizontally by the updated left side bearing
+       */
+      contour_point_t delta;
+      delta.init (-all_points[all_points.length - PHANTOM_COUNT + PHANTOM_LEFT].x, 0.f);
+      if (delta.x) all_points.translate (delta);
+      return true;
+    }
+
+    protected:
+
+    bool get_var_extents_and_phantoms (hb_font_t *font, hb_codepoint_t gid,
+				       hb_glyph_extents_t *extents=nullptr /* OUT */,
+				       contour_point_vector_t *phantoms=nullptr /* OUT */) const
+    {
+      contour_point_vector_t all_points;
+      if (!unlikely (get_points_bearing_applied (font, gid, all_points))) return false;
+      if (extents)
       {
-	unsigned int instruction_len_offset = glyph_header.simple_instruction_len_offset ();
-	if (unlikely (instruction_len_offset + 2 > glyph.length))
+	contour_bounds_t bounds;
+	for (unsigned int i = 0; i + PHANTOM_COUNT < all_points.length; i++)
+	  bounds.add (all_points[i]);
+
+	if (bounds.min.x > bounds.max.x)
 	{
-	  DEBUG_MSG (SUBSET, nullptr, "Glyph size is too short, missing field "
-				      "instructionLength.");
-	  return false;
+	  extents->width = 0;
+	  extents->x_bearing = 0;
 	}
-
-	const HBUINT16 &instruction_len = StructAtOffset<HBUINT16> (&glyph,
-								    instruction_len_offset);
-	/* Out of bounds of the current glyph */
-	if (unlikely (glyph_header.simple_length (instruction_len) > glyph.length))
+	else
 	{
-	  DEBUG_MSG (SUBSET, nullptr, "The instructions array overruns the "
-				      "glyph's boundaries.");
-	  return false;
+	  extents->x_bearing = font->em_scalef_x (bounds.min.x);
+	  extents->width = font->em_scalef_x (bounds.max.x - bounds.min.x);
 	}
-	*length = (uint16_t) instruction_len;
+	if (bounds.min.y > bounds.max.y)
+	{
+	  extents->height = 0;
+	  extents->y_bearing = 0;
+	}
+	else
+	{
+	  extents->y_bearing = font->em_scalef_y (bounds.max.y);
+	  extents->height = font->em_scalef_y (bounds.min.y - bounds.max.y);
+	}
       }
+      if (phantoms)
+	for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
+	  (*phantoms)[i] = all_points[all_points.length - PHANTOM_COUNT + i];
       return true;
     }
 
-    bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+    bool get_var_metrics (hb_font_t *font, hb_codepoint_t gid,
+			  contour_point_vector_t &phantoms) const
+    { return get_var_extents_and_phantoms (font, gid, nullptr, &phantoms); }
+
+    bool get_extents_var (hb_font_t *font, hb_codepoint_t gid,
+			  hb_glyph_extents_t *extents) const
+    { return get_var_extents_and_phantoms (font, gid,  extents); }
+#endif
+
+    public:
+#ifndef HB_NO_VAR
+    unsigned int get_advance_var (hb_font_t *font, hb_codepoint_t gid,
+				  bool is_vertical) const
     {
-      unsigned int start_offset, end_offset;
-      if (!get_offsets (glyph, &start_offset, &end_offset))
-	return false;
+      bool success = false;
+      contour_point_vector_t phantoms;
+      phantoms.resize (PHANTOM_COUNT);
 
-      hb_bytes_t ((const char *) glyf_table + start_offset,
-		  end_offset - start_offset).as<GlyphHeader> ()->get_extents (extents);
-      return true;
+      if (likely (font->num_coords == face->table.gvar->get_axis_count ()))
+	success = get_var_metrics (font, gid, phantoms);
+
+      if (unlikely (!success))
+	return is_vertical ? face->table.vmtx->get_advance (gid) : face->table.hmtx->get_advance (gid);
+
+      if (is_vertical)
+	return roundf (phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y);
+      else
+	return roundf (phantoms[PHANTOM_RIGHT].x - phantoms[PHANTOM_LEFT].x);
     }
 
-    hb_bytes_t bytes_for_glyph (const char *glyf, hb_codepoint_t gid)
+    int get_side_bearing_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
     {
+      hb_glyph_extents_t extents;
+      contour_point_vector_t phantoms;
+      phantoms.resize (PHANTOM_COUNT);
+
+      if (unlikely (!get_var_extents_and_phantoms (font, gid, &extents, &phantoms)))
+	return is_vertical ? face->table.vmtx->get_side_bearing (gid) : face->table.hmtx->get_side_bearing (gid);
+
+      return is_vertical ? ceil (phantoms[PHANTOM_TOP].y) - extents.y_bearing : floor (phantoms[PHANTOM_LEFT].x);
+    }
+#endif
+
+    bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
+    {
+#ifndef HB_NO_VAR
+      unsigned int coord_count;
+      const int *coords = hb_font_get_var_coords_normalized (font, &coord_count);
+      if (coords && coord_count > 0 && coord_count == face->table.gvar->get_axis_count ())
+	return get_extents_var (font, gid, extents);
+#endif
+
+      if (unlikely (gid >= num_glyphs)) return false;
+
+      return glyph_for_gid (gid).get_extents (font, gid, extents);
+    }
+
+    const Glyph
+    glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
+    {
       unsigned int start_offset, end_offset;
-      if (unlikely (!(get_offsets (gid, &start_offset, &end_offset) &&
-		      remove_padding (start_offset, &end_offset))))
+      if (unlikely (gid >= num_glyphs)) return Glyph ();
+
+      if (short_offset)
       {
-	DEBUG_MSG (SUBSET, nullptr, "Unable to get offset or remove padding for %d", gid);
-	return hb_bytes_t ();
+	const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
+	start_offset = 2 * offsets[gid];
+	end_offset   = 2 * offsets[gid + 1];
       }
-      hb_bytes_t glyph_bytes = hb_bytes_t (glyf + start_offset, end_offset - start_offset);
-      if (!glyph_bytes.as<GlyphHeader> ()->has_data ())
+      else
       {
-	DEBUG_MSG (SUBSET, nullptr, "Empty or invalid glyph size, %d", gid);
-	return hb_bytes_t ();
+	const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
+	start_offset = offsets[gid];
+	end_offset   = offsets[gid + 1];
       }
-      return glyph_bytes;
+
+      if (unlikely (start_offset > end_offset || end_offset > glyf_table.get_length ()))
+	return Glyph ();
+
+      Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
+			       end_offset - start_offset));
+      return needs_padding_removal ? glyph.trim_padding () : glyph;
     }
 
+    void
+    add_gid_and_children (hb_codepoint_t gid, hb_set_t *gids_to_retain,
+			  unsigned int depth = 0) const
+    {
+      if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return;
+      /* Check if is already visited */
+      if (gids_to_retain->has (gid)) return;
+
+      gids_to_retain->add (gid);
+
+      for (auto &item : glyph_for_gid (gid).get_composite_iterator ())
+        add_gid_and_children (item.glyphIndex, gids_to_retain, depth);
+    }
+
     private:
     bool short_offset;
     unsigned int num_glyphs;
     hb_blob_ptr_t<loca> loca_table;
     hb_blob_ptr_t<glyf> glyf_table;
+    hb_face_t *face;
   };
 
   struct SubsetGlyph
@@ -658,7 +1057,7 @@
   {
     hb_codepoint_t new_gid;
     hb_codepoint_t old_gid;
-    hb_bytes_t source_glyph;
+    Glyph source_glyph;
     hb_bytes_t dest_start;  /* region of source_glyph to copy first */
     hb_bytes_t dest_end;    /* region of source_glyph to copy second */
 
@@ -670,8 +1069,7 @@
       hb_bytes_t dest_glyph = dest_start.copy (c);
       dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
       unsigned int pad_length = padding ();
-      DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d",
-		 dest_glyph.length, dest_glyph.length  + pad_length, pad_length);
+      DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length  + pad_length, pad_length);
 
       HBUINT8 pad;
       pad = 0;
@@ -681,56 +1079,27 @@
 	pad_length--;
       }
 
-      if (dest_glyph.length)
+      if (!unlikely (dest_glyph.length)) return_trace (true);
+
+      /* update components gids */
+      for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
       {
-	_fix_component_gids (plan, dest_glyph);
-	if (plan->drop_hints)
-	{
-	  _zero_instruction_length (dest_glyph);
-	  c->check_success (_remove_composite_instruction_flag (dest_glyph));
-	}
+	hb_codepoint_t new_gid;
+	if (plan->new_gid_for_old_gid (_.glyphIndex, &new_gid))
+	  ((OT::glyf::CompositeGlyphChain *) &_)->glyphIndex = new_gid;
       }
 
+      if (plan->drop_hints) Glyph (dest_glyph).drop_hints ();
+
       return_trace (true);
     }
 
-    void drop_hints (const OT::glyf::accelerator_t& glyf)
-    {
-      if (source_glyph.length == 0) return;
+    void drop_hints_bytes ()
+    { source_glyph.drop_hints_bytes (dest_start, dest_end); }
 
-      unsigned int instruction_len = 0;
-      if (!glyf.get_instruction_length (source_glyph, &instruction_len))
-      {
-	DEBUG_MSG (SUBSET, nullptr, "Unable to read instruction length for new_gid %d",
-		   new_gid);
-	return ;
-      }
-
-      const GlyphHeader& header = *source_glyph.as<GlyphHeader> ();
-      DEBUG_MSG (SUBSET, nullptr, "new_gid %d drop %d instruction bytes "
-				  "from %d byte source glyph",
-		 new_gid, instruction_len, source_glyph.length);
-      if (header.is_composite_glyph ())
-      {
-	/* just chop instructions off the end for composite glyphs */
-	dest_start = hb_bytes_t (&source_glyph, source_glyph.length - instruction_len);
-      }
-      else
-      {
-	unsigned int glyph_length = header.simple_length (instruction_len);
-	dest_start = hb_bytes_t (&source_glyph, glyph_length - instruction_len);
-	dest_end = hb_bytes_t (&source_glyph + glyph_length,
-			       source_glyph.length - glyph_length);
-	DEBUG_MSG (SUBSET, nullptr, "source_len %d start len %d glyph_len %d "
-				    "instruction_len %d end len %d",
-		   source_glyph.length, dest_start.length, glyph_length,
-		   instruction_len, dest_end.length);
-      }
-    }
-
-    unsigned int length () const      { return dest_start.length + dest_end.length; }
+    unsigned int      length () const { return dest_start.length + dest_end.length; }
     /* pad to 2 to ensure 2-byte loca will be ok */
-    unsigned int padding () const     { return length () % 2; }
+    unsigned int     padding () const { return length () % 2; }
     unsigned int padded_size () const { return length () + padding (); }
   };
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -42,6 +42,13 @@
 #define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
 
 
+HB_INTERNAL int
+_glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
+
+HB_INTERNAL unsigned
+_glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
+
+
 namespace OT {
 
 
@@ -53,6 +60,7 @@
   DEFINE_SIZE_STATIC (4);
 };
 
+
 template <typename T, typename H>
 struct hmtxvmtx
 {
@@ -128,13 +136,12 @@
     auto it =
     + hb_range (c->plan->num_output_glyphs ())
     | hb_map ([c, &_mtx] (unsigned _)
-	{
-	  hb_codepoint_t old_gid;
-	  if (c->plan->old_gid_for_new_gid (_, &old_gid))
-	    return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid));
-	  else
-	    return hb_pair (0u, 0u);
-	})
+	      {
+		hb_codepoint_t old_gid;
+		if (!c->plan->old_gid_for_new_gid (_, &old_gid))
+		  return hb_pair (0u, 0);
+		return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid));
+	      })
     ;
 
     table_prime->serialize (c->serializer, it, num_advances);
@@ -146,9 +153,7 @@
 
     // Amend header num hmetrics
     if (unlikely (!subset_update_header (c->plan, num_advances)))
-    {
       return_trace (false);
-    }
 
     return_trace (true);
   }
@@ -190,8 +195,7 @@
       var_table.destroy ();
     }
 
-    /* TODO Add variations version. */
-    unsigned int get_side_bearing (hb_codepoint_t glyph) const
+    int get_side_bearing (hb_codepoint_t glyph) const
     {
       if (glyph < num_advances)
 	return table->longMetricZ[glyph].sb;
@@ -203,6 +207,23 @@
       return bearings[glyph - num_advances];
     }
 
+    int get_side_bearing (hb_font_t *font, hb_codepoint_t glyph) const
+    {
+      int side_bearing = get_side_bearing (glyph);
+
+#ifndef HB_NO_VAR
+      if (unlikely (glyph >= num_metrics) || !font->num_coords)
+	return side_bearing;
+
+      if (var_table.get_length ())
+        return side_bearing + var_table->get_side_bearing_var (glyph, font->coords, font->num_coords); // TODO Optimize?!
+
+      return _glyf_get_side_bearing_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
+#else
+      return side_bearing;
+#endif
+    }
+
     unsigned int get_advance (hb_codepoint_t glyph) const
     {
       if (unlikely (glyph >= num_metrics))
@@ -223,11 +244,18 @@
 			      hb_font_t      *font) const
     {
       unsigned int advance = get_advance (glyph);
-      if (likely (glyph < num_metrics))
-      {
-	advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?!
-      }
+
+#ifndef HB_NO_VAR
+      if (unlikely (glyph >= num_metrics) || !font->num_coords)
+	return advance;
+
+      if (var_table.get_length ())
+	return advance + roundf (var_table->get_advance_var (font, glyph)); // TODO Optimize?!
+
+      return _glyf_get_advance_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
+#else
       return advance;
+#endif
     }
 
     unsigned int num_advances_for_subset (const hb_subset_plan_t *plan) const

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-kern-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-kern-table.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-kern-table.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -167,8 +167,8 @@
   static constexpr bool apple = false;
   typedef AAT::ObsoleteTypes Types;
 
-  unsigned int tuple_count () const { return 0; }
-  bool is_horizontal () const { return (coverage & Horizontal); }
+  unsigned   tuple_count () const { return 0; }
+  bool     is_horizontal () const { return (coverage & Horizontal); }
 
   enum Coverage
   {
@@ -222,8 +222,8 @@
   static constexpr bool apple = true;
   typedef AAT::ObsoleteTypes Types;
 
-  unsigned int tuple_count () const { return 0; }
-  bool is_horizontal () const       { return !(coverage & Vertical); }
+  unsigned   tuple_count () const { return 0; }
+  bool     is_horizontal () const { return !(coverage & Vertical); }
 
   enum Coverage
   {
@@ -275,8 +275,8 @@
 {
   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_data () const { return u.version32; }
+  unsigned get_type () const { return u.major; }
 
   bool has_state_machine () const
   {

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -33,6 +33,7 @@
 #include "hb-ot-layout.hh"
 #include "hb-open-type.hh"
 #include "hb-set.hh"
+#include "hb-bimap.hh"
 
 
 #ifndef HB_MAX_NESTING_LEVEL
@@ -66,7 +67,77 @@
 #define NOT_COVERED		((unsigned int) -1)
 
 
+template<typename Iterator>
+static inline void Coverage_serialize (hb_serialize_context_t *c,
+				       Iterator it);
+
+template<typename Iterator>
+static inline void ClassDef_serialize (hb_serialize_context_t *c,
+                                       Iterator it);
+
+static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
+                                          const hb_set_t &glyphset,
+                                          const hb_map_t &gid_klass_map,
+                                          hb_sorted_vector_t<HBGlyphID> glyphs,
+                                          hb_sorted_vector_t<unsigned> klasses,
+                                          hb_map_t *klass_map /*INOUT*/);
+
+
+template<typename OutputArray>
+struct subset_offset_array_t
+{
+  subset_offset_array_t
+  (hb_subset_context_t *subset_context,
+   OutputArray& out,
+   const void *src_base,
+   const void *dest_base)
+      : _subset_context(subset_context), _out (out), _src_base (src_base), _dest_base (dest_base) {}
+
+  template <typename T>
+  bool
+  operator ()
+  (T&& offset)
+  {
+    auto *o = _out.serialize_append (_subset_context->serializer);
+    if (unlikely (!o)) return false;
+    auto snap = _subset_context->serializer->snapshot ();
+    bool ret = o->serialize_subset (_subset_context, offset, _src_base, _dest_base);
+    if (!ret)
+    {
+      _out.pop ();
+      _subset_context->serializer->revert (snap);
+    }
+    return ret;
+  }
+
+  private:
+  hb_subset_context_t *_subset_context;
+  OutputArray &_out;
+  const void *_src_base;
+  const void *_dest_base;
+};
+
 /*
+ * Helper to subset an array of offsets. Subsets the thing pointed to by each offset
+ * and discards the offset in the array if the subset operation results in an empty
+ * thing.
+ */
+struct
+{
+  template<typename OutputArray>
+  subset_offset_array_t<OutputArray>
+  operator ()
+  (hb_subset_context_t *subset_context,
+   OutputArray& out,
+   const void *src_base,
+   const void *dest_base) const
+  {
+    return subset_offset_array_t<OutputArray> (subset_context, out, src_base, dest_base);
+  }
+}
+HB_FUNCOBJ (subset_offset_array);
+
+/*
  *
  * OpenType Layout Common Table Formats
  *
@@ -82,6 +153,26 @@
   const void *list_base;
 };
 
+struct RecordList_subset_context_t {
+
+  RecordList_subset_context_t() : script_count (0), langsys_count (0)
+  {}
+
+  bool visitScript ()
+  {
+    return script_count++ < HB_MAX_SCRIPTS;
+  }
+
+  bool visitLangSys ()
+  {
+    return langsys_count++ < HB_MAX_LANGSYS;
+  }
+
+  private:
+  unsigned int script_count;
+  unsigned int langsys_count;
+};
+
 template <typename Type>
 struct Record
 {
@@ -138,11 +229,26 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    auto *out = c->serializer->embed (*this);
-    if (unlikely (!out)) return_trace (false);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+    RecordList_subset_context_t record_list_context;
+
     unsigned int count = this->len;
     for (unsigned int i = 0; i < count; i++)
-      out->get_offset (i).serialize_subset (c, this->get_offset (i), this, out);
+    {
+      auto *record = out->serialize_append (c->serializer);
+      if (unlikely (!record)) return false;
+      auto snap = c->serializer->snapshot ();
+      if (record->offset.serialize_subset (c, this->get_offset (i), this, out, &record_list_context))
+      {
+        record->tag = this->get_tag(i);
+        continue;
+      }
+      out->pop ();
+      c->serializer->revert (snap);
+    }
+
     return_trace (true);
   }
 
@@ -207,7 +313,6 @@
 struct LangSys;
 struct Feature;
 
-
 struct LangSys
 {
   unsigned int get_feature_count () const
@@ -274,15 +379,33 @@
   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
+  bool subset (hb_subset_context_t *c, RecordList_subset_context_t *record_list_context) const
   {
     TRACE_SUBSET (this);
-    auto *out = c->serializer->embed (*this);
-    if (unlikely (!out)) return_trace (false);
+    if (!record_list_context->visitScript ()) return_trace (false);
+
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
     out->defaultLangSys.serialize_copy (c->serializer, defaultLangSys, this, out);
-    unsigned int count = langSys.len;
-    for (unsigned int i = 0; i < count; i++)
-      out->langSys.arrayZ[i].offset.serialize_copy (c->serializer, langSys[i].offset, this, out);
+
+    for (const auto &src: langSys)
+    {
+      if (!record_list_context->visitLangSys ()) {
+        continue;
+      }
+
+      auto snap = c->serializer->snapshot ();
+      auto *lang_sys = c->serializer->embed (src);
+
+      if (likely(lang_sys)
+          && lang_sys->offset.serialize_copy (c->serializer, src.offset, this, out))
+      {
+        out->langSys.len++;
+        continue;
+      }
+      c->serializer->revert (snap);
+    }
     return_trace (true);
   }
 
@@ -559,7 +682,7 @@
   const FeatureParams &get_feature_params () const
   { return this+featureParams; }
 
-  bool subset (hb_subset_context_t *c) const
+  bool subset (hb_subset_context_t *c, RecordList_subset_context_t *r) const
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->embed (*this);
@@ -1072,6 +1195,23 @@
     }
   }
 
+  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;
+
+    auto it =
+    + iter ()
+    | hb_filter (glyphset)
+    | hb_map_retains_sorting (glyph_map)
+    ;
+
+    bool ret = bool (it);
+    Coverage_serialize (c->serializer, it);
+    return_trace (ret);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -1190,15 +1330,51 @@
   DEFINE_SIZE_UNION (2, format);
 };
 
+template<typename Iterator>
+static inline void
+Coverage_serialize (hb_serialize_context_t *c,
+                    Iterator it)
+{ c->start_embed<Coverage> ()->serialize (c, it); }
 
+static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
+                                          const hb_set_t &glyphset,
+                                          const hb_map_t &gid_klass_map,
+                                          hb_sorted_vector_t<HBGlyphID> glyphs,
+                                          hb_sorted_vector_t<unsigned> klasses,
+                                          hb_map_t *klass_map /*INOUT*/)
+{
+  bool has_no_match = glyphset.get_population () > gid_klass_map.get_population ();
+  
+  hb_map_t m;
+  if (!klass_map) klass_map = &m;
+
+  if (has_no_match) klass_map->set (0, 0);
+  unsigned idx = klass_map->has (0) ? 1 : 0;
+  for (const unsigned k: klasses.iter ())
+  {
+    if (klass_map->has (k)) continue;
+    klass_map->set (k, idx);
+    idx++;
+  }
+  
+  auto it =
+  + glyphs.iter ()
+  | hb_map_retains_sorting ([&] (const HBGlyphID& gid) -> hb_pair_t<hb_codepoint_t, HBUINT16>
+                            {
+                              HBUINT16 new_klass;
+                              new_klass = klass_map->get (gid_klass_map[gid]);
+                              return hb_pair ((hb_codepoint_t)gid, new_klass);
+                            })
+  ;
+  
+  c->propagate_error (glyphs, klasses);
+  ClassDef_serialize (c, it);
+}
+
 /*
  * Class Definition Table
  */
 
-static inline void ClassDef_serialize (hb_serialize_context_t *c,
-				       hb_array_t<const HBGlyphID> glyphs,
-				       hb_array_t<const HBUINT16> klasses);
-
 struct ClassDefFormat1
 {
   friend struct ClassDef;
@@ -1209,14 +1385,15 @@
     return classValue[(unsigned int) (glyph_id - startGlyph)];
   }
 
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
   bool serialize (hb_serialize_context_t *c,
-		  hb_array_t<const HBGlyphID> glyphs,
-		  hb_array_t<const HBUINT16> klasses)
+                  Iterator it)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
 
-    if (unlikely (!glyphs))
+    if (unlikely (!it))
     {
       startGlyph = 0;
       classValue.len = 0;
@@ -1223,39 +1400,38 @@
       return_trace (true);
     }
 
-    hb_codepoint_t glyph_min = +glyphs | hb_reduce (hb_min, 0xFFFFu);
-    hb_codepoint_t glyph_max = +glyphs | hb_reduce (hb_max, 0u);
-
-    startGlyph = glyph_min;
-    c->check_assign (classValue.len, 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];
-
+    startGlyph = (*it).first;
+    classValue.serialize (c, + it
+                             | hb_map (hb_second));
     return_trace (true);
   }
 
-  bool subset (hb_subset_context_t *c) const
+  bool subset (hb_subset_context_t *c,
+               hb_map_t *klass_map = nullptr /*OUT*/) const
   {
     TRACE_SUBSET (this);
     const hb_set_t &glyphset = *c->plan->glyphset ();
     const hb_map_t &glyph_map = *c->plan->glyph_map;
+   
     hb_sorted_vector_t<HBGlyphID> glyphs;
-    hb_vector_t<HBUINT16> klasses;
+    hb_sorted_vector_t<unsigned> orig_klasses;
+    hb_map_t gid_org_klass_map;
 
     hb_codepoint_t start = startGlyph;
     hb_codepoint_t end   = start + classValue.len;
-    for (hb_codepoint_t g = start; g < end; g++)
+    for (const hb_codepoint_t gid : + hb_range (start, end)
+				    | hb_filter (glyphset))
     {
-      if (!glyphset.has (g)) continue;
-      unsigned int value = classValue[g - start];
-      if (!value) continue;
-      glyphs.push(glyph_map[g]);
-      klasses.push(value);
+      unsigned klass = classValue[gid - start];
+      if (!klass) continue;
+
+      glyphs.push (glyph_map[gid]);
+      gid_org_klass_map.set (glyph_map[gid], klass);
+      orig_klasses.push (klass);
     }
-    c->serializer->propagate_error (glyphs, klasses);
-    ClassDef_serialize (c->serializer, glyphs, klasses);
+
+    ClassDef_remap_and_serialize (c->serializer, glyphset, gid_org_klass_map,
+                                  glyphs, orig_klasses, klass_map);
     return_trace ((bool) glyphs);
   }
 
@@ -1345,59 +1521,76 @@
     return rangeRecord.bsearch (glyph_id).value;
   }
 
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
   bool serialize (hb_serialize_context_t *c,
-		  hb_array_t<const HBGlyphID> glyphs,
-		  hb_array_t<const HBUINT16> klasses)
+                  Iterator it)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
 
-    if (unlikely (!glyphs))
+    if (unlikely (!it))
     {
       rangeRecord.len = 0;
       return_trace (true);
     }
 
-    unsigned int count = glyphs.len ();
-    unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < count; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i] ||
-	  klasses[i - 1] != klasses[i])
-	num_ranges++;
-    rangeRecord.len = num_ranges;
-    if (unlikely (!c->extend (rangeRecord))) return_trace (false);
+    unsigned num_ranges = 1;
+    hb_codepoint_t prev_gid = (*it).first;
+    unsigned prev_klass = (*it).second;
 
-    unsigned int range = 0;
-    rangeRecord[range].start = glyphs[0];
-    rangeRecord[range].value = klasses[0];
-    for (unsigned int i = 1; i < count; i++)
+    RangeRecord range_rec;
+    range_rec.start = prev_gid;
+    range_rec.end = prev_gid;
+    range_rec.value = prev_klass;
+
+    RangeRecord *record = c->copy (range_rec);
+    if (unlikely (!record)) return_trace (false);
+
+    for (const auto gid_klass_pair : + (++it))
     {
-      if (glyphs[i - 1] + 1 != glyphs[i] ||
-	  klasses[i - 1] != klasses[i])
+      hb_codepoint_t cur_gid = gid_klass_pair.first;
+      unsigned cur_klass = gid_klass_pair.second;
+
+      if (cur_gid != prev_gid + 1 ||
+          cur_klass != prev_klass)
       {
-	rangeRecord[range].end = glyphs[i - 1];
-	range++;
-	rangeRecord[range].start = glyphs[i];
-	rangeRecord[range].value = klasses[i];
+        if (unlikely (!record)) break;
+        record->end = prev_gid;
+        num_ranges++;
+
+        range_rec.start = cur_gid;
+        range_rec.end = cur_gid;
+        range_rec.value = cur_klass;
+
+        record = c->copy (range_rec);
       }
+
+      prev_klass = cur_klass;
+      prev_gid = cur_gid;
     }
-    rangeRecord[range].end = glyphs[count - 1];
+
+    if (likely (record)) record->end = prev_gid;
+    rangeRecord.len = num_ranges;
     return_trace (true);
   }
 
-  bool subset (hb_subset_context_t *c) const
+  bool subset (hb_subset_context_t *c,
+               hb_map_t *klass_map = nullptr /*OUT*/) 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<HBGlyphID> glyphs;
-    hb_vector_t<HBUINT16> klasses;
 
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
+    hb_sorted_vector_t<HBGlyphID> glyphs;
+    hb_sorted_vector_t<unsigned> orig_klasses;
+    hb_map_t gid_org_klass_map;
+
+    unsigned count = rangeRecord.len;
+    for (unsigned i = 0; i < count; i++)
     {
-      unsigned int value = rangeRecord[i].value;
-      if (!value) continue;
+      unsigned klass = rangeRecord[i].value;
+      if (!klass) 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++)
@@ -1404,11 +1597,13 @@
       {
 	if (!glyphset.has (g)) continue;
 	glyphs.push (glyph_map[g]);
-	klasses.push (value);
+        gid_org_klass_map.set (glyph_map[g], klass);
+        orig_klasses.push (klass);
       }
     }
-    c->serializer->propagate_error (glyphs, klasses);
-    ClassDef_serialize (c->serializer, glyphs, klasses);
+
+    ClassDef_remap_and_serialize (c->serializer, glyphset, gid_org_klass_map,
+                                  glyphs, orig_klasses, klass_map);
     return_trace ((bool) glyphs);
   }
 
@@ -1505,26 +1700,37 @@
     }
   }
 
-  bool serialize (hb_serialize_context_t *c,
-		  hb_array_t<const HBGlyphID> glyphs,
-		  hb_array_t<const HBUINT16> klasses)
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  bool serialize (hb_serialize_context_t *c, Iterator it)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
 
-    unsigned int format = 2;
-    if (likely (glyphs))
+    unsigned format = 2;
+    if (likely (it))
     {
-      hb_codepoint_t glyph_min = +glyphs | hb_reduce (hb_min, 0xFFFFu);
-      hb_codepoint_t glyph_max = +glyphs | hb_reduce (hb_max, 0u);
+      hb_codepoint_t glyph_min = (*it).first;
+      hb_codepoint_t glyph_max = + it
+				 | hb_map (hb_first)
+                                 | hb_reduce (hb_max, 0u);
 
-      unsigned int count = glyphs.len ();
-      unsigned int num_ranges = 1;
-      for (unsigned int i = 1; i < count; i++)
-	if (glyphs[i - 1] + 1 != glyphs[i] ||
-	    klasses[i - 1] != klasses[i])
-	  num_ranges++;
+      unsigned num_ranges = 1;
+      hb_codepoint_t prev_gid = glyph_min;
+      unsigned prev_klass = (*it).second;
 
+      for (const auto gid_klass_pair : it)
+      {
+        hb_codepoint_t cur_gid = gid_klass_pair.first;
+        unsigned cur_klass = gid_klass_pair.second;
+        if (cur_gid != prev_gid + 1 ||
+            cur_klass != prev_klass)
+          num_ranges++;
+
+        prev_gid = cur_gid;
+        prev_klass = cur_klass;
+      }
+
       if (1 + (glyph_max - glyph_min + 1) < num_ranges * 3)
 	format = 1;
     }
@@ -1532,18 +1738,19 @@
 
     switch (u.format)
     {
-    case 1: return_trace (u.format1.serialize (c, glyphs, klasses));
-    case 2: return_trace (u.format2.serialize (c, glyphs, klasses));
+    case 1: return_trace (u.format1.serialize (c, it));
+    case 2: return_trace (u.format2.serialize (c, it));
     default:return_trace (false);
     }
   }
 
-  bool subset (hb_subset_context_t *c) const
+  bool subset (hb_subset_context_t *c,
+               hb_map_t *klass_map = nullptr /*OUT*/) const
   {
     TRACE_SUBSET (this);
     switch (u.format) {
-    case 1: return_trace (u.format1.subset (c));
-    case 2: return_trace (u.format2.subset (c));
+    case 1: return_trace (u.format1.subset (c, klass_map));
+    case 2: return_trace (u.format2.subset (c, klass_map));
     default:return_trace (false);
     }
   }
@@ -1610,10 +1817,10 @@
   DEFINE_SIZE_UNION (2, format);
 };
 
+template<typename Iterator>
 static inline void ClassDef_serialize (hb_serialize_context_t *c,
-				       hb_array_t<const HBGlyphID> glyphs,
-				       hb_array_t<const HBUINT16> klasses)
-{ c->start_embed<ClassDef> ()->serialize (c, glyphs, klasses); }
+                                       Iterator it)
+{ c->start_embed<ClassDef> ()->serialize (c, it); }
 
 
 /*
@@ -1691,6 +1898,21 @@
 		  axesZ.sanitize (c, (unsigned int) axisCount * (unsigned int) regionCount));
   }
 
+  bool serialize (hb_serialize_context_t *c, const VarRegionList *src, const hb_bimap_t &region_map)
+  {
+    TRACE_SERIALIZE (this);
+    VarRegionList *out = c->allocate_min<VarRegionList> ();
+    if (unlikely (!out)) return_trace (false);
+    axisCount = src->axisCount;
+    regionCount = region_map.get_population ();
+    if (unlikely (!c->allocate_size<VarRegionList> (get_size () - min_size))) return_trace (false);
+    for (unsigned int r = 0; r < regionCount; r++)
+      memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * region_map.backward (r)], VarRegionAxis::static_size * axisCount);
+
+    return_trace (true);
+  }
+
+  unsigned int get_size () const { return min_size + VarRegionAxis::static_size * axisCount * regionCount; }
   unsigned int get_region_count () const { return regionCount; }
 
   protected:
@@ -1723,7 +1945,7 @@
    unsigned int count = regionIndices.len;
    unsigned int scount = shortCount;
 
-   const HBUINT8 *bytes = &StructAfter<HBUINT8> (regionIndices);
+   const HBUINT8 *bytes = get_delta_bytes ();
    const HBUINT8 *row = bytes + inner * (scount + count);
 
    float delta = 0.;
@@ -1763,12 +1985,118 @@
     return_trace (c->check_struct (this) &&
 		  regionIndices.sanitize (c) &&
 		  shortCount <= regionIndices.len &&
-		  c->check_range (&StructAfter<HBUINT8> (regionIndices),
+		  c->check_range (get_delta_bytes (),
 				  itemCount,
 				  get_row_size ()));
   }
 
+  bool serialize (hb_serialize_context_t *c,
+		  const VarData *src,
+		  const hb_inc_bimap_t &inner_map,
+		  const hb_bimap_t &region_map)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    itemCount = inner_map.get_next_value ();
+
+    /* Optimize short count */
+    unsigned short ri_count = src->regionIndices.len;
+    enum delta_size_t { kZero=0, kByte, kShort };
+    hb_vector_t<delta_size_t> delta_sz;
+    hb_vector_t<unsigned int> ri_map;	/* maps old index to new index */
+    delta_sz.resize (ri_count);
+    ri_map.resize (ri_count);
+    unsigned int new_short_count = 0;
+    unsigned int r;
+    for (r = 0; r < ri_count; r++)
+    {
+      delta_sz[r] = kZero;
+      for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
+      {
+	unsigned int old = inner_map.backward (i);
+	int16_t delta = src->get_item_delta (old, r);
+	if (delta < -128 || 127 < delta)
+	{
+	  delta_sz[r] = kShort;
+	  new_short_count++;
+	  break;
+	}
+	else if (delta != 0)
+	  delta_sz[r] = kByte;
+      }
+    }
+    unsigned int short_index = 0;
+    unsigned int byte_index = new_short_count;
+    unsigned int new_ri_count = 0;
+    for (r = 0; r < ri_count; r++)
+      if (delta_sz[r])
+      {
+      	ri_map[r] = (delta_sz[r] == kShort)? short_index++ : byte_index++;
+      	new_ri_count++;
+      }
+
+    shortCount = new_short_count;
+    regionIndices.len = new_ri_count;
+
+    unsigned int size = regionIndices.get_size () - HBUINT16::static_size/*regionIndices.len*/ + (get_row_size () * itemCount);
+    if (unlikely (!c->allocate_size<HBUINT8> (size)))
+      return_trace (false);
+
+    for (r = 0; r < ri_count; r++)
+      if (delta_sz[r]) regionIndices[ri_map[r]] = region_map[src->regionIndices[r]];
+
+    for (unsigned int i = 0; i < itemCount; i++)
+    {
+      unsigned int	old = inner_map.backward (i);
+      for (unsigned int r = 0; r < ri_count; r++)
+	if (delta_sz[r]) set_item_delta (i, ri_map[r], src->get_item_delta (old, r));
+    }
+
+    return_trace (true);
+  }
+
+  void collect_region_refs (hb_inc_bimap_t &region_map, const hb_inc_bimap_t &inner_map) const
+  {
+    for (unsigned int r = 0; r < regionIndices.len; r++)
+    {
+      unsigned int region = regionIndices[r];
+      if (region_map.has (region)) continue;
+      for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
+	if (get_item_delta (inner_map.backward (i), r) != 0)
+	{
+	  region_map.add (region);
+	  break;
+	}
+    }
+  }
+
   protected:
+  const HBUINT8 *get_delta_bytes () const
+  { return &StructAfter<HBUINT8> (regionIndices); }
+
+  HBUINT8 *get_delta_bytes ()
+  { return &StructAfter<HBUINT8> (regionIndices); }
+
+  int16_t get_item_delta (unsigned int item, unsigned int region) const
+  {
+    if ( item >= itemCount || unlikely (region >= regionIndices.len)) return 0;
+    const HBINT8 *p = (const HBINT8 *)get_delta_bytes () + item * get_row_size ();
+    if (region < shortCount)
+      return ((const HBINT16 *)p)[region];
+    else
+      return (p + HBINT16::static_size * shortCount)[region - shortCount];
+  }
+
+  void set_item_delta (unsigned int item, unsigned int region, int16_t delta)
+  {
+    HBINT8 *p = (HBINT8 *)get_delta_bytes () + item * get_row_size ();
+    if (region < shortCount)
+      ((HBINT16 *)p)[region] = delta;
+    else
+      (p + HBINT16::static_size * shortCount)[region - shortCount] = delta;
+  }
+
+  protected:
   HBUINT16		itemCount;
   HBUINT16		shortCount;
   ArrayOf<HBUINT16>	regionIndices;
@@ -1815,6 +2143,43 @@
 		  dataSets.sanitize (c, this));
   }
 
+  bool serialize (hb_serialize_context_t *c,
+		  const VariationStore *src,
+  		  const hb_array_t <hb_inc_bimap_t> &inner_maps)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int set_count = 0;
+    for (unsigned int i = 0; i < inner_maps.length; i++)
+      if (inner_maps[i].get_population () > 0) set_count++;
+
+    unsigned int size = min_size + HBUINT32::static_size * set_count;
+    if (unlikely (!c->allocate_size<HBUINT32> (size))) return_trace (false);
+    format = 1;
+
+    hb_inc_bimap_t region_map;
+    for (unsigned int i = 0; i < inner_maps.length; i++)
+      (src+src->dataSets[i]).collect_region_refs (region_map, inner_maps[i]);
+    region_map.sort ();
+
+    if (unlikely (!regions.serialize (c, this)
+		  .serialize (c, &(src+src->regions), region_map))) return_trace (false);
+
+    /* TODO: The following code could be simplified when
+     * OffsetListOf::subset () can take a custom param to be passed to VarData::serialize ()
+     */
+    dataSets.len = set_count;
+    unsigned int set_index = 0;
+    for (unsigned int i = 0; i < inner_maps.length; i++)
+    {
+      if (inner_maps[i].get_population () == 0) continue;
+      if (unlikely (!dataSets[set_index++].serialize (c, this)
+		      .serialize (c, &(src+src->dataSets[i]), inner_maps[i], region_map)))
+	return_trace (false);
+    }
+
+    return_trace (true);
+  }
+
   unsigned int get_region_index_count (unsigned int ivs) const
   { return (this+dataSets[ivs]).get_region_index_count (); }
 
@@ -1833,6 +2198,8 @@
 				      &scalars[0], num_scalars);
   }
 
+  unsigned int get_sub_table_count () const { return dataSets.len; }
+
   protected:
   HBUINT16				format;
   LOffsetTo<VarRegionList>		regions;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -101,10 +101,10 @@
   unsigned int get_len () const  { return hb_popcount ((unsigned int) *this); }
   unsigned int get_size () const { return get_len () * Value::static_size; }
 
-  bool apply_value (hb_ot_apply_context_t   *c,
-		    const void           *base,
-		    const Value          *values,
-		    hb_glyph_position_t  &glyph_pos) const
+  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;
@@ -257,7 +257,7 @@
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
-  
+
   AnchorFormat1* copy (hb_serialize_context_t *c) const
   {
     TRACE_SERIALIZE (this);
@@ -558,7 +558,7 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+    const hb_set_t &glyphset = *c->plan->glyphset ();
     const hb_map_t &glyph_map = *c->plan->glyph_map;
 
     auto it =
@@ -647,7 +647,7 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+    const hb_set_t &glyphset = *c->plan->glyphset ();
     const hb_map_t &glyph_map = *c->plan->glyph_map;
 
     unsigned sub_length = valueFormat.get_len ();
@@ -761,6 +761,18 @@
 {
   friend struct PairSet;
 
+  bool serialize (hb_serialize_context_t *c,
+                  unsigned length,
+                  const hb_map_t &glyph_map) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = c->start_embed (*this);
+    if (unlikely (!c->extend_min (out))) return_trace (false);
+    
+    out->secondGlyph = glyph_map[secondGlyph];
+    return_trace (c->copy (values, length));
+  }
+
   protected:
   HBGlyphID	secondGlyph;		/* GlyphID of second glyph in the
 					 * pair--first glyph is listed in the
@@ -846,6 +858,37 @@
     return_trace (false);
   }
 
+  bool subset (hb_subset_context_t *c,
+               const ValueFormat valueFormats[2]) const
+  {
+    TRACE_SUBSET (this);
+    auto snap = c->serializer->snapshot ();
+
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+    out->len = 0;
+
+    const hb_set_t &glyphset = *c->plan->glyphset ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    unsigned len1 = valueFormats[0].get_len ();
+    unsigned len2 = valueFormats[1].get_len ();
+    unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
+
+    const PairValueRecord *record = &firstPairValueRecord;
+    unsigned count = len, num = 0;
+    for (unsigned i = 0; i < count; i++)
+    {
+      if (!glyphset.has (record->secondGlyph)) continue;
+      if (record->serialize (c->serializer, len1 + len2, glyph_map)) num++;
+      record = &StructAtOffset<const PairValueRecord> (record, record_size);
+    }
+
+    out->len = num;
+    if (!num) c->serializer->revert (snap);
+    return_trace (num);
+  }
+
   struct sanitize_closure_t
   {
     const void *base;
@@ -919,8 +962,43 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+
+    const hb_set_t &glyphset = *c->plan->glyphset ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+    out->format = format;
+    out->valueFormat[0] = valueFormat[0];
+    out->valueFormat[1] = valueFormat[1];
+
+    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+
+    + hb_zip (this+coverage, pairSet)
+    | hb_filter (glyphset, hb_first)
+    | hb_filter ([this, c, out] (const OffsetTo<PairSet>& _)
+		 {
+		   auto *o = out->pairSet.serialize_append (c->serializer);
+		   if (unlikely (!o)) return false;
+		   auto snap = c->serializer->snapshot ();
+		   bool ret = o->serialize_subset (c, _, this, out, valueFormat);
+		   if (!ret)
+		   {
+		     out->pairSet.pop ();
+		     c->serializer->revert (snap);
+		   }
+		   return ret;
+		 },
+		 hb_second)
+    | hb_map (hb_first)
+    | hb_map (glyph_map)
+    | hb_sink (new_coverage)
+    ;
+
+    out->coverage.serialize (c->serializer, out)
+		 .serialize (c->serializer, new_coverage.iter ());
+
+    return_trace (bool (new_coverage));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -1011,8 +1089,49 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+    out->format = format;
+    out->valueFormat1 = valueFormat1;
+    out->valueFormat2 = valueFormat2;
+
+    hb_map_t klass1_map;
+    out->classDef1.serialize_subset (c, classDef1, this, out, &klass1_map);
+    out->class1Count = klass1_map.get_population ();
+
+    hb_map_t klass2_map;
+    out->classDef2.serialize_subset (c, classDef2, this, out, &klass2_map);
+    out->class2Count = klass2_map.get_population ();
+
+    unsigned record_len = valueFormat1.get_len () + valueFormat2.get_len ();
+
+    + hb_range ((unsigned) class1Count)
+    | hb_filter (klass1_map)
+    | hb_apply ([&] (const unsigned class1_idx)
+                {
+                  + hb_range ((unsigned) class2Count)
+                  | hb_filter (klass2_map)
+                  | hb_apply ([&] (const unsigned class2_idx)
+                              {
+                                unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_len;
+                                for (unsigned i = 0; i < record_len; i++)
+                                  c->serializer->copy (values[idx+i]);
+                              })
+                  ;
+                })
+    ;
+
+    const hb_set_t &glyphset = *c->plan->glyphset ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    auto it =
+    + hb_iter (this+coverage)
+    | hb_filter (glyphset)
+    | hb_map_retains_sorting (glyph_map)
+    ;
+
+    out->coverage.serialize (c->serializer, out).serialize (c->serializer, it);
+    return_trace (out->class1Count && out->class2Count && bool (it));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -1242,7 +1361,7 @@
 	    hb_requires (hb_is_iterator (Iterator))>
   void serialize (hb_serialize_context_t *c,
 		  Iterator it,
-                  const void *src_base)
+		  const void *src_base)
   {
     if (unlikely (!c->extend_min ((*this)))) return;
     this->format = 1;
@@ -1273,7 +1392,7 @@
     + hb_zip (this+coverage, entryExitRecord)
     | hb_filter (glyphset, hb_first)
     | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&>
-                              { return hb_pair (glyph_map[p.first], p.second);})
+			      { return hb_pair (glyph_map[p.first], p.second);})
     ;
 
     bool ret = bool (it);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -452,20 +452,7 @@
     hb_sorted_vector_t<hb_codepoint_t> new_coverage;
     + hb_zip (this+coverage, sequence)
     | hb_filter (glyphset, hb_first)
-    | hb_filter ([this, c, out] (const OffsetTo<Sequence>& _)
-		 {
-		   auto *o = out->sequence.serialize_append (c->serializer);
-		   if (unlikely (!o)) return false;
-		   auto snap = c->serializer->snapshot ();
-		   bool ret = o->serialize_subset (c, _, this, out);
-		   if (!ret)
-		   {
-		     out->sequence.pop ();
-		     c->serializer->revert (snap);
-		   }
-		   return ret;
-		 },
-		 hb_second)
+    | hb_filter (subset_offset_array (c, out->sequence, this, out), hb_second)
     | hb_map (hb_first)
     | hb_map (glyph_map)
     | hb_sink (new_coverage)
@@ -675,20 +662,7 @@
     hb_sorted_vector_t<hb_codepoint_t> new_coverage;
     + hb_zip (this+coverage, alternateSet)
     | hb_filter (glyphset, hb_first)
-    | hb_filter ([this, c, out] (const OffsetTo<AlternateSet>& _)
-		 {
-		   auto *o = out->alternateSet.serialize_append (c->serializer);
-		   if (unlikely (!o)) return false;
-		   auto snap = c->serializer->snapshot ();
-		   bool ret = o->serialize_subset (c, _, this, out);
-		   if (!ret)
-		   {
-		     out->alternateSet.pop ();
-		     c->serializer->revert (snap);
-		   }
-		   return ret;
-		 },
-		 hb_second)
+    | hb_filter (subset_offset_array (c, out->alternateSet, this, out), hb_second)
     | hb_map (hb_first)
     | hb_map (glyph_map)
     | hb_sink (new_coverage)
@@ -948,19 +922,7 @@
     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
 
     + hb_iter (ligature)
-    | hb_filter ([this, c, out] (const OffsetTo<Ligature>& _)
-		 {
-		   auto *o = out->ligature.serialize_append (c->serializer);
-		   if (unlikely (!o)) return false;
-		   auto snap = c->serializer->snapshot ();
-		   bool ret = o->serialize_subset (c, _, this, out);
-		   if (!ret)
-		   {
-		     out->ligature.pop ();
-		     c->serializer->revert (snap);
-		   }
-		   return ret;
-		 })
+    | hb_filter (subset_offset_array (c, out->ligature, this, out))
     | hb_drain
     ;
     return_trace (bool (out->ligature));
@@ -1074,20 +1036,7 @@
     hb_sorted_vector_t<hb_codepoint_t> new_coverage;
     + hb_zip (this+coverage, ligatureSet)
     | hb_filter (glyphset, hb_first)
-    | hb_filter ([this, c, out] (const OffsetTo<LigatureSet>& _)
-		 {
-		   auto *o = out->ligatureSet.serialize_append (c->serializer);
-		   if (unlikely (!o)) return false;
-		   auto snap = c->serializer->snapshot ();
-		   bool ret = o->serialize_subset (c, _, this, out);
-		   if (!ret)
-		   {
-		     out->ligatureSet.pop ();
-		     c->serializer->revert (snap);
-		   }
-		   return ret;
-		 },
-		 hb_second)
+    | hb_filter (subset_offset_array (c, out->ligatureSet, this, out), hb_second)
     | hb_map (hb_first)
     | hb_map (glyph_map)
     | hb_sink (new_coverage)

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -387,7 +387,7 @@
 	     skip == matcher_t::SKIP_NO))
 	{
 	  num_items--;
-	  match_glyph_data++;
+	  if (match_glyph_data) match_glyph_data++;
 	  return true;
 	}
 
@@ -414,7 +414,7 @@
 	     skip == matcher_t::SKIP_NO))
 	{
 	  num_items--;
-	  match_glyph_data++;
+	  if (match_glyph_data) match_glyph_data++;
 	  return true;
 	}
 
@@ -712,11 +712,9 @@
 				     intersects_func_t intersects_func,
 				     const void *intersects_data)
 {
-  return
-  + hb_iter (values, count)
-  | hb_map ([&] (const HBUINT16 &_) { return intersects_func (glyphs, _, intersects_data); })
-  | hb_any
-  ;
+  for (const HBUINT16 &_ : + hb_iter (values, count))
+    if (intersects_func (glyphs, _, intersects_data)) return true;
+  return false;
 }
 
 
@@ -2002,6 +2000,83 @@
 					      lookup.arrayZ, lookup_context));
   }
 
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  void serialize_array (hb_serialize_context_t *c,
+                        HBUINT16 len,
+                        Iterator it) const
+  {
+    c->copy (len);
+    for (const auto g : it)
+    {
+      HBUINT16 gid;
+      gid = g;
+      c->copy (gid);
+    }
+  }
+
+  ChainRule* copy (hb_serialize_context_t *c,
+		   const hb_map_t *backtrack_map,
+		   const hb_map_t *input_map = nullptr,
+		   const hb_map_t *lookahead_map = nullptr) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = c->start_embed (this);
+    if (unlikely (!out)) return_trace (nullptr);
+
+    const hb_map_t *mapping = backtrack_map;
+    serialize_array (c, backtrack.len, + backtrack.iter ()
+				       | hb_map (mapping));
+
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
+    if (input_map) mapping = input_map;
+    serialize_array (c, input.lenP1, + input.iter ()
+				     | hb_map (mapping));
+
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
+    if (lookahead_map) mapping = lookahead_map;
+    serialize_array (c, lookahead.len, + lookahead.iter ()
+				       | hb_map (mapping));
+
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    c->copy (lookup);
+
+    return_trace (out);
+  }
+
+  bool subset (hb_subset_context_t *c,
+               const hb_map_t *backtrack_map = nullptr,
+               const hb_map_t *input_map = nullptr,
+               const hb_map_t *lookahead_map = nullptr) const
+  {
+    TRACE_SUBSET (this);
+
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
+
+    if (!backtrack_map)
+    {
+      const hb_set_t &glyphset = *c->plan->glyphset ();
+      if (!hb_all (backtrack, glyphset) ||
+          !hb_all (input, glyphset) ||
+          !hb_all (lookahead, glyphset))
+        return_trace (false);
+
+      copy (c->serializer, c->plan->glyph_map);
+    }
+    else
+    {
+      if (!hb_all (backtrack, backtrack_map) ||
+          !hb_all (input, input_map) ||
+          !hb_all (lookahead, lookahead_map))
+        return_trace (false);
+
+      copy (c->serializer, backtrack_map, input_map, lookahead_map);
+    }
+
+    return_trace (true);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -2083,6 +2158,40 @@
     ;
   }
 
+  bool subset (hb_subset_context_t *c,
+               const hb_map_t *backtrack_klass_map = nullptr,
+               const hb_map_t *input_klass_map = nullptr,
+               const hb_map_t *lookahead_klass_map = nullptr) const
+  {
+    TRACE_SUBSET (this);
+
+    auto snap = c->serializer->snapshot ();
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+    for (const OffsetTo<ChainRule>& _ : rule)
+    {
+      if (!_) continue;
+      auto *o = out->rule.serialize_append (c->serializer);
+      if (unlikely (!o)) continue;
+
+      auto o_snap = c->serializer->snapshot ();
+      if (!o->serialize_subset (c, _, this, out,
+                                backtrack_klass_map,
+                                input_klass_map,
+                                lookahead_klass_map))
+      {
+        out->rule.pop ();
+        c->serializer->revert (o_snap);
+      }
+    }
+
+    bool ret = bool (out->rule);
+    if (!ret) c->serializer->revert (snap);
+
+    return_trace (ret);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -2175,8 +2284,25 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+    const hb_set_t &glyphset = *c->plan->glyphset ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+    out->format = format;
+
+    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+    + hb_zip (this+coverage, ruleSet)
+    | hb_filter (glyphset, hb_first)
+    | hb_filter (subset_offset_array (c, out->ruleSet, this, out), hb_second)
+    | hb_map (hb_first)
+    | hb_map (glyph_map)
+    | hb_sink (new_coverage)
+    ;
+
+    out->coverage.serialize (c->serializer, out)
+		 .serialize (c->serializer, new_coverage.iter ());
+    return_trace (bool (new_coverage));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -2314,8 +2440,54 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+    out->format = format;
+    out->coverage.serialize_subset (c, coverage, this, out);
+
+    hb_map_t backtrack_klass_map;
+    out->backtrackClassDef.serialize_subset (c, backtrackClassDef, this, out, &backtrack_klass_map);
+
+    // subset inputClassDef based on glyphs survived in Coverage subsetting
+    hb_map_t input_klass_map;
+    out->inputClassDef.serialize_subset (c, inputClassDef, this, out, &input_klass_map);
+
+    hb_map_t lookahead_klass_map;
+    out->lookaheadClassDef.serialize_subset (c, lookaheadClassDef, this, out, &lookahead_klass_map);
+
+    hb_vector_t<unsigned> rulesets;
+    bool ret = true;
+    for (const OffsetTo<ChainRuleSet>& _ : + hb_enumerate (ruleSet)
+					   | hb_filter (input_klass_map, hb_first)
+					   | hb_map (hb_second))
+    {
+      auto *o = out->ruleSet.serialize_append (c->serializer);
+      if (unlikely (!o))
+      {
+        ret = false;
+        break;
+      }
+      if (!o->serialize_subset (c, _, this, out,
+                                &backtrack_klass_map,
+                                &input_klass_map,
+                                &lookahead_klass_map))
+      {
+        rulesets.push (0);
+      }
+      else rulesets.push (1);
+    }
+
+    if (!ret) return_trace (ret);
+
+    //prune empty trailing ruleSets
+    unsigned count = rulesets.length;
+    while (count > 0 && rulesets[count-1] == 0)
+    {
+      out->ruleSet.pop ();
+      count--;
+    }
+
+    return_trace (bool (out->ruleSet));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -2457,11 +2629,46 @@
 					      lookup.len, lookup.arrayZ, lookup_context));
   }
 
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  bool serialize_coverage_offsets (hb_subset_context_t *c,
+                                   Iterator it,
+				   const void* src_base,
+				   const void* dst_base) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = c->serializer->start_embed<OffsetArrayOf<Coverage>> ();
+
+    if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size))) return_trace (false);
+
+    + it
+    | hb_apply (subset_offset_array (c, *out, src_base, dst_base))
+    ;
+
+    return_trace (out->len);
+  }
+
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+
+    auto *out = c->serializer->start_embed (this);
+    if (unlikely (!out)) return_trace (false);
+    if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
+
+    if (!serialize_coverage_offsets (c, backtrack.iter (), this, out))
+      return_trace (false);
+
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    if (!serialize_coverage_offsets (c, input.iter (), this, out))
+      return_trace (false);
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
+    if (!serialize_coverage_offsets (c, lookahead.iter (), this, out))
+      return_trace (false);
+
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    return_trace (c->serializer->copy (lookup));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -38,7 +38,7 @@
 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].length; i++)
-    hb_set_add (lookups_out, lookups[table_index][i].index);
+    lookups_out->add (lookups[table_index][i].index);
 }
 
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -134,8 +134,8 @@
     OBLIQUE		= 1u<<9
   };
 
-  bool is_italic () const        { return fsSelection & ITALIC; }
-  bool is_oblique () const       { return fsSelection & OBLIQUE; }
+  bool        is_italic () const { return fsSelection & ITALIC; }
+  bool       is_oblique () const { return fsSelection & OBLIQUE; }
   bool use_typo_metrics () const { return fsSelection & USE_TYPO_METRICS; }
 
   enum width_class_t {

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic-fallback.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic-fallback.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic-fallback.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -230,8 +230,8 @@
     return false;
 
   const Manifest &manifest = reinterpret_cast<const Manifest&> (arabic_win1256_gsub_lookups.manifest);
-  static_assert (sizeof (arabic_win1256_gsub_lookups.manifestData) / sizeof (ManifestLookup)
-		 <= ARABIC_FALLBACK_MAX_LOOKUPS, "");
+  static_assert (sizeof (arabic_win1256_gsub_lookups.manifestData) ==
+		 ARABIC_FALLBACK_MAX_LOOKUPS * sizeof (ManifestLookup), "");
   /* TODO sanitize the table? */
 
   unsigned j = 0;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -116,8 +116,8 @@
 
 static void
 setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
-		   hb_buffer_t              *buffer,
-		   hb_font_t                *font HB_UNUSED)
+		     hb_buffer_t              *buffer,
+		     hb_font_t                *font HB_UNUSED)
 {
   HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_category);
   HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_position);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use-table.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use-table.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use-table.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -347,7 +347,7 @@
 
   /* 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,  VPst,  VPst,  VPst,  VBlw,  FAbv,  FAbv,  FAbv,
+  /* 1C20 */     B,     B,     B,     B,   SUB,   SUB,  VPst,  VPre,  VPre,  VPre,  VPst,  VPst,  VBlw,  FAbv,  FAbv,  FAbv,
   /* 1C30 */  FAbv,  FAbv,  FAbv,  FAbv, VMPre, VMPre, FMAbv, 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,
 

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -0,0 +1,734 @@
+/*
+ * Copyright © 2019  Adobe Inc.
+ * Copyright © 2019  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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_OT_VAR_GVAR_TABLE_HH
+#define HB_OT_VAR_GVAR_TABLE_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-glyf-table.hh"
+#include "hb-ot-var-fvar-table.hh"
+
+/*
+ * gvar -- Glyph Variation Table
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/gvar
+ */
+#define HB_OT_TAG_gvar HB_TAG('g','v','a','r')
+
+namespace OT {
+
+struct contour_point_t
+{
+  void init (float x_=0.f, float y_=0.f) { flag = 0; x = x_; y = y_; }
+
+  void translate (const contour_point_t &p) { x += p.x; y += p.y; }
+
+  uint8_t flag;
+  float x, y;
+};
+
+struct contour_point_vector_t : hb_vector_t<contour_point_t>
+{
+  void extend (const hb_array_t<contour_point_t> &a)
+  {
+    unsigned int old_len = length;
+    resize (old_len + a.length);
+    for (unsigned int i = 0; i < a.length; i++)
+      (*this)[old_len + i] = a[i];
+  }
+
+  void transform (const float (&matrix)[4])
+  {
+    for (unsigned int i = 0; i < length; i++)
+    {
+      contour_point_t &p = (*this)[i];
+      float x_ = p.x * matrix[0] + p.y * matrix[2];
+	   p.y = p.x * matrix[1] + p.y * matrix[3];
+      p.x = x_;
+    }
+  }
+
+  void translate (const contour_point_t& delta)
+  {
+    for (unsigned int i = 0; i < length; i++)
+      (*this)[i].translate (delta);
+  }
+};
+
+struct range_checker_t
+{
+  range_checker_t (const void *data_, unsigned int length_)
+    : data ((const char *) data_), length (length_) {}
+
+  template <typename T>
+  bool in_range (const T *p, unsigned int size = T::static_size) const
+  {
+    return ((const char *) p) >= data
+	&& ((const char *) p + size) <= data + length;
+  }
+
+  protected:
+  const char *data;
+  const unsigned int length;
+};
+
+struct Tuple : UnsizedArrayOf<F2DOT14> {};
+
+struct TuppleIndex : HBUINT16
+{
+  enum Flags {
+    EmbeddedPeakTuple   = 0x8000u,
+    IntermediateRegion  = 0x4000u,
+    PrivatePointNumbers = 0x2000u,
+    TupleIndexMask      = 0x0FFFu
+  };
+
+  DEFINE_SIZE_STATIC (2);
+};
+
+struct TupleVarHeader
+{
+  unsigned int get_size (unsigned int axis_count) const
+  {
+    return min_size +
+	   (has_peak () ? get_peak_tuple ().get_size (axis_count) : 0) +
+	   (has_intermediate () ? (get_start_tuple (axis_count).get_size (axis_count) +
+				   get_end_tuple (axis_count).get_size (axis_count)) : 0);
+  }
+
+  const TupleVarHeader &get_next (unsigned int axis_count) const
+  { return StructAtOffset<TupleVarHeader> (this, get_size (axis_count)); }
+
+  float calculate_scalar (const int *coords, unsigned int coord_count,
+  			  const hb_array_t<const F2DOT14> shared_tuples) const
+  {
+    const F2DOT14 *peak_tuple;
+
+    if (has_peak ())
+      peak_tuple = &(get_peak_tuple ()[0]);
+    else
+    {
+      unsigned int index = get_index ();
+      if (unlikely (index * coord_count >= shared_tuples.length))
+	return 0.f;
+      peak_tuple = &shared_tuples[coord_count * index];
+    }
+
+    const F2DOT14 *start_tuple = nullptr;
+    const F2DOT14 *end_tuple = nullptr;
+    if (has_intermediate ())
+    {
+      start_tuple = get_start_tuple (coord_count);
+      end_tuple = get_end_tuple (coord_count);
+    }
+
+    float scalar = 1.f;
+    for (unsigned int i = 0; i < coord_count; i++)
+    {
+      int v = coords[i];
+      int peak = peak_tuple[i];
+      if (!peak || v == peak) continue;
+
+      if (has_intermediate ())
+      {
+	int start = start_tuple[i];
+	int end = end_tuple[i];
+	if (unlikely (start > peak || peak > end ||
+		      (start < 0 && end > 0 && peak))) continue;
+	if (v < start || v > end) return 0.f;
+	if (v < peak)
+	{ if (peak != start) scalar *= (float) (v - start) / (peak - start); }
+	else
+	{ if (peak != end) scalar *= (float) (end - v) / (end - peak); }
+      }
+      else if (!v || v < hb_min (0, peak) || v > hb_max (0, peak)) return 0.f;
+      else
+	scalar *= (float) v / peak;
+    }
+    return scalar;
+  }
+
+  unsigned int get_data_size () const { return varDataSize; }
+
+  bool           has_peak () const { return (tupleIndex & TuppleIndex::EmbeddedPeakTuple); }
+  bool   has_intermediate () const { return (tupleIndex & TuppleIndex::IntermediateRegion); }
+  bool has_private_points () const { return (tupleIndex & TuppleIndex::PrivatePointNumbers); }
+  unsigned int  get_index () const { return (tupleIndex & TuppleIndex::TupleIndexMask); }
+
+  protected:
+  const Tuple &get_peak_tuple () const
+  { return StructAfter<Tuple> (tupleIndex); }
+  const Tuple &get_start_tuple (unsigned int axis_count) const
+  { return *(const Tuple *) &get_peak_tuple ()[has_peak () ? axis_count : 0]; }
+  const Tuple &get_end_tuple (unsigned int axis_count) const
+  { return *(const Tuple *) &get_peak_tuple ()[has_peak () ? (axis_count * 2) : axis_count]; }
+
+  HBUINT16		varDataSize;
+  TuppleIndex		tupleIndex;
+  /* UnsizedArrayOf<F2DOT14> peakTuple - optional */
+  /* UnsizedArrayOf<F2DOT14> intermediateStartTuple - optional */
+  /* UnsizedArrayOf<F2DOT14> intermediateEndTuple - optional */
+
+  public:
+  DEFINE_SIZE_MIN (4);
+};
+
+struct TupleVarCount : HBUINT16
+{
+  bool has_shared_point_numbers () const { return ((*this) & SharedPointNumbers); }
+  unsigned int get_count () const { return (*this) & CountMask; }
+
+  protected:
+  enum Flags
+  {
+    SharedPointNumbers	= 0x8000u,
+    CountMask		= 0x0FFFu
+  };
+
+  public:
+  DEFINE_SIZE_STATIC (2);
+};
+
+struct GlyphVarData
+{
+  const TupleVarHeader &get_tuple_var_header (void) const
+  { return StructAfter<TupleVarHeader> (data); }
+
+  struct tuple_iterator_t
+  {
+    void init (const GlyphVarData *var_data_, unsigned int length_, unsigned int axis_count_)
+    {
+      var_data = var_data_;
+      length = length_;
+      index = 0;
+      axis_count = axis_count_;
+      current_tuple = &var_data->get_tuple_var_header ();
+      data_offset = 0;
+    }
+
+    bool get_shared_indices (hb_vector_t<unsigned int> &shared_indices /* OUT */)
+    {
+      if (var_data->has_shared_point_numbers ())
+      {
+	range_checker_t checker (var_data, length);
+	const HBUINT8 *base = &(var_data+var_data->data);
+	const HBUINT8 *p = base;
+	if (!unpack_points (p, shared_indices, checker)) return false;
+	data_offset = p - base;
+      }
+      return true;
+    }
+
+    bool is_valid () const
+    {
+      return (index < var_data->tupleVarCount.get_count ()) &&
+	     in_range (current_tuple) &&
+	     current_tuple->get_size (axis_count);
+    }
+
+    bool move_to_next ()
+    {
+      data_offset += current_tuple->get_data_size ();
+      current_tuple = &current_tuple->get_next (axis_count);
+      index++;
+      return is_valid ();
+    }
+
+    bool in_range (const void *p, unsigned int l) const
+    { return (const char*) p >= (const char*) var_data && (const char*) p+l <= (const char*) var_data + length; }
+
+    template <typename T> bool in_range (const T *p) const { return in_range (p, sizeof (*p)); }
+
+    const HBUINT8 *get_serialized_data () const
+    { return &(var_data+var_data->data) + data_offset; }
+
+    private:
+    const GlyphVarData *var_data;
+    unsigned int length;
+    unsigned int index;
+    unsigned int axis_count;
+    unsigned int data_offset;
+
+    public:
+    const TupleVarHeader *current_tuple;
+  };
+
+  static bool get_tuple_iterator (const GlyphVarData *var_data,
+  				  unsigned int length,
+  				  unsigned int axis_count,
+  				  hb_vector_t<unsigned int> &shared_indices /* OUT */,
+  				  tuple_iterator_t *iterator /* OUT */)
+  {
+    iterator->init (var_data, length, axis_count);
+    if (!iterator->get_shared_indices (shared_indices))
+      return false;
+    return iterator->is_valid ();
+  }
+
+  bool has_shared_point_numbers () const { return tupleVarCount.has_shared_point_numbers (); }
+
+  static bool unpack_points (const HBUINT8 *&p /* IN/OUT */,
+			     hb_vector_t<unsigned int> &points /* OUT */,
+			     const range_checker_t &check)
+  {
+    enum packed_point_flag_t
+    {
+      POINTS_ARE_WORDS     = 0x80,
+      POINT_RUN_COUNT_MASK = 0x7F
+    };
+
+    if (unlikely (!check.in_range (p))) return false;
+
+    uint16_t count = *p++;
+    if (count & POINTS_ARE_WORDS)
+    {
+      if (unlikely (!check.in_range (p))) return false;
+      count = ((count & POINT_RUN_COUNT_MASK) << 8) | *p++;
+    }
+    points.resize (count);
+
+    unsigned int n = 0;
+    uint16_t i = 0;
+    while (i < count)
+    {
+      if (unlikely (!check.in_range (p))) return false;
+      uint16_t j;
+      uint8_t control = *p++;
+      uint16_t run_count = (control & POINT_RUN_COUNT_MASK) + 1;
+      if (control & POINTS_ARE_WORDS)
+      {
+	for (j = 0; j < run_count && i < count; j++, i++)
+	{
+	  if (unlikely (!check.in_range ((const HBUINT16 *) p)))
+	    return false;
+	  n += *(const HBUINT16 *)p;
+	  points[i] = n;
+	  p += HBUINT16::static_size;
+	}
+      }
+      else
+      {
+	for (j = 0; j < run_count && i < count; j++, i++)
+	{
+	  if (unlikely (!check.in_range (p))) return false;
+	  n += *p++;
+	  points[i] = n;
+	}
+      }
+      if (j < run_count) return false;
+    }
+    return true;
+  }
+
+  static bool unpack_deltas (const HBUINT8 *&p /* IN/OUT */,
+			     hb_vector_t<int> &deltas /* IN/OUT */,
+			     const range_checker_t &check)
+  {
+    enum packed_delta_flag_t
+    {
+      DELTAS_ARE_ZERO      = 0x80,
+      DELTAS_ARE_WORDS     = 0x40,
+      DELTA_RUN_COUNT_MASK = 0x3F
+    };
+
+    unsigned int i = 0;
+    unsigned int count = deltas.length;
+    while (i < count)
+    {
+      if (unlikely (!check.in_range (p))) return false;
+      uint8_t control = *p++;
+      unsigned int run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
+      unsigned int j;
+      if (control & DELTAS_ARE_ZERO)
+	for (j = 0; j < run_count && i < count; j++, i++)
+	  deltas[i] = 0;
+      else if (control & DELTAS_ARE_WORDS)
+	for (j = 0; j < run_count && i < count; j++, i++)
+	{
+	  if (unlikely (!check.in_range ((const HBUINT16 *) p)))
+	    return false;
+	  deltas[i] = *(const HBINT16 *) p;
+	  p += HBUINT16::static_size;
+	}
+      else
+	for (j = 0; j < run_count && i < count; j++, i++)
+	{
+	  if (unlikely (!check.in_range (p)))
+	    return false;
+	  deltas[i] = *(const HBINT8 *) p++;
+	}
+      if (j < run_count)
+	return false;
+    }
+    return true;
+  }
+
+  protected:
+  TupleVarCount		tupleVarCount;
+  OffsetTo<HBUINT8>	data;
+  /* TupleVarHeader tupleVarHeaders[] */
+  public:
+  DEFINE_SIZE_MIN (4);
+};
+
+struct gvar
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_gvar;
+
+  bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && (version.major == 1) &&
+		  (glyphCount == c->get_num_glyphs ()) &&
+		  c->check_array (&(this+sharedTuples), axisCount * sharedTupleCount) &&
+		  (is_long_offset () ?
+		     c->check_array (get_long_offset_array (), glyphCount+1) :
+		     c->check_array (get_short_offset_array (), glyphCount+1)) &&
+		  c->check_array (((const HBUINT8*)&(this+dataZ)) + get_offset (0),
+				  get_offset (glyphCount) - get_offset (0)));
+  }
+
+  /* GlyphVarData not sanitized here; must be checked while accessing each glyph varation data */
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return sanitize_shallow (c); }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+
+    gvar *out = c->serializer->allocate_min<gvar> ();
+    if (unlikely (!out)) return_trace (false);
+
+    out->version.major = 1;
+    out->version.minor = 0;
+    out->axisCount = axisCount;
+    out->sharedTupleCount = sharedTupleCount;
+
+    unsigned int num_glyphs = c->plan->num_output_glyphs ();
+    out->glyphCount = num_glyphs;
+
+    unsigned int subset_data_size = 0;
+    for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
+    {
+      hb_codepoint_t old_gid;
+      if (!c->plan->old_gid_for_new_gid (gid, &old_gid)) continue;
+      subset_data_size += get_glyph_var_data_length (old_gid);
+    }
+
+    bool long_offset = subset_data_size & ~0xFFFFu;
+    out->flags = long_offset ? 1 : 0;
+
+    HBUINT8 *subset_offsets = c->serializer->allocate_size<HBUINT8> ((long_offset ? 4 : 2) * (num_glyphs + 1));
+    if (!subset_offsets) return_trace (false);
+
+    /* shared tuples */
+    if (!sharedTupleCount || !sharedTuples)
+      out->sharedTuples = 0;
+    else
+    {
+      unsigned int shared_tuple_size = F2DOT14::static_size * axisCount * sharedTupleCount;
+      F2DOT14 *tuples = c->serializer->allocate_size<F2DOT14> (shared_tuple_size);
+      if (!tuples) return_trace (false);
+      out->sharedTuples = (char *) tuples - (char *) out;
+      memcpy (tuples, &(this+sharedTuples), shared_tuple_size);
+    }
+
+    char *subset_data = c->serializer->allocate_size<char> (subset_data_size);
+    if (!subset_data) return_trace (false);
+    out->dataZ = subset_data - (char *)out;
+
+    unsigned int glyph_offset = 0;
+    for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
+    {
+      hb_codepoint_t old_gid;
+      unsigned int length = c->plan->old_gid_for_new_gid (gid, &old_gid) ? get_glyph_var_data_length (old_gid) : 0;
+
+      if (long_offset)
+	((HBUINT32 *) subset_offsets)[gid] = glyph_offset;
+      else
+	((HBUINT16 *) subset_offsets)[gid] = glyph_offset / 2;
+
+      if (length > 0) memcpy (subset_data, get_glyph_var_data (old_gid), length);
+      subset_data += length;
+      glyph_offset += length;
+    }
+    if (long_offset)
+      ((HBUINT32 *) subset_offsets)[num_glyphs] = glyph_offset;
+    else
+      ((HBUINT16 *) subset_offsets)[num_glyphs] = glyph_offset / 2;
+
+    return_trace (true);
+  }
+
+  protected:
+  const GlyphVarData *get_glyph_var_data (hb_codepoint_t glyph) const
+  {
+    unsigned int start_offset = get_offset (glyph);
+    unsigned int end_offset = get_offset (glyph+1);
+
+    if ((start_offset == end_offset) ||
+	unlikely ((start_offset > get_offset (glyphCount)) ||
+		  (start_offset + GlyphVarData::min_size > end_offset)))
+      return &Null (GlyphVarData);
+    return &(((unsigned char *) this + start_offset) + dataZ);
+  }
+
+  bool is_long_offset () const { return (flags & 1) != 0; }
+
+  unsigned int get_offset (unsigned int i) const
+  {
+    if (is_long_offset ())
+      return get_long_offset_array ()[i];
+    else
+      return get_short_offset_array ()[i] * 2;
+  }
+
+  unsigned int get_glyph_var_data_length (unsigned int glyph) const
+  {
+    unsigned int end_offset = get_offset (glyph + 1);
+    unsigned int start_offset = get_offset (glyph);
+    if (unlikely (start_offset > end_offset || end_offset > get_offset (glyphCount)))
+      return 0;
+    return end_offset - start_offset;
+  }
+
+  const HBUINT32 * get_long_offset_array () const { return (const HBUINT32 *) &offsetZ; }
+  const HBUINT16 *get_short_offset_array () const { return (const HBUINT16 *) &offsetZ; }
+
+  public:
+  struct accelerator_t
+  {
+    void init (hb_face_t *face)
+    {
+      gvar_table = hb_sanitize_context_t ().reference_table<gvar> (face);
+      hb_blob_ptr_t<fvar> fvar_table = hb_sanitize_context_t ().reference_table<fvar> (face);
+      unsigned int axis_count = fvar_table->get_axis_count ();
+      fvar_table.destroy ();
+
+      if (unlikely ((gvar_table->glyphCount != face->get_num_glyphs ()) ||
+		    (gvar_table->axisCount != axis_count)))
+      	fini ();
+
+      unsigned int num_shared_coord = gvar_table->sharedTupleCount * gvar_table->axisCount;
+      shared_tuples.resize (num_shared_coord);
+      for (unsigned int i = 0; i < num_shared_coord; i++)
+	shared_tuples[i] = (&(gvar_table + gvar_table->sharedTuples))[i];
+    }
+
+    void fini ()
+    {
+      gvar_table.destroy ();
+      shared_tuples.fini ();
+    }
+
+    private:
+    struct x_getter { static float get (const contour_point_t &p) { return p.x; } };
+    struct y_getter { static float get (const contour_point_t &p) { return p.y; } };
+
+    template <typename T>
+    static float infer_delta (const hb_array_t<contour_point_t> points,
+			      const hb_array_t<contour_point_t> deltas,
+			      unsigned int target, unsigned int prev, unsigned int next)
+    {
+      float target_val = T::get (points[target]);
+      float prev_val = T::get (points[prev]);
+      float next_val = T::get (points[next]);
+      float prev_delta = T::get (deltas[prev]);
+      float next_delta = T::get (deltas[next]);
+
+      if (prev_val == next_val)
+      	return (prev_delta == next_delta) ? prev_delta : 0.f;
+      else if (target_val <= hb_min (prev_val, next_val))
+      	return (prev_val < next_val) ? prev_delta : next_delta;
+      else if (target_val >= hb_max (prev_val, next_val))
+      	return (prev_val > next_val) ? prev_delta : next_delta;
+
+      /* linear interpolation */
+      float r = (target_val - prev_val) / (next_val - prev_val);
+      return (1.f - r) * prev_delta + r * next_delta;
+    }
+
+    static unsigned int next_index (unsigned int i, unsigned int start, unsigned int end)
+    { return (i >= end) ? start : (i + 1); }
+
+    public:
+    bool apply_deltas_to_points (hb_codepoint_t glyph,
+				 const int *coords, unsigned int coord_count,
+				 const hb_array_t<contour_point_t> points,
+				 const hb_array_t<unsigned int> end_points) const
+    {
+      if (unlikely (coord_count != gvar_table->axisCount)) return false;
+
+      const GlyphVarData *var_data = gvar_table->get_glyph_var_data (glyph);
+      if (var_data == &Null (GlyphVarData)) return true;
+      hb_vector_t<unsigned int> shared_indices;
+      GlyphVarData::tuple_iterator_t iterator;
+      if (!GlyphVarData::get_tuple_iterator (var_data,
+					     gvar_table->get_glyph_var_data_length (glyph),
+					     gvar_table->axisCount,
+					     shared_indices,
+					     &iterator))
+	return false;
+
+      /* Save original points for inferred delta calculation */
+      contour_point_vector_t orig_points;
+      orig_points.resize (points.length);
+      for (unsigned int i = 0; i < orig_points.length; i++)
+	orig_points[i] = points[i];
+
+      contour_point_vector_t deltas; /* flag is used to indicate referenced point */
+      deltas.resize (points.length);
+
+      do
+      {
+	float scalar = iterator.current_tuple->calculate_scalar (coords, coord_count, shared_tuples.as_array ());
+	if (scalar == 0.f) continue;
+	const HBUINT8 *p = iterator.get_serialized_data ();
+	unsigned int length = iterator.current_tuple->get_data_size ();
+	if (unlikely (!iterator.in_range (p, length)))
+	  return false;
+
+	range_checker_t checker (p, length);
+	hb_vector_t<unsigned int> private_indices;
+	if (iterator.current_tuple->has_private_points () &&
+	    !GlyphVarData::unpack_points (p, private_indices, checker))
+	  return false;
+	const hb_array_t<unsigned int> &indices = private_indices.length ? private_indices : shared_indices;
+
+	bool apply_to_all = (indices.length == 0);
+	unsigned int num_deltas = apply_to_all ? points.length : indices.length;
+	hb_vector_t<int> x_deltas;
+	x_deltas.resize (num_deltas);
+	if (!GlyphVarData::unpack_deltas (p, x_deltas, checker))
+	  return false;
+	hb_vector_t<int> y_deltas;
+	y_deltas.resize (num_deltas);
+	if (!GlyphVarData::unpack_deltas (p, y_deltas, checker))
+	  return false;
+
+	for (unsigned int i = 0; i < deltas.length; i++)
+	  deltas[i].init ();
+	for (unsigned int i = 0; i < num_deltas; i++)
+	{
+	  unsigned int pt_index = apply_to_all ? i : indices[i];
+	  deltas[pt_index].flag = 1;	/* this point is referenced, i.e., explicit deltas specified */
+	  deltas[pt_index].x += x_deltas[i] * scalar;
+	  deltas[pt_index].y += y_deltas[i] * scalar;
+	}
+
+	/* infer deltas for unreferenced points */
+	unsigned int start_point = 0;
+	for (unsigned int c = 0; c < end_points.length; c++)
+	{
+	  unsigned int end_point = end_points[c];
+	  unsigned int i, j;
+
+	  /* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */
+	  unsigned int unref_count = 0;
+	  for (i = start_point; i <= end_point; i++)
+	    if (!deltas[i].flag) unref_count++;
+	  if (unref_count == 0 || unref_count > end_point - start_point)
+	    goto no_more_gaps;
+
+	  j = start_point;
+	  for (;;)
+	  {
+	    /* Locate the next gap of unreferenced points between two referenced points prev and next.
+	     * Note that a gap may wrap around at left (start_point) and/or at right (end_point).
+	     */
+	    unsigned int prev, next;
+	    for (;;)
+	    {
+	      i = j;
+	      j = next_index (i, start_point, end_point);
+	      if (deltas[i].flag && !deltas[j].flag) break;
+	    }
+	    prev = j = i;
+	    for (;;)
+	    {
+	      i = j;
+	      j = next_index (i, start_point, end_point);
+	      if (!deltas[i].flag && deltas[j].flag) break;
+	    }
+	    next = j;
+	    /* Infer deltas for all unref points in the gap between prev and next */
+	    i = prev;
+	    for (;;)
+	    {
+	      i = next_index (i, start_point, end_point);
+	      if (i == next) break;
+	      deltas[i].x = infer_delta<x_getter> (orig_points.as_array (), deltas.as_array (), i, prev, next);
+	      deltas[i].y = infer_delta<y_getter> (orig_points.as_array (), deltas.as_array (), i, prev, next);
+	      if (--unref_count == 0) goto no_more_gaps;
+	    }
+	  }
+no_more_gaps:
+	  start_point = end_point + 1;
+	}
+
+	/* apply specified / inferred deltas to points */
+	for (unsigned int i = 0; i < points.length; i++)
+	{
+	  points[i].x += (float) roundf (deltas[i].x);
+	  points[i].y += (float) roundf (deltas[i].y);
+	}
+      } while (iterator.move_to_next ());
+
+      return true;
+    }
+
+    unsigned int get_axis_count () const { return gvar_table->axisCount; }
+
+    protected:
+    const GlyphVarData *get_glyph_var_data (hb_codepoint_t glyph) const
+    { return gvar_table->get_glyph_var_data (glyph); }
+
+    private:
+    hb_blob_ptr_t<gvar> gvar_table;
+    hb_vector_t<F2DOT14> shared_tuples;
+  };
+
+  protected:
+  FixedVersion<>version;	/* Version of gvar table. Set to 0x00010000u. */
+  HBUINT16	axisCount;
+  HBUINT16	sharedTupleCount;
+  LOffsetTo<F2DOT14>
+		sharedTuples;	/* LOffsetTo<UnsizedArrayOf<Tupple>> */
+  HBUINT16	glyphCount;
+  HBUINT16	flags;
+  LOffsetTo<GlyphVarData>
+		dataZ;		/* Array of GlyphVarData */
+  UnsizedArrayOf<HBUINT8>
+		offsetZ;	/* Array of 16-bit or 32-bit (glyphCount+1) offsets */
+  public:
+  DEFINE_SIZE_MIN (20);
+};
+
+struct gvar_accelerator_t : gvar::accelerator_t {};
+
+} /* namespace OT */
+
+#endif /* HB_OT_VAR_GVAR_TABLE_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -114,14 +114,21 @@
 		  rsbMap.sanitize (c, this));
   }
 
-  float get_advance_var (hb_codepoint_t glyph,
-			 const int *coords, unsigned int coord_count) const
+  float get_advance_var (hb_font_t *font, hb_codepoint_t glyph) const
   {
     unsigned int varidx = (this+advMap).map (glyph);
+    return (this+varStore).get_delta (varidx, font->coords, font->num_coords);
+  }
+
+  float get_side_bearing_var (hb_codepoint_t glyph,
+			      const int *coords, unsigned int coord_count) const
+  {
+    if (!has_side_bearing_deltas ()) return 0.f;
+    unsigned int varidx = (this+lsbMap).map (glyph);
     return (this+varStore).get_delta (varidx, coords, coord_count);
   }
 
-  bool has_sidebearing_deltas () const { return lsbMap && rsbMap; }
+  bool has_side_bearing_deltas () const { return lsbMap && rsbMap; }
 
   protected:
   FixedVersion<>version;	/* Version of the metrics variation table

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -154,7 +154,9 @@
  *
  * Shapes @buffer using @font turning its Unicode characters content to
  * positioned glyphs. If @features is not %NULL, it will be used to control the
- * features applied during shaping.
+ * features applied during shaping. If two @features have the same tag but
+ * overlapping ranges the value of the feature with the higher index takes
+ * precedence.
  *
  * Since: 0.9.2
  **/

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -68,8 +68,7 @@
   {
     /* 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;
+    if (unlikely (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++)
     {

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -548,7 +548,7 @@
     /* create a remapping of subroutine numbers from old to new.
      * no optimization based on usage counts. fonttools doesn't appear doing that either.
      */
-    
+
     hb_codepoint_t old_num = HB_SET_VALUE_INVALID;
     while (hb_set_next (closure, &old_num))
       add (old_num);
@@ -916,7 +916,7 @@
 				  hb_set_t *closure,
 				  const subr_subset_param_t &param)
   {
-    hb_set_add (closure, subr_num);
+    closure->add (subr_num);
     collect_subr_refs_in_str (subrs[subr_num], param);
   }
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -389,7 +389,7 @@
     byte_str_ref_t    str_ref = env.str_ref;
     env.call_subr (subrs, type);
     param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num);
-    hb_set_add (closure, env.context.subr_num);
+    closure->add (env.context.subr_num);
     param.set_current_str (env, true);
   }
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -219,7 +219,7 @@
     byte_str_ref_t    str_ref = env.str_ref;
     env.call_subr (subrs, type);
     param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num);
-    hb_set_add (closure, env.context.subr_num);
+    closure->add (env.context.subr_num);
     param.set_current_str (env, true);
   }
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -34,38 +34,17 @@
 #include "hb-ot-var-fvar-table.hh"
 #include "hb-ot-stat-table.hh"
 
-static inline void
-_add_gid_and_children (const OT::glyf::accelerator_t &glyf,
-		       hb_codepoint_t gid,
-		       hb_set_t *gids_to_retain)
-{
-  if (gids_to_retain->has (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());
-  }
-}
-
 #ifndef HB_NO_SUBSET_CFF
 static inline void
 _add_cff_seac_components (const OT::cff1::accelerator_t &cff,
-	   hb_codepoint_t gid,
-	   hb_set_t *gids_to_retain)
+			  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);
+    gids_to_retain->add (base_gid);
+    gids_to_retain->add (accent_gid);
   }
 }
 #endif
@@ -151,7 +130,7 @@
   hb_codepoint_t gid = HB_SET_VALUE_INVALID;
   while (plan->_glyphset_gsub->next (&gid))
   {
-    _add_gid_and_children (glyf, gid, plan->_glyphset);
+    glyf.add_gid_and_children (gid, plan->_glyphset);
 #ifndef HB_NO_SUBSET_CFF
     if (cff.is_valid ())
       _add_cff_seac_components (cff, gid, plan->_glyphset);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -270,9 +270,9 @@
  **/
 hb_bool_t
 hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
-			        hb_user_data_key_t *key,
-			        void *              data,
-			        hb_destroy_func_t   destroy,
+				hb_user_data_key_t *key,
+				void *              data,
+				hb_destroy_func_t   destroy,
 				hb_bool_t           replace)
 {
   return hb_object_set_user_data (ufuncs, key, data, destroy, replace);
@@ -291,7 +291,7 @@
  **/
 void *
 hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
-			        hb_user_data_key_t *key)
+				hb_user_data_key_t *key)
 {
   return hb_object_get_user_data (ufuncs, key);
 }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.h	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.h	2019-10-28 23:44:53 UTC (rev 52560)
@@ -200,15 +200,15 @@
 
 HB_EXTERN hb_bool_t
 hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
-			        hb_user_data_key_t *key,
-			        void *              data,
-			        hb_destroy_func_t   destroy,
+				hb_user_data_key_t *key,
+				void *              data,
+				hb_destroy_func_t   destroy,
 				hb_bool_t           replace);
 
 
 HB_EXTERN void *
 hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
-			        hb_user_data_key_t *key);
+				hb_user_data_key_t *key);
 
 
 HB_EXTERN void
@@ -260,8 +260,8 @@
  * @user_data:
  * @destroy:
  *
- * 
  *
+ *
  * Since: 0.9.2
  **/
 HB_EXTERN void
@@ -276,8 +276,8 @@
  * @user_data:
  * @destroy:
  *
- * 
  *
+ *
  * Since: 0.9.2
  **/
 HB_EXTERN void
@@ -292,8 +292,8 @@
  * @user_data:
  * @destroy:
  *
- * 
  *
+ *
  * Since: 0.9.2
  **/
 HB_EXTERN void
@@ -308,8 +308,8 @@
  * @user_data:
  * @destroy:
  *
- * 
  *
+ *
  * Since: 0.9.2
  **/
 HB_EXTERN void
@@ -324,8 +324,8 @@
  * @user_data:
  * @destroy:
  *
- * 
  *
+ *
  * Since: 0.9.2
  **/
 HB_EXTERN void
@@ -340,8 +340,8 @@
  * @user_data:
  * @destroy:
  *
- * 
  *
+ *
  * Since: 0.9.2
  **/
 HB_EXTERN void

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh	2019-10-28 23:44:53 UTC (rev 52560)
@@ -302,8 +302,8 @@
   { 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
+	      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); }
 };
 

Deleted: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-warning.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-warning.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-warning.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -1,37 +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
- */
-
-#include "hb.hh"
-
-#ifdef 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.hh for possible resolutions."
-#endif
-
-#ifdef HB_MUTEX_IMPL_NIL
-#error "Could not find any system to define mutex macros, library WILL NOT be thread-safe"
-#error "Check hb-mutex.hh for possible resolutions."
-#endif

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -45,7 +45,8 @@
 int
 main (int argc, char **argv)
 {
-  if (argc != 2) {
+  if (argc != 2)
+  {
     fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]);
     exit (1);
   }
@@ -65,7 +66,8 @@
   const OpenTypeFontFile& ot = *sanitized;
 
 
-  switch (ot.get_tag ()) {
+  switch (ot.get_tag ())
+  {
   case OpenTypeFontFile::TrueTypeTag:
     printf ("OpenType font with TrueType outlines\n");
     break;
@@ -91,13 +93,15 @@
 
   int num_fonts = ot.get_face_count ();
   printf ("%d font(s) found in file\n", num_fonts);
-  for (int n_font = 0; n_font < num_fonts; n_font++) {
+  for (int n_font = 0; n_font < num_fonts; n_font++)
+  {
     const OpenTypeFontFace &font = ot.get_face (n_font);
     printf ("Font %d of %d:\n", n_font, num_fonts);
 
     int num_tables = font.get_table_count ();
     printf ("  %d table(s) found in font\n", num_tables);
-    for (int n_table = 0; n_table < num_tables; n_table++) {
+    for (int n_table = 0; n_table < num_tables; n_table++)
+    {
       const OpenTypeTable &table = font.get_table (n_table);
       printf ("  Table %2d of %2d: %.4s (0x%08x+0x%08x)\n", n_table, num_tables,
 	      (const char *) table.tag,
@@ -104,7 +108,8 @@
 	      (unsigned int) table.offset,
 	      (unsigned int) table.length);
 
-      switch (table.tag) {
+      switch (table.tag)
+      {
 
       case HB_OT_TAG_GSUB:
       case HB_OT_TAG_GPOS:
@@ -114,10 +119,11 @@
 
 	int num_scripts = g.get_script_count ();
 	printf ("    %d script(s) found in table\n", num_scripts);
-	for (int n_script = 0; n_script < num_scripts; n_script++) {
+	for (int n_script = 0; n_script < num_scripts; n_script++)
+	{
 	  const Script &script = g.get_script (n_script);
 	  printf ("    Script %2d of %2d: %.4s\n", n_script, num_scripts,
-	          (const char *)g.get_script_tag(n_script));
+		  (const char *)g.get_script_tag(n_script));
 
 	  if (!script.has_default_lang_sys())
 	    printf ("      No default language system\n");
@@ -140,9 +146,10 @@
 
 	    int num_features = langsys.get_feature_count ();
 	    printf ("        %d feature(s) found in language system\n", num_features);
-	    for (int n_feature = 0; n_feature < num_features; n_feature++) {
+	    for (int n_feature = 0; n_feature < num_features; n_feature++)
+	    {
 	      printf ("        Feature index %2d of %2d: %d\n", n_feature, num_features,
-	              langsys.get_feature_index (n_feature));
+		      langsys.get_feature_index (n_feature));
 	    }
 	  }
 	}
@@ -149,25 +156,27 @@
 
 	int num_features = g.get_feature_count ();
 	printf ("    %d feature(s) found in table\n", num_features);
-	for (int n_feature = 0; n_feature < num_features; n_feature++) {
+	for (int n_feature = 0; n_feature < num_features; n_feature++)
+	{
 	  const Feature &feature = g.get_feature (n_feature);
 	  int num_lookups = feature.get_lookup_count ();
 	  printf ("    Feature %2d of %2d: %c%c%c%c\n", n_feature, num_features,
-	          HB_UNTAG(g.get_feature_tag(n_feature)));
+		  HB_UNTAG(g.get_feature_tag(n_feature)));
 
 	  printf ("        %d lookup(s) found in feature\n", num_lookups);
 	  for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++) {
 	    printf ("        Lookup index %2d of %2d: %d\n", n_lookup, num_lookups,
-	            feature.get_lookup_index (n_lookup));
+		    feature.get_lookup_index (n_lookup));
 	  }
 	}
 
 	int num_lookups = g.get_lookup_count ();
 	printf ("    %d lookup(s) found in table\n", num_lookups);
-	for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++) {
+	for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++)
+	{
 	  const Lookup &lookup = g.get_lookup (n_lookup);
 	  printf ("    Lookup %2d of %2d: type %d, props 0x%04X\n", n_lookup, num_lookups,
-	          lookup.get_type(), lookup.get_props());
+		  lookup.get_type(), lookup.get_props());
 	}
 
 	}

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc	2019-10-28 23:44:53 UTC (rev 52560)
@@ -234,7 +234,7 @@
 	    {
 	      hb_set_t *set = hb_set_create ();
 	      for (unsigned int i = 0; i < temp1; ++i)
-	        hb_set_add (set, i);
+		hb_set_add (set, i);
 	      temp1++;
 	      return set;
 	    })

Modified: trunk/Build/source/libs/harfbuzz/version.ac
===================================================================
--- trunk/Build/source/libs/harfbuzz/version.ac	2019-10-28 21:33:01 UTC (rev 52559)
+++ trunk/Build/source/libs/harfbuzz/version.ac	2019-10-28 23:44:53 UTC (rev 52560)
@@ -8,4 +8,4 @@
 dnl --------------------------------------------------------
 dnl
 dnl  m4-include this file to define the current harfbuzz version
-m4_define([harfbuzz_version], [2.6.2])
+m4_define([harfbuzz_version], [2.6.3])



More information about the tex-live-commits mailing list