texlive[59092] Build/source/libs: harfbuzz 2.8.1

commits+kakuto at tug.org commits+kakuto at tug.org
Thu May 6 00:28:05 CEST 2021


Revision: 59092
          http://tug.org/svn/texlive?view=revision&revision=59092
Author:   kakuto
Date:     2021-05-06 00:28:05 +0200 (Thu, 06 May 2021)
Log Message:
-----------
harfbuzz 2.8.1

Modified Paths:
--------------
    trunk/Build/source/libs/README
    trunk/Build/source/libs/harfbuzz/ChangeLog
    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/CMakeLists.txt
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/Makefile.am
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-ankr-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-feat-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-just-table.hh
    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-morx-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-opbd-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-ltag-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.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-cff1-table.hh
    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-colr-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-color-svg-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-gasp-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-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-layout-base-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-gdef-table.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-layout-jstf-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-meta-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-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-fallback.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-avar-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh
    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-hvar-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-mvar-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build
    trunk/Build/source/libs/harfbuzz/version.ac

Added Paths:
-----------
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-priority-queue.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc

Modified: trunk/Build/source/libs/README
===================================================================
--- trunk/Build/source/libs/README	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/README	2021-05-05 22:28:05 UTC (rev 59092)
@@ -25,8 +25,8 @@
   http://sourceforge.net/projects/silgraphite/files/graphite2/
   (requires C++11)
 
-harfbuzz 2.8.0 - checked 18apr21
-  https://github.com/harfbuzz/harfbuzz/releases/download/2.8.0/
+harfbuzz 2.8.1 - checked 06may21
+  https://github.com/harfbuzz/harfbuzz/releases/download/2.8.1/
 
 icu 68.2 - checked 13feb21
   http://download.icu-project.org/files/icu4c/

Modified: trunk/Build/source/libs/harfbuzz/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/ChangeLog	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/ChangeLog	2021-05-05 22:28:05 UTC (rev 59092)
@@ -1,3 +1,8 @@
+2021-05-06  Akira Kakuto  <kakuto at w32tex.org>
+
+	Import harfbuzz-2.8.1.
+	* version.ac: Adjusted.
+
 2021-04-18  Akira Kakuto  <kakuto at w32tex.org>
 
 	Import harfbuzz-2.8.0.

Modified: trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog	2021-05-05 22:28:05 UTC (rev 59092)
@@ -1,3 +1,8 @@
+2021-05-06  Akira Kakuto  <kakuto at w32tex.org>
+
+	Imported harfbuzz-2.8.1 source tree from:
+	https://github.com/harfbuzz/harfbuzz/releases/download/2.8.1/
+
 2021-04-18  Akira Kakuto  <kakuto at w32tex.org>
 
 	Imported harfbuzz-2.8.0 source tree from:

Modified: trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes
===================================================================
--- trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes	2021-05-05 22:28:05 UTC (rev 59092)
@@ -1,5 +1,5 @@
-Changes applied to the harfbuzz-2.8.0/ tree as obtained from:
-	https://github.com/harfbuzz/harfbuzz/releases/download/2.8.0/
+Changes applied to the harfbuzz-2.8.1/ tree as obtained from:
+	https://github.com/harfbuzz/harfbuzz/releases/download/2.8.1/
 
 Removed:
 	COPYING
@@ -22,7 +22,6 @@
         unused dirs:
 	docs
 	m4
-	meson-cc-tests
 	perf
 	subprojects
 	test

Modified: trunk/Build/source/libs/harfbuzz/configure
===================================================================
--- trunk/Build/source/libs/harfbuzz/configure	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/configure	2021-05-05 22:28:05 UTC (rev 59092)
@@ -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.8.0.
+# Generated by GNU Autoconf 2.69 for harfbuzz (TeX Live) 2.8.1.
 #
 # 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.8.0'
-PACKAGE_STRING='harfbuzz (TeX Live) 2.8.0'
+PACKAGE_VERSION='2.8.1'
+PACKAGE_STRING='harfbuzz (TeX Live) 2.8.1'
 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.8.0 to adapt to many kinds of systems.
+\`configure' configures harfbuzz (TeX Live) 2.8.1 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.8.0:";;
+     short | recursive ) echo "Configuration of harfbuzz (TeX Live) 2.8.1:";;
    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.8.0
+harfbuzz (TeX Live) configure 2.8.1
 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.8.0, which was
+It was created by harfbuzz (TeX Live) $as_me 2.8.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4042,7 +4042,7 @@
 
 # Define the identity of the package.
  PACKAGE='harfbuzz--tex-live-'
- VERSION='2.8.0'
+ VERSION='2.8.1'
 
 
 # Some tools Automake needs.
@@ -4236,8 +4236,8 @@
 
 HB_VERSION_MAJOR=2
 HB_VERSION_MINOR=8
-HB_VERSION_MICRO=0
-HB_VERSION=2.8.0
+HB_VERSION_MICRO=1
+HB_VERSION=2.8.1
 
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
@@ -7914,7 +7914,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.8.0, which was
+This file was extended by harfbuzz (TeX Live) $as_me 2.8.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -7980,7 +7980,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.8.0
+harfbuzz (TeX Live) config.status 2.8.1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/CMakeLists.txt
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/CMakeLists.txt	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/CMakeLists.txt	2021-05-05 22:28:05 UTC (rev 59092)
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8.0)
+cmake_minimum_required(VERSION 3.0.0)
 project(harfbuzz)
 
 message(WARN "HarfBuzz has a Meson port and tries to migrate all the other build systems to it, please consider using it as we might remove our cmake port soon.")
@@ -414,8 +414,10 @@
 ## Define harfbuzz library
 add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_headers})
 target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS})
+target_include_directories(harfbuzz PUBLIC
+                           "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>"
+                           "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/harfbuzz>")
 
-
 ## Define harfbuzz-icu library
 if (HB_HAVE_ICU)
   add_library(harfbuzz-icu ${PROJECT_SOURCE_DIR}/src/hb-icu.cc ${PROJECT_SOURCE_DIR}/src/hb-icu.h)

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog	2021-05-05 22:28:05 UTC (rev 59092)
@@ -1,3 +1,2611 @@
+commit b37f03f16b39d397a626f097858e9ae550234ca0
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Tue May 4 02:07:06 2021 +0200
+
+    2.8.1
+
+ NEWS             | 9 +++++++++
+ configure.ac     | 2 +-
+ meson.build      | 2 +-
+ src/hb-version.h | 4 ++--
+ 4 files changed, 13 insertions(+), 4 deletions(-)
+
+commit d3e84413fd512441e62e5200eab6a24d34282e9a
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Sun May 2 01:03:21 2021 +0200
+
+    [ci] Drop macos-10_13_6-aat-fonts job
+    
+    This version of macOS is no longer supported by Homebrew, it takes 26
+    minutes to brew the dependencies before it fails.
+
+ .circleci/config.yml | 14 --------------
+ 1 file changed, 14 deletions(-)
+
+commit 517d68b26e04be63a306cdacec20218a18ede3a4
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Sat May 1 23:50:39 2021 +0200
+
+    [ci] Pin fedora 33 docker image
+    
+    g-ir-scanner is broken on 34 image:
+    
+    FAILED: src/HarfBuzz-0.0.gir
+    /usr/bin/g-ir-scanner --no-libtool --namespace=HarfBuzz --nsversion=0.0 --warn-all --output src/HarfBuzz-0.0.gir --c-include=hb-gobject.h --cflags-begin -DHB_NO_SINGLE_HEADER_ERROR -DHAVE_GOBJECT -DHB_EXTERN= --cflags-end -I/root/project/src -I/root/project/build/src -I./. -I../. --filelist=/root/project/build/src/libharfbuzz-gobject.so.0.20800.0.p/HarfBuzz_0.0_gir_filelist --include=GObject-2.0 --symbol-prefix=hb --symbol-prefix=hb_gobject --identifier-prefix=hb_ --pkg-export=harfbuzz-gobject --cflags-begin -DHAVE_CONFIG_H -I./. -I../. -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/sysprof-4 -I./src/. -I../src/. -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/gobject-introspection-1.0 --cflags-end --add-include-path=/usr/share/gir-1.0 -L/root/project/build/src --extra-library=harfbuzz --library harfbuzz-gobject -L/root/project/build/src -L/root/project/build/src --extra-library=glib-2.0 --extra-library=gobject-2.0 --extra-library=m --extra-library=freetype --extra-library=girepository-1.0 --sources-top-dirs /root/project/subprojects/ --sources-top-dirs /root/project/build/subprojects/
+    ../src/hb-buffer.cc:641: Warning: HarfBuzz: unknown annotation: xconstructor
+    ../src/hb-face.cc:192: Warning: HarfBuzz: unknown annotation: xconstructor
+    ../src/hb-font.cc:551: Warning: HarfBuzz: unknown annotation: xconstructor
+    ../src/hb-font.cc:1519: Warning: HarfBuzz: unknown annotation: xconstructor
+    ../src/hb-map.cc:43: Warning: HarfBuzz: unknown annotation: xconstructor
+    ../src/hb-ot-name.cc:55: Warning: HarfBuzz: unexpected annotation: out
+    ../src/hb-set.cc:43: Warning: HarfBuzz: unknown annotation: xconstructor
+    ../src/hb-shape-plan.cc:173: Warning: HarfBuzz: unknown annotation: xconstructor
+    ../src/hb-shape-plan.cc:201: Warning: HarfBuzz: unknown annotation: xconstructor
+    ../src/hb-unicode.cc:172: Warning: HarfBuzz: unknown annotation: xconstructor
+    g-ir-scanner: link: gcc -pthread -o /root/project/build/tmp-introspecta9rymai3/HarfBuzz-0.0 /root/project/build/tmp-introspecta9rymai3/HarfBuzz-0.0.o -L. -Wl,-rpath,. -Wl,--no-as-needed -L/root/project/build/src -Wl,-rpath,/root/project/build/src -L/root/project/build/src -Wl,-rpath,/root/project/build/src -L/root/project/build/src -Wl,-rpath,/root/project/build/src -lharfbuzz-gobject -lharfbuzz -lglib-2.0 -lgobject-2.0 -lm -lfreetype -lgirepository-1.0 -lgio-2.0 -lgobject-2.0 -Wl,--export-dynamic -lgmodule-2.0 -pthread -lglib-2.0 -lglib-2.0
+    ldd: error: you do not have read permission for `/root/project/build/tmp-introspecta9rymai3/HarfBuzz-0.0'
+    Traceback (most recent call last):
+      File "/usr/bin/g-ir-scanner", line 99, in <module>
+        sys.exit(scanner_main(sys.argv))
+      File "/usr/lib64/gobject-introspection/giscanner/scannermain.py", line 599, in scanner_main
+        shlibs = create_binary(transformer, options, args)
+      File "/usr/lib64/gobject-introspection/giscanner/scannermain.py", line 428, in create_binary
+        shlibs = resolve_shlibs(options, binary, options.libraries)
+      File "/usr/lib64/gobject-introspection/giscanner/shlibs.py", line 170, in resolve_shlibs
+        _resolve_non_libtool(options, binary, non_libtool))
+      File "/usr/lib64/gobject-introspection/giscanner/shlibs.py", line 106, in _resolve_non_libtool
+        output = subprocess.check_output(args)
+      File "/usr/lib64/python3.9/subprocess.py", line 424, in check_output
+        return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
+      File "/usr/lib64/python3.9/subprocess.py", line 528, in run
+        raise CalledProcessError(retcode, process.args,
+    subprocess.CalledProcessError: Command '['ldd', '/root/project/build/tmp-introspecta9rymai3/HarfBuzz-0.0']' returned non-zero exit status 1.
+    ninja: build stopped: subcommand failed.
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 2b7647649a2016e1f10a0eacc2bf2285e1207954
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Apr 30 13:34:16 2021 -0700
+
+    [subset] update test-subset-gpos expected files.
+
+ test/api/fonts/AdobeVFPrototype.WA.gpos.otf | Bin 4148 -> 4096 bytes
+ test/api/fonts/Roboto-Regular-gpos-aw.ttf   | Bin 2236 -> 2228 bytes
+ 2 files changed, 0 insertions(+), 0 deletions(-)
+
+commit be50779cda64d6b7bc8422d6b428892ca829733f
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Apr 30 12:59:17 2021 -0700
+
+    [subset] correct ClassDef format determination.
+    
+    It was possible for glyph_min to be a glyph mapped to class zero which threw off the number of glyph calculation.
+
+ src/hb-ot-layout-common.hh | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+commit 90713f270eeb8286067c141245209814b9e7e706
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Fri Apr 30 16:56:39 2021 +0200
+
+    [hb-ot-layout] Document some return values
+
+ src/hb-ot-layout.cc | 25 +++++++++++++++++++++++--
+ 1 file changed, 23 insertions(+), 2 deletions(-)
+
+commit 46362a954c1408f8e4046d1c2069f2f9d7f80dcd
+Merge: 42bf8e3d4 e25efb31f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Apr 30 11:39:47 2021 -0600
+
+    Merge pull request #2958 from googlefonts/layout_by_default_gr
+    
+    [subset] Enable layout subsetting by default.
+
+commit 42bf8e3d49b789adc00c6d7602ba8c73757ebfaf
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Apr 26 12:31:44 2021 -0600
+
+    [util] Disable chafa's truecolor mode
+    
+    See https://github.com/harfbuzz/harfbuzz/pull/2959#issuecomment-827056111
+
+ util/helper-cairo-ansi.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit c571a96eb0866093f6bece1069f292e34f933421
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Sun Apr 25 15:43:30 2021 +0200
+
+    [ci] Disable Chafa on jobs that enables all auto features
+    
+    No suitable versions are available on these setups.
+
+ .circleci/config.yml           | 2 +-
+ .github/workflows/linux-ci.yml | 2 +-
+ .github/workflows/msys2-ci.yml | 3 ++-
+ 3 files changed, 4 insertions(+), 3 deletions(-)
+
+commit 8298c2f93b0dbe39eae66455c80e68e812213a2f
+Author: Hans Petter Jansson <hpj at hpjansson.org>
+Date:   Fri Apr 23 18:37:58 2021 +0200
+
+    [hb-view] Use Chafa for terminal graphics if available
+    
+    This produces high-quality terminal graphics using symbols or sixels
+    according to the detected terminal capabilities.
+    
+    Fixes #2430.
+
+ configure.ac              |  19 +++++++++
+ meson.build               |   7 ++++
+ meson_options.txt         |   2 +
+ util/Makefile.am          |   2 +
+ util/helper-cairo-ansi.cc | 104 +++++++++++++++++++++++++++++++++++++++++++++-
+ util/meson.build          |   2 +-
+ 6 files changed, 133 insertions(+), 3 deletions(-)
+
+commit e25efb31f21441d29866a2be866abb835b77d7c8
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Apr 23 19:09:37 2021 -0700
+
+    [subset] consider all value formats when computing effective format.
+
+ src/hb-ot-layout-gpos-table.hh | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+commit 84dbfacfec3818478a1e5ac2b9922d25917493ef
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Apr 15 16:52:11 2021 -0700
+
+    [subset] fix collect_variation_idx in PairPosFormat2
+
+ src/hb-ot-layout-common.hh     | 15 ++++++++++-----
+ src/hb-ot-layout-gdef-table.hh |  4 ++--
+ src/hb-ot-layout-gpos-table.hh | 22 ++++++++++++++++++----
+ 3 files changed, 30 insertions(+), 11 deletions(-)
+
+commit d356d0f79c6086e913722a8f40cbc0e59a365c1b
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Apr 23 17:41:09 2021 -0700
+
+    [subset] optimize ValueRecord's for PairPosFormat1.
+
+ src/hb-ot-layout-gpos-table.hh | 53 +++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 52 insertions(+), 1 deletion(-)
+
+commit f9fbe4817ebcb0c88865dc19b7a6e616842a7be6
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Apr 23 17:06:06 2021 -0700
+
+    [subset] implement value record optimization for PairPosFormat2.
+
+ src/hb-ot-layout-gpos-table.hh | 59 ++++++++++++++++++++++++++++--------------
+ 1 file changed, 40 insertions(+), 19 deletions(-)
+
+commit badb8e409bf65a7a0a1f73af735c86870c5c7899
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Apr 23 16:32:56 2021 -0700
+
+    [subset] use copy_values for PairPos serialize.
+
+ src/hb-ot-layout-gpos-table.hh | 111 +++++++++++++++++++++++------------------
+ 1 file changed, 62 insertions(+), 49 deletions(-)
+
+commit 2f50283cd33f20b41a9efd5e851272edacf1d8c1
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Apr 23 15:21:30 2021 -0700
+
+    [subset] Begin implementing ValueRecord optimization:
+    
+    remove value records which have a zero value.
+
+ src/hb-ot-layout-gpos-table.hh | 91 +++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 76 insertions(+), 15 deletions(-)
+
+commit 5df7c668ba530fb5b27e6eed482aa286db3add23
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Apr 22 16:45:14 2021 -0700
+
+    [subset] In SinglePosFormat1 serialize only 1 value record.
+    
+    Previously one record per glyph in the subset was serialized.
+
+ src/hb-ot-layout-gpos-table.hh | 22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+commit 92757f68097aaae74043a5030789289cc3ce514e
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Apr 22 15:18:35 2021 -0700
+
+    [subset] Don't drop anchor device tables when dropping hints. These may contain variation data.
+    
+    Update subseting expected files to match latest version of fontTools.
+
+ src/hb-ot-layout-gpos-table.hh                     |  20 +++++++++-----------
+ .../Comfortaa-Regular-new.default.61,62,63.ttf     | Bin 8100 -> 8100 bytes
+ .../basics/Comfortaa-Regular-new.default.61,63.ttf | Bin 7736 -> 7736 bytes
+ .../basics/Comfortaa-Regular-new.default.61.ttf    | Bin 7360 -> 7360 bytes
+ .../basics/Comfortaa-Regular-new.default.62.ttf    | Bin 6796 -> 6796 bytes
+ ...aa-Regular-new.default.retain-all-codepoint.ttf | Bin 222212 -> 222212 bytes
+ ...Regular-new.drop-hints-retain-gids.61,62,63.ttf | Bin 7032 -> 7012 bytes
+ ...aa-Regular-new.drop-hints-retain-gids.61,63.ttf | Bin 6724 -> 6712 bytes
+ ...ortaa-Regular-new.drop-hints-retain-gids.61.ttf | Bin 6396 -> 6388 bytes
+ ...ortaa-Regular-new.drop-hints-retain-gids.62.ttf | Bin 4396 -> 4396 bytes
+ ...ortaa-Regular-new.drop-hints-retain-gids.63.ttf | Bin 4472 -> 4468 bytes
+ ...drop-hints-retain-gids.retain-all-codepoint.ttf | Bin 187952 -> 190920 bytes
+ .../Comfortaa-Regular-new.drop-hints.61,62,63.ttf  | Bin 3444 -> 3424 bytes
+ .../Comfortaa-Regular-new.drop-hints.61,63.ttf     | Bin 3140 -> 3128 bytes
+ .../basics/Comfortaa-Regular-new.drop-hints.61.ttf | Bin 2804 -> 2800 bytes
+ .../basics/Comfortaa-Regular-new.drop-hints.62.ttf | Bin 2396 -> 2396 bytes
+ .../basics/Comfortaa-Regular-new.drop-hints.63.ttf | Bin 2464 -> 2460 bytes
+ ...Regular-new.drop-hints.retain-all-codepoint.ttf | Bin 187944 -> 190908 bytes
+ .../basics/Comfortaa-Regular-new.gids.61,62,63.ttf | Bin 9036 -> 9036 bytes
+ .../basics/Comfortaa-Regular-new.gids.61,63.ttf    | Bin 8668 -> 8668 bytes
+ .../basics/Comfortaa-Regular-new.gids.61.ttf       | Bin 8304 -> 8304 bytes
+ .../basics/Comfortaa-Regular-new.gids.62.ttf       | Bin 8236 -> 8236 bytes
+ .../basics/Comfortaa-Regular-new.gids.63.ttf       | Bin 8220 -> 8220 bytes
+ ...ortaa-Regular-new.gids.retain-all-codepoint.ttf | Bin 222212 -> 222212 bytes
+ .../Comfortaa-Regular-new.name-ids.61,62,63.ttf    | Bin 7840 -> 7840 bytes
+ .../Comfortaa-Regular-new.name-ids.61,63.ttf       | Bin 7476 -> 7476 bytes
+ .../basics/Comfortaa-Regular-new.name-ids.61.ttf   | Bin 7100 -> 7100 bytes
+ .../basics/Comfortaa-Regular-new.name-ids.62.ttf   | Bin 6536 -> 6536 bytes
+ ...a-Regular-new.name-ids.retain-all-codepoint.ttf | Bin 221952 -> 221952 bytes
+ ...mfortaa-Regular-new.name-languages.61,62,63.ttf | Bin 8100 -> 8100 bytes
+ .../Comfortaa-Regular-new.name-languages.61,63.ttf | Bin 7736 -> 7736 bytes
+ .../Comfortaa-Regular-new.name-languages.61.ttf    | Bin 7360 -> 7360 bytes
+ .../Comfortaa-Regular-new.name-languages.62.ttf    | Bin 6796 -> 6796 bytes
+ ...lar-new.name-languages.retain-all-codepoint.ttf | Bin 222212 -> 222212 bytes
+ .../Comfortaa-Regular-new.name-legacy.61,62,63.ttf | Bin 8100 -> 8100 bytes
+ .../Comfortaa-Regular-new.name-legacy.61,63.ttf    | Bin 7736 -> 7736 bytes
+ .../Comfortaa-Regular-new.name-legacy.61.ttf       | Bin 7360 -> 7360 bytes
+ .../Comfortaa-Regular-new.name-legacy.62.ttf       | Bin 6796 -> 6796 bytes
+ ...egular-new.name-legacy.retain-all-codepoint.ttf | Bin 222212 -> 222212 bytes
+ .../Comfortaa-Regular-new.retain-gids.61,62,63.ttf | Bin 11688 -> 11688 bytes
+ .../Comfortaa-Regular-new.retain-gids.61,63.ttf    | Bin 11320 -> 11320 bytes
+ .../Comfortaa-Regular-new.retain-gids.61.ttf       | Bin 10952 -> 10952 bytes
+ .../Comfortaa-Regular-new.retain-gids.62.ttf       | Bin 8796 -> 8796 bytes
+ ...egular-new.retain-gids.retain-all-codepoint.ttf | Bin 222224 -> 222224 bytes
+ ...Regular.abc.drop-hints-retain-gids.61,62,63.ttf | Bin 1208 -> 1192 bytes
+ ...to-Regular.abc.drop-hints-retain-gids.61,63.ttf | Bin 1136 -> 1124 bytes
+ ...oboto-Regular.abc.drop-hints-retain-gids.61.ttf | Bin 988 -> 984 bytes
+ ...oboto-Regular.abc.drop-hints-retain-gids.63.ttf | Bin 972 -> 968 bytes
+ ...drop-hints-retain-gids.retain-all-codepoint.ttf | Bin 1208 -> 1192 bytes
+ .../Roboto-Regular.abc.drop-hints.61,62,63.ttf     | Bin 1208 -> 1192 bytes
+ .../basics/Roboto-Regular.abc.drop-hints.61,63.ttf | Bin 1120 -> 1108 bytes
+ .../basics/Roboto-Regular.abc.drop-hints.61.ttf    | Bin 988 -> 984 bytes
+ .../basics/Roboto-Regular.abc.drop-hints.63.ttf    | Bin 960 -> 956 bytes
+ ...Regular.abc.drop-hints.retain-all-codepoint.ttf | Bin 1208 -> 1192 bytes
+ ...subroutinize-retain-gids.1FC,21,41,20,62,63.otf | Bin 30500 -> 30488 bytes
+ ...rop-hints-desubroutinize.1FC,21,41,20,62,63.otf | Bin 3680 -> 3668 bytes
+ ...r.drop-hints-retain-gids.1FC,21,41,20,62,63.otf | Bin 30636 -> 30624 bytes
+ ...nsPro-Regular.drop-hints.1FC,21,41,20,62,63.otf | Bin 3820 -> 3808 bytes
+ .../Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf   | Bin 2192 -> 2184 bytes
+ ...ifVariable-Roman.default.1FC,21,41,20,62,63.ttf | Bin 6876 -> 6876 bytes
+ .../SourceSerifVariable-Roman.default.61,62,63.ttf | Bin 6552 -> 6552 bytes
+ ...ariable-Roman.drop-hints.1FC,21,41,20,62,63.ttf | Bin 6612 -> 6832 bytes
+ ...urceSerifVariable-Roman.drop-hints.61,62,63.ttf | Bin 6356 -> 6552 bytes
+ ...rifVariable-Roman.drop-hints.D7,D8,D9,DA,DE.ttf | Bin 5880 -> 6136 bytes
+ .../AdobeVFPrototype.drop-hints.41,42,43,57.otf    | Bin 5180 -> 5272 bytes
+ .../AdobeVFPrototype.drop-hints.41,42,43.otf       | Bin 4688 -> 4744 bytes
+ .../AdobeVFPrototype.drop-hints.41,42.otf          | Bin 4236 -> 4264 bytes
+ .../AdobeVFPrototype.drop-hints.41,56,57.otf       | Bin 4348 -> 4408 bytes
+ .../AdobeVFPrototype.drop-hints.41.otf             | Bin 3552 -> 3560 bytes
+ .../AdobeVFPrototype.drop-hints.42,57.otf          | Bin 4364 -> 4396 bytes
+ .../Roboto-Regular.drop-hints.1E00,303.ttf         | Bin 1468 -> 1464 bytes
+ .../expected/layout.khmer/Khmer.default.1780.ttf   | Bin 0 -> 4204 bytes
+ ...ult.1789,17BB,17C6,1794,17B6,1793,1798,17BE.ttf | Bin 0 -> 6412 bytes
+ .../expected/layout.khmer/Khmer.default.31.ttf     | Bin 0 -> 4140 bytes
+ .../layout.khmer/Khmer.retain-gids.1780.ttf        | Bin 0 -> 4464 bytes
+ ...ids.1789,17BB,17C6,1794,17B6,1793,1798,17BE.ttf | Bin 0 -> 7848 bytes
+ .../expected/layout.khmer/Khmer.retain-gids.31.ttf | Bin 0 -> 4256 bytes
+ .../variable/Fraunces.default.26,66,69,124,125.ttf | Bin 0 -> 18448 bytes
+ .../data/expected/variable/Fraunces.default.61.ttf | Bin 0 -> 5880 bytes
+ 79 files changed, 9 insertions(+), 11 deletions(-)
+
+commit 6fddc2bbf9224bde4327e1792a683de637ad5613
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Apr 1 15:34:17 2021 -0700
+
+    [subset] subset layout tables (G*) by default.
+
+ src/hb-subset-input.cc                             |   3 ---
+ .../Comfortaa-Regular-new.default.61,62,63.ttf     | Bin 7392 -> 8100 bytes
+ .../basics/Comfortaa-Regular-new.default.61,63.ttf | Bin 7036 -> 7736 bytes
+ .../basics/Comfortaa-Regular-new.default.61.ttf    | Bin 6684 -> 7360 bytes
+ .../basics/Comfortaa-Regular-new.default.62.ttf    | Bin 6628 -> 6796 bytes
+ .../basics/Comfortaa-Regular-new.default.63.ttf    | Bin 6608 -> 6844 bytes
+ ...aa-Regular-new.default.retain-all-codepoint.ttf | Bin 182876 -> 222212 bytes
+ ...Regular-new.drop-hints-retain-gids.61,62,63.ttf | Bin 4844 -> 7032 bytes
+ ...aa-Regular-new.drop-hints-retain-gids.61,63.ttf | Bin 4552 -> 6724 bytes
+ ...ortaa-Regular-new.drop-hints-retain-gids.61.ttf | Bin 3988 -> 6396 bytes
+ ...ortaa-Regular-new.drop-hints-retain-gids.62.ttf | Bin 4228 -> 4396 bytes
+ ...ortaa-Regular-new.drop-hints-retain-gids.63.ttf | Bin 4236 -> 4472 bytes
+ ...drop-hints-retain-gids.retain-all-codepoint.ttf | Bin 151672 -> 187952 bytes
+ .../Comfortaa-Regular-new.drop-hints.61,62,63.ttf  | Bin 2852 -> 3444 bytes
+ .../Comfortaa-Regular-new.drop-hints.61,63.ttf     | Bin 2552 -> 3140 bytes
+ .../basics/Comfortaa-Regular-new.drop-hints.61.ttf | Bin 2240 -> 2804 bytes
+ .../basics/Comfortaa-Regular-new.drop-hints.62.ttf | Bin 2228 -> 2396 bytes
+ .../basics/Comfortaa-Regular-new.drop-hints.63.ttf | Bin 2228 -> 2464 bytes
+ ...Regular-new.drop-hints.retain-all-codepoint.ttf | Bin 151608 -> 187944 bytes
+ .../basics/Comfortaa-Regular-new.gids.61,62,63.ttf | Bin 8296 -> 9036 bytes
+ .../basics/Comfortaa-Regular-new.gids.61,63.ttf    | Bin 7944 -> 8668 bytes
+ .../basics/Comfortaa-Regular-new.gids.61.ttf       | Bin 7588 -> 8304 bytes
+ .../basics/Comfortaa-Regular-new.gids.62.ttf       | Bin 7528 -> 8236 bytes
+ .../basics/Comfortaa-Regular-new.gids.63.ttf       | Bin 7516 -> 8220 bytes
+ ...ortaa-Regular-new.gids.retain-all-codepoint.ttf | Bin 182876 -> 222212 bytes
+ ...Regular-new.keep-layout-drop-hints.61,62,63.ttf | Bin 3444 -> 0 bytes
+ ...aa-Regular-new.keep-layout-drop-hints.61,63.ttf | Bin 3140 -> 0 bytes
+ ...ortaa-Regular-new.keep-layout-drop-hints.61.ttf | Bin 2804 -> 0 bytes
+ ...ortaa-Regular-new.keep-layout-drop-hints.62.ttf | Bin 2396 -> 0 bytes
+ ...ortaa-Regular-new.keep-layout-drop-hints.63.ttf | Bin 2464 -> 0 bytes
+ ...keep-layout-drop-hints.retain-all-codepoint.ttf | Bin 187944 -> 0 bytes
+ .../Comfortaa-Regular-new.keep-layout.61,62,63.ttf | Bin 8100 -> 0 bytes
+ .../Comfortaa-Regular-new.keep-layout.61,63.ttf    | Bin 7736 -> 0 bytes
+ .../Comfortaa-Regular-new.keep-layout.61.ttf       | Bin 7360 -> 0 bytes
+ .../Comfortaa-Regular-new.keep-layout.62.ttf       | Bin 6796 -> 0 bytes
+ .../Comfortaa-Regular-new.keep-layout.63.ttf       | Bin 6844 -> 0 bytes
+ ...egular-new.keep-layout.retain-all-codepoint.ttf | Bin 222212 -> 0 bytes
+ .../Comfortaa-Regular-new.name-ids.61,62,63.ttf    | Bin 7132 -> 7840 bytes
+ .../Comfortaa-Regular-new.name-ids.61,63.ttf       | Bin 6776 -> 7476 bytes
+ .../basics/Comfortaa-Regular-new.name-ids.61.ttf   | Bin 6424 -> 7100 bytes
+ .../basics/Comfortaa-Regular-new.name-ids.62.ttf   | Bin 6368 -> 6536 bytes
+ .../basics/Comfortaa-Regular-new.name-ids.63.ttf   | Bin 6348 -> 6584 bytes
+ ...a-Regular-new.name-ids.retain-all-codepoint.ttf | Bin 182616 -> 221952 bytes
+ ...mfortaa-Regular-new.name-languages.61,62,63.ttf | Bin 7392 -> 8100 bytes
+ .../Comfortaa-Regular-new.name-languages.61,63.ttf | Bin 7036 -> 7736 bytes
+ .../Comfortaa-Regular-new.name-languages.61.ttf    | Bin 6684 -> 7360 bytes
+ .../Comfortaa-Regular-new.name-languages.62.ttf    | Bin 6628 -> 6796 bytes
+ .../Comfortaa-Regular-new.name-languages.63.ttf    | Bin 6608 -> 6844 bytes
+ ...lar-new.name-languages.retain-all-codepoint.ttf | Bin 182876 -> 222212 bytes
+ .../Comfortaa-Regular-new.name-legacy.61,62,63.ttf | Bin 7392 -> 8100 bytes
+ .../Comfortaa-Regular-new.name-legacy.61,63.ttf    | Bin 7036 -> 7736 bytes
+ .../Comfortaa-Regular-new.name-legacy.61.ttf       | Bin 6684 -> 7360 bytes
+ .../Comfortaa-Regular-new.name-legacy.62.ttf       | Bin 6628 -> 6796 bytes
+ .../Comfortaa-Regular-new.name-legacy.63.ttf       | Bin 6608 -> 6844 bytes
+ ...egular-new.name-legacy.retain-all-codepoint.ttf | Bin 182876 -> 222212 bytes
+ .../Comfortaa-Regular-new.retain-gids.61,62,63.ttf | Bin 9384 -> 11688 bytes
+ .../Comfortaa-Regular-new.retain-gids.61,63.ttf    | Bin 9036 -> 11320 bytes
+ .../Comfortaa-Regular-new.retain-gids.61.ttf       | Bin 8432 -> 10952 bytes
+ .../Comfortaa-Regular-new.retain-gids.62.ttf       | Bin 8628 -> 8796 bytes
+ .../Comfortaa-Regular-new.retain-gids.63.ttf       | Bin 8616 -> 8852 bytes
+ ...egular-new.retain-gids.retain-all-codepoint.ttf | Bin 182940 -> 222224 bytes
+ ...ular-subset.keep-layout-drop-hints.61,62,63.ttf | Bin 1452 -> 0 bytes
+ ...Regular-subset.keep-layout-drop-hints.61,63.ttf | Bin 1276 -> 0 bytes
+ ...jo-Regular-subset.keep-layout-drop-hints.61.ttf | Bin 1128 -> 0 bytes
+ ...jo-Regular-subset.keep-layout-drop-hints.62.ttf | Bin 1140 -> 0 bytes
+ ...jo-Regular-subset.keep-layout-drop-hints.63.ttf | Bin 1104 -> 0 bytes
+ ...keep-layout-drop-hints.retain-all-codepoint.ttf | Bin 3536 -> 0 bytes
+ ...yeongjo-Regular-subset.keep-layout.61,62,63.ttf | Bin 4128 -> 0 bytes
+ ...umMyeongjo-Regular-subset.keep-layout.61,63.ttf | Bin 3580 -> 0 bytes
+ ...NanumMyeongjo-Regular-subset.keep-layout.61.ttf | Bin 3156 -> 0 bytes
+ ...NanumMyeongjo-Regular-subset.keep-layout.62.ttf | Bin 3180 -> 0 bytes
+ ...NanumMyeongjo-Regular-subset.keep-layout.63.ttf | Bin 3048 -> 0 bytes
+ ...lar-subset.keep-layout.retain-all-codepoint.ttf | Bin 9524 -> 0 bytes
+ .../basics/Roboto-Regular.abc.default.61,62,63.ttf | Bin 2168 -> 2452 bytes
+ .../basics/Roboto-Regular.abc.default.61,63.ttf    | Bin 1988 -> 2260 bytes
+ .../basics/Roboto-Regular.abc.default.61.ttf       | Bin 1792 -> 2048 bytes
+ .../basics/Roboto-Regular.abc.default.62.ttf       | Bin 1740 -> 1916 bytes
+ .../basics/Roboto-Regular.abc.default.63.ttf       | Bin 1716 -> 1972 bytes
+ ...to-Regular.abc.default.retain-all-codepoint.ttf | Bin 2168 -> 2452 bytes
+ ...Regular.abc.drop-hints-retain-gids.61,62,63.ttf | Bin 924 -> 1208 bytes
+ ...to-Regular.abc.drop-hints-retain-gids.61,63.ttf | Bin 856 -> 1136 bytes
+ ...oboto-Regular.abc.drop-hints-retain-gids.61.ttf | Bin 732 -> 988 bytes
+ ...oboto-Regular.abc.drop-hints-retain-gids.62.ttf | Bin 704 -> 880 bytes
+ ...oboto-Regular.abc.drop-hints-retain-gids.63.ttf | Bin 716 -> 972 bytes
+ ...drop-hints-retain-gids.retain-all-codepoint.ttf | Bin 924 -> 1208 bytes
+ .../Roboto-Regular.abc.drop-hints.61,62,63.ttf     | Bin 924 -> 1208 bytes
+ .../basics/Roboto-Regular.abc.drop-hints.61,63.ttf | Bin 848 -> 1120 bytes
+ .../basics/Roboto-Regular.abc.drop-hints.61.ttf    | Bin 732 -> 988 bytes
+ .../basics/Roboto-Regular.abc.drop-hints.62.ttf    | Bin 700 -> 876 bytes
+ .../basics/Roboto-Regular.abc.drop-hints.63.ttf    | Bin 704 -> 960 bytes
+ ...Regular.abc.drop-hints.retain-all-codepoint.ttf | Bin 924 -> 1208 bytes
+ .../basics/Roboto-Regular.abc.gids.61,62,63.ttf    | Bin 2168 -> 2452 bytes
+ .../basics/Roboto-Regular.abc.gids.61,63.ttf       | Bin 2168 -> 2452 bytes
+ .../expected/basics/Roboto-Regular.abc.gids.61.ttf | Bin 2168 -> 2452 bytes
+ .../expected/basics/Roboto-Regular.abc.gids.62.ttf | Bin 2168 -> 2452 bytes
+ .../expected/basics/Roboto-Regular.abc.gids.63.ttf | Bin 2168 -> 2452 bytes
+ ...oboto-Regular.abc.gids.retain-all-codepoint.ttf | Bin 2168 -> 2452 bytes
+ ...Regular.abc.keep-layout-drop-hints.61,62,63.ttf | Bin 1208 -> 0 bytes
+ ...to-Regular.abc.keep-layout-drop-hints.61,63.ttf | Bin 1120 -> 0 bytes
+ ...oboto-Regular.abc.keep-layout-drop-hints.61.ttf | Bin 988 -> 0 bytes
+ ...oboto-Regular.abc.keep-layout-drop-hints.62.ttf | Bin 876 -> 0 bytes
+ ...oboto-Regular.abc.keep-layout-drop-hints.63.ttf | Bin 960 -> 0 bytes
+ ...keep-layout-drop-hints.retain-all-codepoint.ttf | Bin 1208 -> 0 bytes
+ .../Roboto-Regular.abc.keep-layout.61,62,63.ttf    | Bin 2452 -> 0 bytes
+ .../Roboto-Regular.abc.keep-layout.61,63.ttf       | Bin 2260 -> 0 bytes
+ .../basics/Roboto-Regular.abc.keep-layout.61.ttf   | Bin 2048 -> 0 bytes
+ .../basics/Roboto-Regular.abc.keep-layout.62.ttf   | Bin 1916 -> 0 bytes
+ .../basics/Roboto-Regular.abc.keep-layout.63.ttf   | Bin 1972 -> 0 bytes
+ ...egular.abc.keep-layout.retain-all-codepoint.ttf | Bin 2452 -> 0 bytes
+ .../Roboto-Regular.abc.name-ids.61,62,63.ttf       | Bin 2168 -> 2452 bytes
+ .../basics/Roboto-Regular.abc.name-ids.61,63.ttf   | Bin 1988 -> 2260 bytes
+ .../basics/Roboto-Regular.abc.name-ids.61.ttf      | Bin 1792 -> 2048 bytes
+ .../basics/Roboto-Regular.abc.name-ids.62.ttf      | Bin 1740 -> 1916 bytes
+ .../basics/Roboto-Regular.abc.name-ids.63.ttf      | Bin 1716 -> 1972 bytes
+ ...o-Regular.abc.name-ids.retain-all-codepoint.ttf | Bin 2168 -> 2452 bytes
+ .../Roboto-Regular.abc.name-languages.61,62,63.ttf | Bin 2168 -> 2452 bytes
+ .../Roboto-Regular.abc.name-languages.61,63.ttf    | Bin 1988 -> 2260 bytes
+ .../Roboto-Regular.abc.name-languages.61.ttf       | Bin 1792 -> 2048 bytes
+ .../Roboto-Regular.abc.name-languages.62.ttf       | Bin 1740 -> 1916 bytes
+ .../Roboto-Regular.abc.name-languages.63.ttf       | Bin 1716 -> 1972 bytes
+ ...lar.abc.name-languages.retain-all-codepoint.ttf | Bin 2168 -> 2452 bytes
+ .../Roboto-Regular.abc.name-legacy.61,62,63.ttf    | Bin 2168 -> 2452 bytes
+ .../Roboto-Regular.abc.name-legacy.61,63.ttf       | Bin 1988 -> 2260 bytes
+ .../basics/Roboto-Regular.abc.name-legacy.61.ttf   | Bin 1792 -> 2048 bytes
+ .../basics/Roboto-Regular.abc.name-legacy.62.ttf   | Bin 1740 -> 1916 bytes
+ .../basics/Roboto-Regular.abc.name-legacy.63.ttf   | Bin 1716 -> 1972 bytes
+ ...egular.abc.name-legacy.retain-all-codepoint.ttf | Bin 2168 -> 2452 bytes
+ .../Roboto-Regular.abc.retain-gids.61,62,63.ttf    | Bin 2168 -> 2452 bytes
+ .../Roboto-Regular.abc.retain-gids.61,63.ttf       | Bin 1996 -> 2276 bytes
+ .../basics/Roboto-Regular.abc.retain-gids.61.ttf   | Bin 1792 -> 2048 bytes
+ .../basics/Roboto-Regular.abc.retain-gids.62.ttf   | Bin 1748 -> 1924 bytes
+ .../basics/Roboto-Regular.abc.retain-gids.63.ttf   | Bin 1732 -> 1988 bytes
+ ...egular.abc.retain-gids.retain-all-codepoint.ttf | Bin 2168 -> 2452 bytes
+ ...olorEmoji.subset.index_format3.default.2049.ttf | Bin 3112 -> 3108 bytes
+ ...rEmoji.subset.index_format3.default.38,2049.ttf | Bin 4080 -> 4076 bytes
+ ...rEmoji.subset.index_format3.default.38,20E3.ttf | Bin 3564 -> 3560 bytes
+ ...index_format3.default.38,39,AE,2049,38,20E3.ttf | Bin 10112 -> 10112 bytes
+ ...oji.subset.index_format3.default.38,AE,2049.ttf | Bin 7536 -> 7536 bytes
+ ...oColorEmoji.subset.index_format3.default.39.ttf | Bin 1920 -> 1916 bytes
+ ...oColorEmoji.subset.index_format3.default.AE.ttf | Bin 4412 -> 4408 bytes
+ ...t.index_format3.drop-hints-retain-gids.2049.ttf | Bin 3136 -> 3132 bytes
+ ...ndex_format3.drop-hints-retain-gids.38,2049.ttf | Bin 4104 -> 4100 bytes
+ ...ndex_format3.drop-hints-retain-gids.38,20E3.ttf | Bin 3596 -> 3592 bytes
+ ...rop-hints-retain-gids.38,39,AE,2049,38,20E3.ttf | Bin 10112 -> 10112 bytes
+ ...x_format3.drop-hints-retain-gids.38,AE,2049.ttf | Bin 7556 -> 7552 bytes
+ ...set.index_format3.drop-hints-retain-gids.39.ttf | Bin 1928 -> 1924 bytes
+ ...set.index_format3.drop-hints-retain-gids.AE.ttf | Bin 4428 -> 4424 bytes
+ ...rEmoji.subset.index_format3.drop-hints.2049.ttf | Bin 3112 -> 3108 bytes
+ ...oji.subset.index_format3.drop-hints.38,2049.ttf | Bin 4080 -> 4076 bytes
+ ...oji.subset.index_format3.drop-hints.38,20E3.ttf | Bin 3564 -> 3560 bytes
+ ...ex_format3.drop-hints.38,39,AE,2049,38,20E3.ttf | Bin 10112 -> 10112 bytes
+ ....subset.index_format3.drop-hints.38,AE,2049.ttf | Bin 7536 -> 7536 bytes
+ ...lorEmoji.subset.index_format3.drop-hints.39.ttf | Bin 1920 -> 1916 bytes
+ ...lorEmoji.subset.index_format3.drop-hints.AE.ttf | Bin 4412 -> 4408 bytes
+ ...Emoji.subset.index_format3.retain-gids.2049.ttf | Bin 3136 -> 3132 bytes
+ ...ji.subset.index_format3.retain-gids.38,2049.ttf | Bin 4104 -> 4100 bytes
+ ...ji.subset.index_format3.retain-gids.38,20E3.ttf | Bin 3596 -> 3592 bytes
+ ...x_format3.retain-gids.38,39,AE,2049,38,20E3.ttf | Bin 10112 -> 10112 bytes
+ ...subset.index_format3.retain-gids.38,AE,2049.ttf | Bin 7556 -> 7552 bytes
+ ...orEmoji.subset.index_format3.retain-gids.39.ttf | Bin 1928 -> 1924 bytes
+ ...orEmoji.subset.index_format3.retain-gids.AE.ttf | Bin 4428 -> 4424 bytes
+ ...eSansPro-Regular.default.1FC,21,41,20,62,63.otf | Bin 2180 -> 4192 bytes
+ .../SourceSansPro-Regular.default.61,62,63.otf     | Bin 1892 -> 3856 bytes
+ ...ourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf | Bin 2008 -> 3144 bytes
+ ...subroutinize-retain-gids.1FC,21,41,20,62,63.otf | Bin 19796 -> 30788 bytes
+ ...Regular.desubroutinize-retain-gids.61,62,63.otf | Bin 1992 -> 30908 bytes
+ ...r.desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf | Bin 30208 -> 31336 bytes
+ ...o-Regular.desubroutinize.1FC,21,41,20,62,63.otf | Bin 2036 -> 3968 bytes
+ ...urceSansPro-Regular.desubroutinize.61,62,63.otf | Bin 1796 -> 3556 bytes
+ ...nsPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf | Bin 1992 -> 3168 bytes
+ ...subroutinize-retain-gids.1FC,21,41,20,62,63.otf | Bin 19636 -> 30500 bytes
+ ...p-hints-desubroutinize-retain-gids.61,62,63.otf | Bin 1868 -> 30668 bytes
+ ...s-desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf | Bin 30060 -> 31124 bytes
+ ...rop-hints-desubroutinize.1FC,21,41,20,62,63.otf | Bin 1876 -> 3680 bytes
+ ...-Regular.drop-hints-desubroutinize.61,62,63.otf | Bin 1672 -> 3320 bytes
+ ...ar.drop-hints-desubroutinize.D7,D8,D9,DA,DE.otf | Bin 1844 -> 2952 bytes
+ ...r.drop-hints-retain-gids.1FC,21,41,20,62,63.otf | Bin 19728 -> 30636 bytes
+ ...Pro-Regular.drop-hints-retain-gids.61,62,63.otf | Bin 1904 -> 30888 bytes
+ ...gular.drop-hints-retain-gids.D7,D8,D9,DA,DE.otf | Bin 30072 -> 31104 bytes
+ ...nsPro-Regular.drop-hints.1FC,21,41,20,62,63.otf | Bin 1960 -> 3820 bytes
+ .../SourceSansPro-Regular.drop-hints.61,62,63.otf  | Bin 1736 -> 3524 bytes
+ ...ceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf | Bin 1860 -> 2932 bytes
+ ...sPro-Regular.retain-gids.1FC,21,41,20,62,63.otf | Bin 19948 -> 31012 bytes
+ .../SourceSansPro-Regular.retain-gids.61,62,63.otf | Bin 2060 -> 31208 bytes
+ ...eSansPro-Regular.retain-gids.D7,D8,D9,DA,DE.otf | Bin 30224 -> 31312 bytes
+ ...ubset.default.3042,3044,3046,3048,304A,304B.otf | Bin 3036 -> 4884 bytes
+ ...ubset.default.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 3248 -> 6276 bytes
+ ...eHanSans-Regular_subset.default.61,63,65,6B.otf | Bin 2208 -> 2588 bytes
+ ...ubset.default.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 3468 -> 6736 bytes
+ .../SourceHanSans-Regular_subset.default.660E.otf  | Bin 1928 -> 2456 bytes
+ ...e-retain-gids.3042,3044,3046,3048,304A,304B.otf | Bin 8932 -> 129876 bytes
+ ...e-retain-gids.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 116080 -> 130920 bytes
+ ...bset.desubroutinize-retain-gids.61,63,65,6B.otf | Bin 3016 -> 3412 bytes
+ ...e-retain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 116264 -> 122048 bytes
+ ...ular_subset.desubroutinize-retain-gids.660E.otf | Bin 50224 -> 50760 bytes
+ ...esubroutinize.3042,3044,3046,3048,304A,304B.otf | Bin 2960 -> 4724 bytes
+ ...esubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 3144 -> 5928 bytes
+ ...s-Regular_subset.desubroutinize.61,63,65,6B.otf | Bin 2140 -> 2520 bytes
+ ...esubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 3264 -> 6232 bytes
+ ...eHanSans-Regular_subset.desubroutinize.660E.otf | Bin 1904 -> 2440 bytes
+ ...e-retain-gids.3042,3044,3046,3048,304A,304B.otf | Bin 8672 -> 129448 bytes
+ ...e-retain-gids.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 115768 -> 130312 bytes
+ ...ints-desubroutinize-retain-gids.61,63,65,6B.otf | Bin 2892 -> 3288 bytes
+ ...e-retain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 115884 -> 121284 bytes
+ ....drop-hints-desubroutinize-retain-gids.660E.otf | Bin 50040 -> 50540 bytes
+ ...esubroutinize.3042,3044,3046,3048,304A,304B.otf | Bin 2800 -> 4420 bytes
+ ...esubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 2904 -> 5416 bytes
+ ...ubset.drop-hints-desubroutinize.61,63,65,6B.otf | Bin 2036 -> 2416 bytes
+ ...esubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 2972 -> 5556 bytes
+ ...gular_subset.drop-hints-desubroutinize.660E.otf | Bin 1812 -> 2308 bytes
+ ...s-retain-gids.3042,3044,3046,3048,304A,304B.otf | Bin 8740 -> 129576 bytes
+ ...s-retain-gids.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 115864 -> 130604 bytes
+ ...r_subset.drop-hints-retain-gids.61,63,65,6B.otf | Bin 2852 -> 3248 bytes
+ ...s-retain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 116084 -> 121776 bytes
+ ...-Regular_subset.drop-hints-retain-gids.660E.otf | Bin 50060 -> 50552 bytes
+ ...et.drop-hints.3042,3044,3046,3048,304A,304B.otf | Bin 2856 -> 4548 bytes
+ ...et.drop-hints.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 2996 -> 5708 bytes
+ ...nSans-Regular_subset.drop-hints.61,63,65,6B.otf | Bin 2068 -> 2448 bytes
+ ...et.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 3172 -> 6048 bytes
+ ...ourceHanSans-Regular_subset.drop-hints.660E.otf | Bin 1832 -> 2316 bytes
+ ...t.retain-gids.3042,3044,3046,3048,304A,304B.otf | Bin 9016 -> 130036 bytes
+ ...t.retain-gids.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 116184 -> 131272 bytes
+ ...Sans-Regular_subset.retain-gids.61,63,65,6B.otf | Bin 3012 -> 3408 bytes
+ ...t.retain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 116468 -> 122552 bytes
+ ...urceHanSans-Regular_subset.retain-gids.660E.otf | Bin 50244 -> 50776 bytes
+ .../TwemojiMozilla.subset.default.32,3297,3299.ttf | Bin 5624 -> 5712 bytes
+ .../colr/TwemojiMozilla.subset.default.32,3297.ttf | Bin 5088 -> 5176 bytes
+ .../colr/TwemojiMozilla.subset.default.32,3299.ttf | Bin 5264 -> 5352 bytes
+ .../colr/TwemojiMozilla.subset.default.32.ttf      | Bin 4664 -> 4748 bytes
+ .../TwemojiMozilla.subset.default.3297,3299.ttf    | Bin 5604 -> 5692 bytes
+ .../colr/TwemojiMozilla.subset.default.3297.ttf    | Bin 5068 -> 5152 bytes
+ .../colr/TwemojiMozilla.subset.default.3299.ttf    | Bin 5244 -> 5328 bytes
+ ....subset.drop-hints-retain-gids.32,3297,3299.ttf | Bin 5604 -> 5692 bytes
+ ...zilla.subset.drop-hints-retain-gids.32,3297.ttf | Bin 5084 -> 5172 bytes
+ ...zilla.subset.drop-hints-retain-gids.32,3299.ttf | Bin 5264 -> 5352 bytes
+ ...ojiMozilla.subset.drop-hints-retain-gids.32.ttf | Bin 4644 -> 4728 bytes
+ ...lla.subset.drop-hints-retain-gids.3297,3299.ttf | Bin 5588 -> 5676 bytes
+ ...iMozilla.subset.drop-hints-retain-gids.3297.ttf | Bin 5064 -> 5148 bytes
+ ...iMozilla.subset.drop-hints-retain-gids.3299.ttf | Bin 5244 -> 5328 bytes
+ ...emojiMozilla.subset.drop-hints.32,3297,3299.ttf | Bin 5604 -> 5692 bytes
+ .../TwemojiMozilla.subset.drop-hints.32,3297.ttf   | Bin 5068 -> 5156 bytes
+ .../TwemojiMozilla.subset.drop-hints.32,3299.ttf   | Bin 5244 -> 5332 bytes
+ .../colr/TwemojiMozilla.subset.drop-hints.32.ttf   | Bin 4644 -> 4728 bytes
+ .../TwemojiMozilla.subset.drop-hints.3297,3299.ttf | Bin 5584 -> 5672 bytes
+ .../colr/TwemojiMozilla.subset.drop-hints.3297.ttf | Bin 5048 -> 5132 bytes
+ .../colr/TwemojiMozilla.subset.drop-hints.3299.ttf | Bin 5224 -> 5308 bytes
+ ...mojiMozilla.subset.retain-gids.32,3297,3299.ttf | Bin 5624 -> 5712 bytes
+ .../TwemojiMozilla.subset.retain-gids.32,3297.ttf  | Bin 5104 -> 5192 bytes
+ .../TwemojiMozilla.subset.retain-gids.32,3299.ttf  | Bin 5284 -> 5372 bytes
+ .../colr/TwemojiMozilla.subset.retain-gids.32.ttf  | Bin 4664 -> 4748 bytes
+ ...TwemojiMozilla.subset.retain-gids.3297,3299.ttf | Bin 5608 -> 5696 bytes
+ .../TwemojiMozilla.subset.retain-gids.3297.ttf     | Bin 5084 -> 5168 bytes
+ .../TwemojiMozilla.subset.retain-gids.3299.ttf     | Bin 5264 -> 5348 bytes
+ .../Roboto-Regular.default.1FC,21,41,20,62,63.ttf  | Bin 2984 -> 4656 bytes
+ .../full-font/Roboto-Regular.default.61,62,63.ttf  | Bin 2580 -> 3904 bytes
+ .../Roboto-Regular.default.D7,D8,D9,DA,DE.ttf      | Bin 2944 -> 3976 bytes
+ ...oboto-Regular.drop-hints.1FC,21,41,20,62,63.ttf | Bin 1436 -> 2532 bytes
+ .../Roboto-Regular.drop-hints.61,62,63.ttf         | Bin 1228 -> 2116 bytes
+ .../Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf   | Bin 1464 -> 2192 bytes
+ ...ifVariable-Roman.default.1FC,21,41,20,62,63.ttf | Bin 3572 -> 6876 bytes
+ .../SourceSerifVariable-Roman.default.61,62,63.ttf | Bin 3540 -> 6552 bytes
+ ...eSerifVariable-Roman.default.D7,D8,D9,DA,DE.ttf | Bin 4032 -> 6136 bytes
+ ...ariable-Roman.drop-hints.1FC,21,41,20,62,63.ttf | Bin 3572 -> 6612 bytes
+ ...urceSerifVariable-Roman.drop-hints.61,62,63.ttf | Bin 3540 -> 6356 bytes
+ ...rifVariable-Roman.drop-hints.D7,D8,D9,DA,DE.ttf | Bin 4032 -> 5880 bytes
+ .../Mplus1p-Regular.default.1D715,1D7D8,41,42.ttf  | Bin 2108 -> 2344 bytes
+ .../japanese/Mplus1p-Regular.default.25771.ttf     | Bin 1824 -> 1992 bytes
+ ...gular.default.3042,3044,3046,3048,304A,304B.ttf | Bin 2532 -> 2704 bytes
+ ...gular.default.3042,3044,3046,73E0,5EA6,8F38.ttf | Bin 2776 -> 2948 bytes
+ .../Mplus1p-Regular.default.61,63,65,6B.ttf        | Bin 2076 -> 2324 bytes
+ ...gular.default.660E,6975,73E0,5EA6,8F38,6E05.ttf | Bin 3072 -> 3244 bytes
+ .../japanese/Mplus1p-Regular.default.660E.ttf      | Bin 1816 -> 1984 bytes
+ ...plus1p-Regular.drop-hints.1D715,1D7D8,41,42.ttf | Bin 1380 -> 1616 bytes
+ .../japanese/Mplus1p-Regular.drop-hints.25771.ttf  | Bin 1096 -> 1264 bytes
+ ...ar.drop-hints.3042,3044,3046,3048,304A,304B.ttf | Bin 1804 -> 1976 bytes
+ ...ar.drop-hints.3042,3044,3046,73E0,5EA6,8F38.ttf | Bin 2048 -> 2220 bytes
+ .../Mplus1p-Regular.drop-hints.61,63,65,6B.ttf     | Bin 1348 -> 1596 bytes
+ ...ar.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.ttf | Bin 2344 -> 2516 bytes
+ .../japanese/Mplus1p-Regular.drop-hints.660E.ttf   | Bin 1088 -> 1256 bytes
+ ...Mplus1p-Regular.keep-gdef.1D715,1D7D8,41,42.ttf | Bin 2148 -> 2344 bytes
+ .../japanese/Mplus1p-Regular.keep-gdef.25771.ttf   | Bin 1860 -> 1992 bytes
+ ...lar.keep-gdef.3042,3044,3046,3048,304A,304B.ttf | Bin 2572 -> 2704 bytes
+ ...lar.keep-gdef.3042,3044,3046,73E0,5EA6,8F38.ttf | Bin 2816 -> 2948 bytes
+ .../Mplus1p-Regular.keep-gdef.61,63,65,6B.ttf      | Bin 2116 -> 2324 bytes
+ ...lar.keep-gdef.660E,6975,73E0,5EA6,8F38,6E05.ttf | Bin 3112 -> 3244 bytes
+ .../japanese/Mplus1p-Regular.keep-gdef.660E.ttf    | Bin 1852 -> 1984 bytes
+ ...ext1_multiple_subrules_f1.default.41,42,43.otf} | Bin
+ ...ontext1_multiple_subrules_f1.default.41,42.otf} | Bin
+ ...ontext1_multiple_subrules_f1.default.41,43.otf} | Bin
+ ...s_context1_multiple_subrules_f1.default.41.otf} | Bin
+ ...e_subrules_f1.default.retain-all-codepoint.otf} | Bin
+ ..._multiple_subrules_f1.retain-gids.41,42,43.otf} | Bin
+ ...xt1_multiple_subrules_f1.retain-gids.41,42.otf} | Bin
+ ...xt1_multiple_subrules_f1.retain-gids.41,43.otf} | Bin
+ ...ntext1_multiple_subrules_f1.retain-gids.41.otf} | Bin
+ ...brules_f1.retain-gids.retain-all-codepoint.otf} | Bin
+ ...ext2_multiple_subrules_f1.default.41,42,43.otf} | Bin
+ ...ontext2_multiple_subrules_f1.default.41,42.otf} | Bin
+ ...ontext2_multiple_subrules_f1.default.41,43.otf} | Bin
+ ...s_context2_multiple_subrules_f1.default.41.otf} | Bin
+ ...e_subrules_f1.default.retain-all-codepoint.otf} | Bin
+ ..._multiple_subrules_f1.retain-gids.41,42,43.otf} | Bin
+ ...xt2_multiple_subrules_f1.retain-gids.41,42.otf} | Bin
+ ...xt2_multiple_subrules_f1.retain-gids.41,43.otf} | Bin
+ ...ntext2_multiple_subrules_f1.retain-gids.41.otf} | Bin
+ ...brules_f1.retain-gids.retain-all-codepoint.otf} | Bin
+ ...> gpos_context3_simple_f1.default.41,42,43.otf} | Bin
+ ...f => gpos_context3_simple_f1.default.41,42.otf} | Bin
+ ...f => gpos_context3_simple_f1.default.41,43.otf} | Bin
+ ....otf => gpos_context3_simple_f1.default.41.otf} | Bin
+ ...xt3_simple_f1.default.retain-all-codepoint.otf} | Bin
+ ...os_context3_simple_f1.retain-gids.41,42,43.otf} | Bin
+ ... gpos_context3_simple_f1.retain-gids.41,42.otf} | Bin
+ ... gpos_context3_simple_f1.retain-gids.41,43.otf} | Bin
+ ... => gpos_context3_simple_f1.retain-gids.41.otf} | Bin
+ ...simple_f1.retain-gids.retain-all-codepoint.otf} | Bin
+ .../IndicTestJalandhar-Regular.default.A01.ttf     | Bin 4088 -> 4220 bytes
+ .../IndicTestJalandhar-Regular.default.A05,A06.ttf | Bin 4652 -> 4796 bytes
+ .../IndicTestJalandhar-Regular.default.A07,A1B.ttf | Bin 4620 -> 4768 bytes
+ ...andhar-Regular.default.retain-all-codepoint.ttf | Bin 28176 -> 49288 bytes
+ .../IndicTestJalandhar-Regular.drop-hints.A01.ttf  | Bin 948 -> 1080 bytes
+ ...dicTestJalandhar-Regular.drop-hints.A05,A06.ttf | Bin 1244 -> 1388 bytes
+ ...dicTestJalandhar-Regular.drop-hints.A07,A1B.ttf | Bin 1240 -> 1388 bytes
+ ...har-Regular.drop-hints.retain-all-codepoint.ttf | Bin 15200 -> 29504 bytes
+ .../IndicTestJalandhar-Regular.keep-gdef.A01.ttf   | Bin 4140 -> 4220 bytes
+ ...ndicTestJalandhar-Regular.keep-gdef.A05,A06.ttf | Bin 4716 -> 4796 bytes
+ ...ndicTestJalandhar-Regular.keep-gdef.A07,A1B.ttf | Bin 4688 -> 4768 bytes
+ ...dhar-Regular.keep-gdef.retain-all-codepoint.ttf | Bin 28604 -> 49288 bytes
+ .../AdobeVFPrototype.default.41,42,43,57.otf       | Bin 4960 -> 5460 bytes
+ .../AdobeVFPrototype.default.41,42,43.otf          | Bin 4540 -> 4932 bytes
+ .../AdobeVFPrototype.default.41,42.otf             | Bin 4132 -> 4452 bytes
+ .../AdobeVFPrototype.default.41,56,57.otf          | Bin 4152 -> 4600 bytes
+ .../AdobeVFPrototype.default.41.otf                | Bin 3468 -> 3748 bytes
+ .../AdobeVFPrototype.default.42,57.otf             | Bin 4208 -> 4584 bytes
+ .../AdobeVFPrototype.drop-hints.41,42,43,57.otf    | Bin 4772 -> 5180 bytes
+ .../AdobeVFPrototype.drop-hints.41,42,43.otf       | Bin 4352 -> 4688 bytes
+ .../AdobeVFPrototype.drop-hints.41,42.otf          | Bin 3944 -> 4236 bytes
+ .../AdobeVFPrototype.drop-hints.41,56,57.otf       | Bin 3964 -> 4348 bytes
+ .../AdobeVFPrototype.drop-hints.41.otf             | Bin 3280 -> 3552 bytes
+ .../AdobeVFPrototype.drop-hints.42,57.otf          | Bin 4020 -> 4364 bytes
+ ...AdobeVFPrototype.keep-gdef-gpos.41,42,43,57.otf | Bin 5400 -> 5460 bytes
+ .../AdobeVFPrototype.keep-gdef-gpos.41,42,43.otf   | Bin 4872 -> 4932 bytes
+ .../AdobeVFPrototype.keep-gdef-gpos.41,42.otf      | Bin 4392 -> 4452 bytes
+ .../AdobeVFPrototype.keep-gdef-gpos.41,56,57.otf   | Bin 4540 -> 4600 bytes
+ .../AdobeVFPrototype.keep-gdef-gpos.41.otf         | Bin 3688 -> 3748 bytes
+ .../AdobeVFPrototype.keep-gdef-gpos.42,57.otf      | Bin 4524 -> 4584 bytes
+ .../Roboto-Regular.default.1E00,303.ttf            | Bin 2456 -> 2720 bytes
+ .../layout.gdef/Roboto-Regular.default.303.ttf     | Bin 2128 -> 2312 bytes
+ .../Roboto-Regular.default.309,20,30F.ttf          | Bin 2220 -> 2408 bytes
+ .../layout.gdef/Roboto-Regular.default.323.ttf     | Bin 2020 -> 2204 bytes
+ .../Roboto-Regular.default.41,42,43.ttf            | Bin 2480 -> 3668 bytes
+ .../Roboto-Regular.drop-hints.1E00,303.ttf         | Bin 1204 -> 1468 bytes
+ .../layout.gdef/Roboto-Regular.drop-hints.303.ttf  | Bin 1012 -> 1196 bytes
+ .../Roboto-Regular.drop-hints.309,20,30F.ttf       | Bin 1068 -> 1256 bytes
+ .../layout.gdef/Roboto-Regular.drop-hints.323.ttf  | Bin 952 -> 1136 bytes
+ .../Roboto-Regular.drop-hints.41,42,43.ttf         | Bin 1188 -> 2036 bytes
+ .../Roboto-Regular.keep-gdef-gpos.1E00,303.ttf     | Bin 2648 -> 2720 bytes
+ .../Roboto-Regular.keep-gdef-gpos.303.ttf          | Bin 2240 -> 2312 bytes
+ .../Roboto-Regular.keep-gdef-gpos.309,20,30F.ttf   | Bin 2336 -> 2408 bytes
+ .../Roboto-Regular.keep-gdef-gpos.323.ttf          | Bin 2132 -> 2204 bytes
+ .../Roboto-Regular.keep-gdef-gpos.41,42,43.ttf     | Bin 2728 -> 3668 bytes
+ ...ut.41,43.otf => gpos1_2_font.default.41,43.otf} | Bin
+ ...ut.41,46.otf => gpos1_2_font.default.41,46.otf} | Bin
+ ...p-layout.41.otf => gpos1_2_font.default.41.otf} | Bin
+ ...ut.42,44.otf => gpos1_2_font.default.42,44.otf} | Bin
+ ...ut.43,46.otf => gpos1_2_font.default.43,46.otf} | Bin
+ ... gpos1_2_font.default.retain-all-codepoint.otf} | Bin
+ ...1,43.otf => gpos1_2_font.retain-gids.41,43.otf} | Bin
+ ...1,46.otf => gpos1_2_font.retain-gids.41,46.otf} | Bin
+ ...gids.41.otf => gpos1_2_font.retain-gids.41.otf} | Bin
+ ...2,44.otf => gpos1_2_font.retain-gids.42,44.otf} | Bin
+ ...3,46.otf => gpos1_2_font.retain-gids.43,46.otf} | Bin
+ ...s1_2_font.retain-gids.retain-all-codepoint.otf} | Bin
+ ...3,25.otf => gpos2_1_font7.default.21,23,25.otf} | Bin
+ ...t.21,23.otf => gpos2_1_font7.default.21,23.otf} | Bin
+ ...t.2E,23.otf => gpos2_1_font7.default.2E,23.otf} | Bin
+ ...2,43.otf => gpos2_1_font7.default.41,42,43.otf} | Bin
+ ...gpos2_1_font7.default.retain-all-codepoint.otf} | Bin
+ ....otf => gpos2_1_font7.retain-gids.21,23,25.otf} | Bin
+ ...,23.otf => gpos2_1_font7.retain-gids.21,23.otf} | Bin
+ ...,23.otf => gpos2_1_font7.retain-gids.2E,23.otf} | Bin
+ ....otf => gpos2_1_font7.retain-gids.41,42,43.otf} | Bin
+ ...2_1_font7.retain-gids.retain-all-codepoint.otf} | Bin
+ ...3,25.otf => gpos2_2_font5.default.21,23,25.otf} | Bin
+ ...t.21,23.otf => gpos2_2_font5.default.21,23.otf} | Bin
+ ...t.2E,23.otf => gpos2_2_font5.default.2E,23.otf} | Bin
+ ...2,43.otf => gpos2_2_font5.default.41,42,43.otf} | Bin
+ ...gpos2_2_font5.default.retain-all-codepoint.otf} | Bin
+ ....otf => gpos2_2_font5.retain-gids.21,23,25.otf} | Bin
+ ...,23.otf => gpos2_2_font5.retain-gids.21,23.otf} | Bin
+ ...,23.otf => gpos2_2_font5.retain-gids.2E,23.otf} | Bin
+ ....otf => gpos2_2_font5.retain-gids.41,42,43.otf} | Bin
+ ...2_2_font5.retain-gids.retain-all-codepoint.otf} | Bin
+ ...out.28,29.otf => gpos3_font3.default.28,29.otf} | Bin
+ ...out.28,2B.otf => gpos3_font3.default.28,2B.otf} | Bin
+ ...out.29,2B.otf => gpos3_font3.default.29,2B.otf} | Bin
+ ...,42,43.otf => gpos3_font3.default.41,42,43.otf} | Bin
+ ...> gpos3_font3.default.retain-all-codepoint.otf} | Bin
+ ...28,29.otf => gpos3_font3.retain-gids.28,29.otf} | Bin
+ ...28,2B.otf => gpos3_font3.retain-gids.28,2B.otf} | Bin
+ ...29,2B.otf => gpos3_font3.retain-gids.29,2B.otf} | Bin
+ ...43.otf => gpos3_font3.retain-gids.41,42,43.otf} | Bin
+ ...os3_font3.retain-gids.retain-all-codepoint.otf} | Bin
+ ...os4_multiple_anchors_1.default.41,42,43,44.otf} | Bin
+ ...os4_multiple_anchors_1.default.41,42,43,45.otf} | Bin
+ ... gpos4_multiple_anchors_1.default.41,42,43.otf} | Bin
+ ... => gpos4_multiple_anchors_1.default.41,42.otf} | Bin
+ ..._multiple_anchors_1.default.41,43,44,45,46.otf} | Bin
+ ... gpos4_multiple_anchors_1.default.41,43,44.otf} | Bin
+ ... gpos4_multiple_anchors_1.default.41,43,45.otf} | Bin
+ ... => gpos4_multiple_anchors_1.default.41,43.otf} | Bin
+ ...otf => gpos4_multiple_anchors_1.default.41.otf} | Bin
+ ...ple_anchors_1.default.retain-all-codepoint.otf} | Bin
+ ...multiple_anchors_1.retain-gids.41,42,43,44.otf} | Bin
+ ...multiple_anchors_1.retain-gids.41,42,43,45.otf} | Bin
+ ...s4_multiple_anchors_1.retain-gids.41,42,43.otf} | Bin
+ ...gpos4_multiple_anchors_1.retain-gids.41,42.otf} | Bin
+ ...tiple_anchors_1.retain-gids.41,43,44,45,46.otf} | Bin
+ ...s4_multiple_anchors_1.retain-gids.41,43,44.otf} | Bin
+ ...s4_multiple_anchors_1.retain-gids.41,43,45.otf} | Bin
+ ...gpos4_multiple_anchors_1.retain-gids.41,43.otf} | Bin
+ ...=> gpos4_multiple_anchors_1.retain-gids.41.otf} | Bin
+ ...anchors_1.retain-gids.retain-all-codepoint.otf} | Bin
+ ...,44.otf => gpos5_font1.default.41,42,43,44.otf} | Bin
+ ...,45.otf => gpos5_font1.default.41,42,43,45.otf} | Bin
+ ...,42,43.otf => gpos5_font1.default.41,42,43.otf} | Bin
+ ...,42,44.otf => gpos5_font1.default.41,42,44.otf} | Bin
+ ...,42,45.otf => gpos5_font1.default.41,42,45.otf} | Bin
+ ...out.41,42.otf => gpos5_font1.default.41,42.otf} | Bin
+ ...out.41,43.otf => gpos5_font1.default.41,43.otf} | Bin
+ ...ep-layout.41.otf => gpos5_font1.default.41.otf} | Bin
+ ...ep-layout.42.otf => gpos5_font1.default.42.otf} | Bin
+ ...> gpos5_font1.default.retain-all-codepoint.otf} | Bin
+ ...otf => gpos5_font1.retain-gids.41,42,43,44.otf} | Bin
+ ...otf => gpos5_font1.retain-gids.41,42,43,45.otf} | Bin
+ ...43.otf => gpos5_font1.retain-gids.41,42,43.otf} | Bin
+ ...44.otf => gpos5_font1.retain-gids.41,42,44.otf} | Bin
+ ...45.otf => gpos5_font1.retain-gids.41,42,45.otf} | Bin
+ ...41,42.otf => gpos5_font1.retain-gids.41,42.otf} | Bin
+ ...41,43.otf => gpos5_font1.retain-gids.41,43.otf} | Bin
+ ...-gids.41.otf => gpos5_font1.retain-gids.41.otf} | Bin
+ ...-gids.42.otf => gpos5_font1.retain-gids.42.otf} | Bin
+ ...os5_font1.retain-gids.retain-all-codepoint.otf} | Bin
+ ...,44.otf => gpos6_font1.default.41,42,43,44.otf} | Bin
+ ...,45.otf => gpos6_font1.default.41,42,43,45.otf} | Bin
+ ...,42,43.otf => gpos6_font1.default.41,42,43.otf} | Bin
+ ...out.41,42.otf => gpos6_font1.default.41,42.otf} | Bin
+ ....otf => gpos6_font1.default.41,43,44,45,46.otf} | Bin
+ ...,43,44.otf => gpos6_font1.default.41,43,44.otf} | Bin
+ ...,43,45.otf => gpos6_font1.default.41,43,45.otf} | Bin
+ ...out.41,43.otf => gpos6_font1.default.41,43.otf} | Bin
+ ...ep-layout.41.otf => gpos6_font1.default.41.otf} | Bin
+ ...> gpos6_font1.default.retain-all-codepoint.otf} | Bin
+ ...otf => gpos6_font1.retain-gids.41,42,43,44.otf} | Bin
+ ...otf => gpos6_font1.retain-gids.41,42,43,45.otf} | Bin
+ ...43.otf => gpos6_font1.retain-gids.41,42,43.otf} | Bin
+ ...41,42.otf => gpos6_font1.retain-gids.41,42.otf} | Bin
+ ... => gpos6_font1.retain-gids.41,43,44,45,46.otf} | Bin
+ ...44.otf => gpos6_font1.retain-gids.41,43,44.otf} | Bin
+ ...45.otf => gpos6_font1.retain-gids.41,43,45.otf} | Bin
+ ...41,43.otf => gpos6_font1.retain-gids.41,43.otf} | Bin
+ ...-gids.41.otf => gpos6_font1.retain-gids.41.otf} | Bin
+ ...os6_font1.retain-gids.retain-all-codepoint.otf} | Bin
+ ...lar.default.627,644,623,62D,644,627,645,2E.ttf} | Bin
+ ...f => Amiri-Regular.default.627,644,62D,628.ttf} | Bin
+ ...7,644.ttf => Amiri-Regular.default.627,644.ttf} | Bin
+ ...Regular.default.633,645,627,621,20,644,627.ttf} | Bin
+ ...1.ttf => Amiri-Regular.default.63A,64A,631.ttf} | Bin
+ ...retain-gids.627,644,623,62D,644,627,645,2E.ttf} | Bin
+ ... Amiri-Regular.retain-gids.627,644,62D,628.ttf} | Bin
+ ...4.ttf => Amiri-Regular.retain-gids.627,644.ttf} | Bin
+ ...lar.retain-gids.633,645,627,621,20,644,627.ttf} | Bin
+ ...f => Amiri-Regular.retain-gids.63A,64A,631.ttf} | Bin
+ ...1_multiple_subrules_f1.default.30,31,32,33.otf} | Bin
+ ...ing1_multiple_subrules_f1.default.41,42,43.otf} | Bin
+ ...e_subrules_f1.default.retain-all-codepoint.otf} | Bin
+ ...ltiple_subrules_f1.retain-gids.30,31,32,33.otf} | Bin
+ ..._multiple_subrules_f1.retain-gids.41,42,43.otf} | Bin
+ ...brules_f1.retain-gids.retain-all-codepoint.otf} | Bin
+ ...2_multiple_subrules_f1.default.30,31,32,33.otf} | Bin
+ ...ing2_multiple_subrules_f1.default.41,42,43.otf} | Bin
+ ...e_subrules_f1.default.retain-all-codepoint.otf} | Bin
+ ...ltiple_subrules_f1.retain-gids.30,31,32,33.otf} | Bin
+ ..._multiple_subrules_f1.retain-gids.41,42,43.otf} | Bin
+ ...brules_f1.retain-gids.retain-all-codepoint.otf} | Bin
+ ...os_chaining3_simple_f1.default.30,31,32,33.otf} | Bin
+ ... gpos_chaining3_simple_f1.default.41,42,43.otf} | Bin
+ ...ng3_simple_f1.default.retain-all-codepoint.otf} | Bin
+ ...haining3_simple_f1.retain-gids.30,31,32,33.otf} | Bin
+ ...s_chaining3_simple_f1.retain-gids.41,42,43.otf} | Bin
+ ...simple_f1.retain-gids.retain-all-codepoint.otf} | Bin
+ ...out.41,42.otf => gpos9_font2.default.41,42.otf} | Bin
+ ...ep-layout.41.otf => gpos9_font2.default.41.otf} | Bin
+ ...ep-layout.42.otf => gpos9_font2.default.42.otf} | Bin
+ ...41,42.otf => gpos9_font2.retain-gids.41,42.otf} | Bin
+ ...-gids.41.otf => gpos9_font2.retain-gids.41.otf} | Bin
+ ...-gids.42.otf => gpos9_font2.retain-gids.42.otf} | Bin
+ ...b_alternate_substitution.default.53A9,53F1.otf} | Bin
+ ...> gsub_alternate_substitution.default.53A9.otf} | Bin
+ ...> gsub_alternate_substitution.default.53F1.otf} | Bin
+ ..._substitution.default.retain-all-codepoint.otf} | Bin
+ ...ternate_substitution.retain-gids.53A9,53F1.otf} | Bin
+ ...ub_alternate_substitution.retain-gids.53A9.otf} | Bin
+ ...ub_alternate_substitution.retain-gids.53F1.otf} | Bin
+ ...stitution.retain-gids.retain-all-codepoint.otf} | Bin
+ ...ext1_multiple_subrules_f2.default.41,42,43.otf} | Bin
+ ...ontext1_multiple_subrules_f2.default.41,42.otf} | Bin
+ ...ontext1_multiple_subrules_f2.default.41,43.otf} | Bin
+ ...b_context1_multiple_subrules_f2.default.41.otf} | Bin
+ ...e_subrules_f2.default.retain-all-codepoint.otf} | Bin
+ ..._multiple_subrules_f2.retain-gids.41,42,43.otf} | Bin
+ ...xt1_multiple_subrules_f2.retain-gids.41,42.otf} | Bin
+ ...xt1_multiple_subrules_f2.retain-gids.41,43.otf} | Bin
+ ...ntext1_multiple_subrules_f2.retain-gids.41.otf} | Bin
+ ...brules_f2.retain-gids.retain-all-codepoint.otf} | Bin
+ ...ext2_multiple_subrules_f2.default.41,42,43.otf} | Bin
+ ...ontext2_multiple_subrules_f2.default.41,42.otf} | Bin
+ ...ontext2_multiple_subrules_f2.default.41,43.otf} | Bin
+ ...b_context2_multiple_subrules_f2.default.41.otf} | Bin
+ ...e_subrules_f2.default.retain-all-codepoint.otf} | Bin
+ ..._multiple_subrules_f2.retain-gids.41,42,43.otf} | Bin
+ ...xt2_multiple_subrules_f2.retain-gids.41,42.otf} | Bin
+ ...xt2_multiple_subrules_f2.retain-gids.41,43.otf} | Bin
+ ...ntext2_multiple_subrules_f2.retain-gids.41.otf} | Bin
+ ...brules_f2.retain-gids.retain-all-codepoint.otf} | Bin
+ ...ub_context3_successive_f1.default.41,42,43.otf} | Bin
+ ... gsub_context3_successive_f1.default.41,42.otf} | Bin
+ ... gsub_context3_successive_f1.default.41,43.otf} | Bin
+ ... => gsub_context3_successive_f1.default.41.otf} | Bin
+ ...successive_f1.default.retain-all-codepoint.otf} | Bin
+ ...ontext3_successive_f1.retain-gids.41,42,43.otf} | Bin
+ ...b_context3_successive_f1.retain-gids.41,42.otf} | Bin
+ ...b_context3_successive_f1.retain-gids.41,43.otf} | Bin
+ ...gsub_context3_successive_f1.retain-gids.41.otf} | Bin
+ ...essive_f1.retain-gids.retain-all-codepoint.otf} | Bin
+ ...1_multiple_subrules_f1.default.30,31,32,33.otf} | Bin
+ ...ing1_multiple_subrules_f1.default.41,42,43.otf} | Bin
+ ...e_subrules_f1.default.retain-all-codepoint.otf} | Bin
+ ...ltiple_subrules_f1.retain-gids.30,31,32,33.otf} | Bin
+ ..._multiple_subrules_f1.retain-gids.41,42,43.otf} | Bin
+ ...brules_f1.retain-gids.retain-all-codepoint.otf} | Bin
+ ...2_multiple_subrules_f1.default.30,31,32,33.otf} | Bin
+ ...ing2_multiple_subrules_f1.default.41,42,43.otf} | Bin
+ ...e_subrules_f1.default.retain-all-codepoint.otf} | Bin
+ ...ltiple_subrules_f1.retain-gids.30,31,32,33.otf} | Bin
+ ..._multiple_subrules_f1.retain-gids.41,42,43.otf} | Bin
+ ...brules_f1.retain-gids.retain-all-codepoint.otf} | Bin
+ ...ub_chaining3_simple_f2.default.30,31,32,33.otf} | Bin
+ ... gsub_chaining3_simple_f2.default.41,42,43.otf} | Bin
+ ...ng3_simple_f2.default.retain-all-codepoint.otf} | Bin
+ ...haining3_simple_f2.retain-gids.30,31,32,33.otf} | Bin
+ ...b_chaining3_simple_f2.retain-gids.41,42,43.otf} | Bin
+ ...simple_f2.retain-gids.retain-all-codepoint.otf} | Bin
+ ...created.default.41,42,43,44,45,46,47,48,49.otf} | Bin
+ ...ually_created.default.41,42,43,44,45,46,47.otf} | Bin
+ ...ually_created.default.41,42,43,44,45,46,4D.otf} | Bin
+ ...ually_created.default.41,42,43,44,45,46,51.otf} | Bin
+ ...manually_created.default.41,42,43,44,45,46.otf} | Bin
+ ...=> gsub8_manually_created.default.41,42,43.otf} | Bin
+ ...1.otf => gsub8_manually_created.default.41.otf} | Bin
+ ...1.otf => gsub8_manually_created.default.61.otf} | Bin
+ ...ually_created.default.retain-all-codepoint.otf} | Bin
+ ...ted.retain-gids.41,42,43,44,45,46,47,48,49.otf} | Bin
+ ...y_created.retain-gids.41,42,43,44,45,46,47.otf} | Bin
+ ...y_created.retain-gids.41,42,43,44,45,46,4D.otf} | Bin
+ ...y_created.retain-gids.41,42,43,44,45,46,51.otf} | Bin
+ ...ally_created.retain-gids.41,42,43,44,45,46.otf} | Bin
+ ...sub8_manually_created.retain-gids.41,42,43.otf} | Bin
+ ...f => gsub8_manually_created.retain-gids.41.otf} | Bin
+ ...f => gsub8_manually_created.retain-gids.61.otf} | Bin
+ ...y_created.retain-gids.retain-all-codepoint.otf} | Bin
+ .../Khmer.keep-layout-retain-gids.1780.ttf         | Bin 4464 -> 0 bytes
+ ...ids.1789,17BB,17C6,1794,17B6,1793,1798,17BE.ttf | Bin 7848 -> 0 bytes
+ .../Khmer.keep-layout-retain-gids.31.ttf           | Bin 4256 -> 0 bytes
+ .../layout.khmer/Khmer.keep-layout.1780.ttf        | Bin 4204 -> 0 bytes
+ ...out.1789,17BB,17C6,1794,17B6,1793,1798,17BE.ttf | Bin 6412 -> 0 bytes
+ .../expected/layout.khmer/Khmer.keep-layout.31.ttf | Bin 4140 -> 0 bytes
+ ...oNastaliqUrdu-Bold.retain-gids.627,644,62D.ttf} | Bin
+ ... Roboto-Regular.smallcaps.default.41,42,43.ttf} | Bin
+ ... => Roboto-Regular.smallcaps.default.41,43.ttf} | Bin
+ ...ttf => Roboto-Regular.smallcaps.default.41.ttf} | Bin
+ ...ttf => Roboto-Regular.smallcaps.default.43.ttf} | Bin
+ ... => Roboto-Regular.smallcaps.default.CA,CB.ttf} | Bin
+ ...oto-Regular.smallcaps.retain-gids.41,42,43.ttf} | Bin
+ ...Roboto-Regular.smallcaps.retain-gids.41,43.ttf} | Bin
+ ...=> Roboto-Regular.smallcaps.retain-gids.41.ttf} | Bin
+ ...=> Roboto-Regular.smallcaps.retain-gids.43.ttf} | Bin
+ ...Roboto-Regular.smallcaps.retain-gids.CA,CB.ttf} | Bin
+ .../Fraunces.keep-layout.26,66,69,124,125.ttf      | Bin 18496 -> 0 bytes
+ .../expected/variable/Fraunces.keep-layout.61.ttf  | Bin 5880 -> 0 bytes
+ .../data/profiles/keep-layout-drop-hints.txt       |   2 --
+ .../data/profiles/keep-layout-retain-gids.txt      |   2 --
+ test/subset/data/profiles/keep-layout.txt          |   1 -
+ test/subset/data/tests/basics.tests                |   2 --
+ test/subset/data/tests/layout.context.tests        |   4 ++--
+ test/subset/data/tests/layout.gpos.tests           |   4 ++--
+ test/subset/data/tests/layout.gpos2.tests          |   4 ++--
+ test/subset/data/tests/layout.gpos3.tests          |   4 ++--
+ test/subset/data/tests/layout.gpos4.tests          |   4 ++--
+ test/subset/data/tests/layout.gpos5.tests          |   4 ++--
+ test/subset/data/tests/layout.gpos6.tests          |   4 ++--
+ test/subset/data/tests/layout.gpos8.amiri.tests    |   4 ++--
+ test/subset/data/tests/layout.gpos8.tests          |   4 ++--
+ test/subset/data/tests/layout.gpos9.tests          |   4 ++--
+ test/subset/data/tests/layout.gsub3.tests          |   4 ++--
+ test/subset/data/tests/layout.gsub5.tests          |   4 ++--
+ test/subset/data/tests/layout.gsub6.tests          |   4 ++--
+ test/subset/data/tests/layout.gsub8.tests          |   4 ++--
+ test/subset/data/tests/layout.khmer.tests          |   4 ++--
+ .../data/tests/layout.notonastaliqurdu.tests       |   2 +-
+ test/subset/data/tests/layout.tests                |   4 ++--
+ test/subset/data/tests/variable.tests              |   2 +-
+ test/subset/generate-expected-outputs.py           |   2 +-
+ test/subset/run-tests.py                           |   2 +-
+ 614 files changed, 36 insertions(+), 46 deletions(-)
+
+commit 425ba1f4ab4fd1ee0245bc822336d26bd1755c52
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Apr 19 18:01:24 2021 -0700
+
+    [subset] fixes infinite loop in hb_set_get_max().
+    
+    Fixes https://oss-fuzz.com/testcase-detail/5363902507515904
+
+ src/hb-set.hh                                            |   2 +-
+ test/api/test-set.c                                      |   7 ++++++-
+ ...-testcase-minimized-hb-subset-fuzzer-5363902507515904 | Bin 0 -> 1683 bytes
+ 3 files changed, 7 insertions(+), 2 deletions(-)
+
+commit ec4321068b9de1ea2730b8a62dda7cb23d064303
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Apr 19 17:18:05 2021 -0700
+
+    [subset] fix infinite loop caused by alloc failure in repacker.
+    
+    Fixes: https://oss-fuzz.com/testcase-detail/5609112151916544.
+
+ src/hb-repacker.hh                                      |   8 ++++----
+ ...testcase-minimized-hb-subset-fuzzer-5609112151916544 | Bin 0 -> 80225 bytes
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+commit 0e845d973e2bf15b56cf68af9db778d1258b7709
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Apr 19 16:09:37 2021 -0700
+
+    [subset] fix memory leak in repacker caused by failed alloc.
+    
+    Fixes: https://oss-fuzz.com/testcase-detail/5616763250278400.
+
+ src/hb-repacker.hh                                      |   4 +++-
+ ...testcase-minimized-hb-subset-fuzzer-5616763250278400 | Bin 0 -> 97363 bytes
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+commit 3fb62cdc141d2d30ba0fc4a173dd50e7c1d56466
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Apr 5 15:48:34 2021 -0700
+
+    [subset] fail on offset overflow in tables that we don't repack.
+    
+    Fixes: https://oss-fuzz.com/testcase-detail/5229304507138048
+
+ src/hb-subset.cc                                        |   5 ++++-
+ ...testcase-minimized-hb-subset-fuzzer-5229304507138048 | Bin 0 -> 56552 bytes
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+commit 19e096aa97b1b3af21313df5250a937ddfece7fb
+Merge: ed2ee8a8c 23a28f5ad
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Apr 16 14:35:04 2021 -0600
+
+    Merge pull request #2067 from harfbuzz/null-size
+    
+    Avoid undefined-behavior, another try
+
+commit ed2ee8a8c26dc39e39172c169d8a0d434083fefe
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Apr 16 13:53:43 2021 -0600
+
+    Revert "Disable -Wunused-macros under GCC"
+    
+    This reverts commit 1b1413246b8b4a9c6f7e0aac16afd6d110c142cf.
+    
+    Err. It wasn't working. We already have that disabled in the files it
+    is warning about. Doesn't work.
+
+ src/hb.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 47cbf8f2c49ae82b85bf1edb211ade257f009800
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Mar 30 21:01:44 2021 -0600
+
+    [test] Silence more compiler warnings
+
+ test/api/test-unicode.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 1b1413246b8b4a9c6f7e0aac16afd6d110c142cf
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Mar 30 20:54:20 2021 -0600
+
+    Disable -Wunused-macros under GCC
+    
+    Since the pragram in hb-ot-shape-complex-indic-table.cc didn't seem to
+    silence GCC, eg:
+    
+    ../../src/hb-ot-shape-complex-indic-table.cc:55: warning: macro "ISC_TL" is not used [-Wunused-macros]
+       55 | #define ISC_TL   INDIC_SYLLABIC_CATEGORY_TONE_LETTER                 /*    7 chars; Tone_Letter */
+    
+    disable it at compiler level.
+
+ src/hb.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 23a28f5ad059a45ff861a06a63d8537dab7f81b7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Apr 16 13:22:05 2021 -0600
+
+    Avoid undefined-behavior
+    
+    If a struct had (because it's a union) sizeof that is larger than the null_size,
+    we were providing only null_size bytes for its Null object. We know we'd never
+    access beyond that, but is undefined-behavior nonetheless according to the
+    standard.
+    
+    The alternative fix would have required use of flexible-arrays, which are not
+    standard and have their own issues in various compiler. We've discussed that
+    extensively in the follow Mozilla issue (currently locked; I've asked that it
+    be opened):
+    
+      https://bugzilla.mozilla.org/show_bug.cgi?id=1577584
+    
+    Part of
+    https://github.com/harfbuzz/harfbuzz/pull/2067
+
+ src/hb-null.hh | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+commit 499248c533eaf88f20920bc438a939989a359956
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Apr 16 13:14:48 2021 -0600
+
+    [blob] Use min_size, instead of null_size in .as<T>()
+    
+    Part of https://github.com/harfbuzz/harfbuzz/pull/2067
+
+ src/hb-array.hh | 2 +-
+ src/hb-null.hh  | 9 ++++++++-
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+commit a4fb5da984d1dc50e419298a6212a0f53b4f761f
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Fri Apr 16 14:10:37 2021 +0200
+
+    [ci] Enable DirectWrite in win32 tarballs
+
+ .ci/build-win32.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f2240d12c2a847afda0eb2da635694ca2346de65
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Fri Apr 16 02:37:11 2021 +0200
+
+    [ci] Use -j2 for make and ninja in distcheck job
+    
+    Lets see if this makes it faster without crashing gcc.
+
+ .circleci/config.yml | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit f5c922b7091b9919cd6dbe17db663edb366aea52
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Fri Apr 16 01:47:34 2021 +0200
+
+    [ci] Try to stop distcheck job from crashing gcc
+
+ .circleci/config.yml | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit e116058bba1f5eb667d211c0c6c0be1bbffc6213
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Thu Apr 15 13:52:19 2021 +0200
+
+    [directwrite] Use correct UTF-16 string length
+    
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/2474
+
+ src/hb-directwrite.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 668acff1f07ed6bb1472467e59d16399befa68ae
+Author: Ben Denckla <bdenckla at alum.mit.edu>
+Date:   Mon Apr 12 14:25:19 2021 -0400
+
+    similarly improve comments on Hebrew ccc 18 & 19
+    
+    Should have committed this along with commit 9658435a25c2ba82 but forgot.
+
+ src/hb-ot-shape-fallback.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 43d955207bcfcddbf5a5e3d35819fddb81605be3
+Author: Ben Denckla <bdenckla at alum.mit.edu>
+Date:   Mon Apr 12 14:01:56 2021 -0400
+
+    improve comments on Hebrew ccc 18 & 19
+    
+    improve comments to reflect that:
+    ccc 18 includes both "flavors" of qamats: qamats [gadol] and qamats qatan
+    ccc 19 includes both "flavors" of holam: holam [not haser for vav] and holam haser for vav
+    This code and its comments may have been written before these code points were added to Unicode.
+    I.e. originally, these comments may have been complete, but they may have become incomplete in the meantime.
+
+ src/hb-unicode.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 4cc4cd3b24ded40cfff651ebf63d20d19253c505
+Author: Ambient Lighter <victor at opennodecloud.com>
+Date:   Sat Apr 10 14:11:23 2021 +0300
+
+    [docs] Fix spelling typo (#2945)
+
+ docs/usermanual-object-model.xml | 2 +-
+ perf/texts/en-words.txt          | 1 -
+ 2 files changed, 1 insertion(+), 2 deletions(-)
+
+commit 9dc9f0385dce05456d48730bf5dc7cac52eaa4da
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Apr 8 11:00:17 2021 -0700
+
+    [subset] fix for fuzzer testcase: https://oss-fuzz.com/testcase-detail/5858518134554624
+
+ src/hb-ot-layout-gpos-table.hh                            |   4 ++++
+ ...z-testcase-minimized-hb-subset-fuzzer-5858518134554624 | Bin 0 -> 802 bytes
+ 2 files changed, 4 insertions(+)
+
+commit 430a67ceaba5896c850c0a0da80f1bc211c022d8
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Apr 1 12:01:19 2021 -0700
+
+    [subset] COLRv1 struct definitions
+
+ src/hb-ot-color-colr-table.hh | 479 +++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 474 insertions(+), 5 deletions(-)
+
+commit 553ffaf6823040bf4a91bcd4c8e42592cd4d13c2
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Wed Apr 7 17:15:32 2021 -0700
+
+    [subset] fix for fuzzer testcase: https://oss-fuzz.com/testcase-detail/6382598554255360
+     avoid writing to null pointer
+
+ src/hb-ot-layout-gpos-table.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 4af5dacedc8d45c701c8a559962f1b071419ca50
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Wed Apr 7 10:56:49 2021 -0700
+
+    [subset] add fuzzer testcase
+
+ ...z-testcase-minimized-hb-subset-fuzzer-6382598554255360 | Bin 0 -> 766 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 8b686afeb5a7f959d98c0f85844d782c1cbc489f
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Apr 6 11:33:38 2021 -0700
+
+    [subset] add unlikely().
+
+ src/hb-ot-layout-gsubgpos.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 64122b5a443d78cc1c4c0c94fa2e489e1f22dd3e
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Apr 5 12:53:08 2021 -0700
+
+    [subset] don't visit lookup if covered glyph set has failed.
+    
+    If covered glyph set is in error then the same lookup can be recursed into repeatedly potentially causing a fuzzer timeout. Fixes: https://oss-fuzz.com/testcase-detail/5416421032067072.
+
+ src/hb-ot-layout-gsubgpos.hh                              |   2 ++
+ ...z-testcase-minimized-hb-subset-fuzzer-5416421032067072 | Bin 0 -> 114 bytes
+ 2 files changed, 2 insertions(+)
+
+commit 4ec18c85e6eebc0948c29df36fc13b5467fce86b
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Apr 2 15:33:54 2021 -0700
+
+    [subset] add subsetting tests with drop hints and layout subsetting enabled.
+
+ ...taa-Regular-new.keep-layout-drop-hints.61,62,63.ttf | Bin 0 -> 3444 bytes
+ ...fortaa-Regular-new.keep-layout-drop-hints.61,63.ttf | Bin 0 -> 3140 bytes
+ ...Comfortaa-Regular-new.keep-layout-drop-hints.61.ttf | Bin 0 -> 2804 bytes
+ ...Comfortaa-Regular-new.keep-layout-drop-hints.62.ttf | Bin 0 -> 2396 bytes
+ ...Comfortaa-Regular-new.keep-layout-drop-hints.63.ttf | Bin 0 -> 2464 bytes
+ ...new.keep-layout-drop-hints.retain-all-codepoint.ttf | Bin 0 -> 187944 bytes
+ ...-Regular-subset.keep-layout-drop-hints.61,62,63.ttf | Bin 0 -> 1452 bytes
+ ...gjo-Regular-subset.keep-layout-drop-hints.61,63.ttf | Bin 0 -> 1276 bytes
+ ...eongjo-Regular-subset.keep-layout-drop-hints.61.ttf | Bin 0 -> 1128 bytes
+ ...eongjo-Regular-subset.keep-layout-drop-hints.62.ttf | Bin 0 -> 1140 bytes
+ ...eongjo-Regular-subset.keep-layout-drop-hints.63.ttf | Bin 0 -> 1104 bytes
+ ...set.keep-layout-drop-hints.retain-all-codepoint.ttf | Bin 0 -> 3536 bytes
+ ...oto-Regular.abc.keep-layout-drop-hints.61,62,63.ttf | Bin 0 -> 1208 bytes
+ ...Roboto-Regular.abc.keep-layout-drop-hints.61,63.ttf | Bin 0 -> 1120 bytes
+ .../Roboto-Regular.abc.keep-layout-drop-hints.61.ttf   | Bin 0 -> 988 bytes
+ .../Roboto-Regular.abc.keep-layout-drop-hints.62.ttf   | Bin 0 -> 876 bytes
+ .../Roboto-Regular.abc.keep-layout-drop-hints.63.ttf   | Bin 0 -> 960 bytes
+ ...abc.keep-layout-drop-hints.retain-all-codepoint.ttf | Bin 0 -> 1208 bytes
+ test/subset/data/profiles/keep-layout-drop-hints.txt   |   2 ++
+ test/subset/data/tests/basics.tests                    |   1 +
+ 20 files changed, 3 insertions(+)
+
+commit 6f98a8ed4627b662d9591649328d2d302fc01987
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Apr 2 14:37:10 2021 -0700
+
+    [subset] Anchor should only use format 1 when hints are dropped.
+    
+    Refactor Anchor to have a subset method instead of copy. This also allows
+    use to use serialize_subset in several places which simplifies calculating
+    offset bases.
+
+ src/hb-ot-layout-gpos-table.hh | 189 +++++++++++++++++++++--------------------
+ 1 file changed, 95 insertions(+), 94 deletions(-)
+
+commit 71d6d1560035619ee685dc9aa626eeefabe5e9f1
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Apr 5 12:03:17 2021 -0700
+
+    [subset] clamp distance to prevent shifting outside of the limits of int64.
+    
+    Fixes https://oss-fuzz.com/testcase-detail/4961171477233664.
+
+ src/hb-repacker.hh                                      |   3 ++-
+ ...testcase-minimized-hb-subset-fuzzer-4961171477233664 | Bin 0 -> 39793 bytes
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+commit fcacd17748b85a56ff0c1d822295bfcbd8e175a2
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Mon Apr 5 22:27:39 2021 +0200
+
+    [ot] Update _hb_glyph_info_is_default_ignorable_and_not_hidden()
+    
+    Used _hb_glyph_info_substituted() similar to the change made to
+    _hb_glyph_info_is_default_ignorable() in
+    7686ff854bbb9698bb1469dcfe6d288c695a76b7.
+
+ src/hb-ot-layout.hh | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 596f4258d0b6464a8186263625a2da1b16014bdd
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Apr 2 12:41:09 2021 -0700
+
+    [subset] copy Lookup::markFilteringSet when subseting.
+
+ src/hb-ot-layout-common.hh                             |   8 ++++++++
+ .../Comfortaa-Regular-new.keep-layout.61,62,63.ttf     | Bin 0 -> 8100 bytes
+ .../basics/Comfortaa-Regular-new.keep-layout.61,63.ttf | Bin 0 -> 7736 bytes
+ .../basics/Comfortaa-Regular-new.keep-layout.61.ttf    | Bin 0 -> 7360 bytes
+ .../basics/Comfortaa-Regular-new.keep-layout.62.ttf    | Bin 0 -> 6796 bytes
+ .../basics/Comfortaa-Regular-new.keep-layout.63.ttf    | Bin 0 -> 6844 bytes
+ ...aa-Regular-new.keep-layout.retain-all-codepoint.ttf | Bin 0 -> 222212 bytes
+ ...numMyeongjo-Regular-subset.keep-layout.61,62,63.ttf | Bin 0 -> 4128 bytes
+ .../NanumMyeongjo-Regular-subset.keep-layout.61,63.ttf | Bin 0 -> 3580 bytes
+ .../NanumMyeongjo-Regular-subset.keep-layout.61.ttf    | Bin 0 -> 3156 bytes
+ .../NanumMyeongjo-Regular-subset.keep-layout.62.ttf    | Bin 0 -> 3180 bytes
+ .../NanumMyeongjo-Regular-subset.keep-layout.63.ttf    | Bin 0 -> 3048 bytes
+ ...Regular-subset.keep-layout.retain-all-codepoint.ttf | Bin 0 -> 9524 bytes
+ .../basics/Roboto-Regular.abc.keep-layout.61,62,63.ttf | Bin 0 -> 2452 bytes
+ .../basics/Roboto-Regular.abc.keep-layout.61,63.ttf    | Bin 0 -> 2260 bytes
+ .../basics/Roboto-Regular.abc.keep-layout.61.ttf       | Bin 0 -> 2048 bytes
+ .../basics/Roboto-Regular.abc.keep-layout.62.ttf       | Bin 0 -> 1916 bytes
+ .../basics/Roboto-Regular.abc.keep-layout.63.ttf       | Bin 0 -> 1972 bytes
+ ...to-Regular.abc.keep-layout.retain-all-codepoint.ttf | Bin 0 -> 2452 bytes
+ test/subset/data/tests/basics.tests                    |   1 +
+ 20 files changed, 9 insertions(+)
+
+commit d3a2f999e4d5c83e14f6380b780aab170d9cbd39
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Apr 2 08:32:41 2021 -0600
+
+    Fix up build
+    
+    This was left out; oops.
+
+ src/hb-set-digest.hh | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+commit c35d7863979f2395140d70cda49a19857b98f515
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Apr 1 14:32:38 2021 -0700
+
+    [subset] never drop the 'pref' feature.
+    
+    Never ever drop feature 'pref', even if it's empty. Harfbuzz uses it to choose the shaper for Khmer.
+
+ src/hb-ot-layout-gsubgpos.hh                            |   7 +++++++
+ test/subset/data/Makefile.am                            |   1 +
+ test/subset/data/Makefile.sources                       |   1 +
+ .../layout.khmer/Khmer.keep-layout-retain-gids.1780.ttf | Bin 0 -> 4464 bytes
+ ...ain-gids.1789,17BB,17C6,1794,17B6,1793,1798,17BE.ttf | Bin 0 -> 7848 bytes
+ .../layout.khmer/Khmer.keep-layout-retain-gids.31.ttf   | Bin 0 -> 4256 bytes
+ .../expected/layout.khmer/Khmer.keep-layout.1780.ttf    | Bin 0 -> 4204 bytes
+ ...p-layout.1789,17BB,17C6,1794,17B6,1793,1798,17BE.ttf | Bin 0 -> 6412 bytes
+ .../data/expected/layout.khmer/Khmer.keep-layout.31.ttf | Bin 0 -> 4140 bytes
+ test/subset/data/fonts/Khmer.ttf                        | Bin 0 -> 75368 bytes
+ test/subset/data/tests/layout.khmer.tests               |  11 +++++++++++
+ test/subset/meson.build                                 |   1 +
+ 12 files changed, 21 insertions(+)
+
+commit 092094f7055c1632e9bdf2c07f16e984a88a65ec
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Apr 1 15:47:21 2021 -0600
+
+    Use as_array() and range loops in a few places
+
+ src/hb-ot-cmap-table.hh    | 17 +++++++----------
+ src/hb-ot-layout-common.hh | 26 +++++++++-----------------
+ src/hb-set.hh              |  4 ++++
+ 3 files changed, 20 insertions(+), 27 deletions(-)
+
+commit 55e7f3fe329021c77c880f1f3fd6d082f4ac27da
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Apr 1 13:35:30 2021 -0700
+
+    [subset] Match FeatureVariationRecord dropping from fontTools.
+    
+    Only drop records with no matching features that are at the end of the list. See: https://github.com/fonttools/fonttools/commit/cab7d13dc0883765cde435215c7d65e9212f152d
+
+ src/hb-ot-layout-common.hh | 36 ++++++++++++++++++++++++++++++------
+ 1 file changed, 30 insertions(+), 6 deletions(-)
+
+commit f0c78e028261a7823194cccc7be241aa9ddbac25
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Mar 25 12:57:12 2021 -0700
+
+    [subset] don't drop features referenced in a feature variation substitution.
+
+ src/hb-ot-layout-common.hh | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+commit dae99b7769616d354e8cce41fbd7cf780353cb44
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Mar 25 12:33:51 2021 -0700
+
+    [subset] don't keep FeatureVariationRecord's with no subsittutions.
+
+ src/hb-ot-layout-common.hh | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+commit 85b07287838440e000622c53cee9cc911ad0de6d
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Mar 25 12:17:18 2021 -0700
+
+    Add full variable font subsetting test.
+
+ test/subset/data/Makefile.am                           |   1 +
+ test/subset/data/Makefile.sources                      |   1 +
+ .../variable/Fraunces.keep-layout.26,66,69,124,125.ttf | Bin 0 -> 18496 bytes
+ .../data/expected/variable/Fraunces.keep-layout.61.ttf | Bin 0 -> 5880 bytes
+ test/subset/data/fonts/Fraunces.ttf                    | Bin 0 -> 360440 bytes
+ test/subset/data/tests/variable.tests                  |   9 +++++++++
+ test/subset/meson.build                                |   1 +
+ 7 files changed, 12 insertions(+)
+
+commit c4b49075f62eaa11799c95099a70acbb70e566c9
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Apr 1 10:47:18 2021 -0700
+
+    Update CMakeLists.txt
+    
+    Keep the warning.
+
+ CMakeLists.txt | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9945f327463066957f2677237d468651235a1f3d
+Author: Timo Suoranta <timo.suoranta at varjo.com>
+Date:   Sat Feb 6 14:24:25 2021 +0200
+
+    Test fix to export target include directories
+
+ CMakeLists.txt | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+commit b10741ca7f4cd55526f303c47c72f0a5c1a932fe
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Mar 25 19:14:48 2021 -0700
+
+    [subset] when closing glyphs in context lookups don't use a current glyph set if a lookup is already applied.
+
+ src/hb-ot-layout-gsubgpos.hh                            |  12 ++++++++----
+ ...ayout-retain-gids.627,644,623,62D,644,627,645,2E.ttf | Bin 18272 -> 0 bytes
+ ...rdu-Bold.keep-layout-retain-gids.627,644,62D,628.ttf | Bin 24416 -> 0 bytes
+ ...liqUrdu-Bold.keep-layout-retain-gids.627,644,62D.ttf | Bin 0 -> 11532 bytes
+ ...astaliqUrdu-Bold.keep-layout-retain-gids.627,644.ttf | Bin 9216 -> 0 bytes
+ ...ep-layout-retain-gids.633,645,627,621,20,644,627.ttf | Bin 18212 -> 0 bytes
+ ...liqUrdu-Bold.keep-layout-retain-gids.63A,64A,631.ttf | Bin 26628 -> 0 bytes
+ ...-Bold.keep-layout.627,644,623,62D,644,627,645,2E.ttf | Bin 11436 -> 0 bytes
+ ...otoNastaliqUrdu-Bold.keep-layout.627,644,62D,628.ttf | Bin 18288 -> 0 bytes
+ .../NotoNastaliqUrdu-Bold.keep-layout.627,644.ttf       | Bin 3568 -> 0 bytes
+ ...Urdu-Bold.keep-layout.633,645,627,621,20,644,627.ttf | Bin 12408 -> 0 bytes
+ .../NotoNastaliqUrdu-Bold.keep-layout.63A,64A,631.ttf   | Bin 20408 -> 0 bytes
+ test/subset/data/tests/layout.notonastaliqurdu.tests    |   7 +------
+ 13 files changed, 9 insertions(+), 10 deletions(-)
+
+commit 2773d057403292e4a13e13ca12912437607b9d86
+Author: Garret Rieger <grieger at google.com>
+Date:   Wed Nov 4 11:11:16 2020 -0800
+
+    [subset] Add a test case using NotoNastaliqUrdu.
+
+ test/subset/data/Makefile.am                            |   1 +
+ test/subset/data/Makefile.sources                       |   1 +
+ ...ayout-retain-gids.627,644,623,62D,644,627,645,2E.ttf | Bin 0 -> 18272 bytes
+ ...rdu-Bold.keep-layout-retain-gids.627,644,62D,628.ttf | Bin 0 -> 24416 bytes
+ ...astaliqUrdu-Bold.keep-layout-retain-gids.627,644.ttf | Bin 0 -> 9216 bytes
+ ...ep-layout-retain-gids.633,645,627,621,20,644,627.ttf | Bin 0 -> 18212 bytes
+ ...liqUrdu-Bold.keep-layout-retain-gids.63A,64A,631.ttf | Bin 0 -> 26628 bytes
+ ...-Bold.keep-layout.627,644,623,62D,644,627,645,2E.ttf | Bin 0 -> 11436 bytes
+ ...otoNastaliqUrdu-Bold.keep-layout.627,644,62D,628.ttf | Bin 0 -> 18288 bytes
+ .../NotoNastaliqUrdu-Bold.keep-layout.627,644.ttf       | Bin 0 -> 3568 bytes
+ ...Urdu-Bold.keep-layout.633,645,627,621,20,644,627.ttf | Bin 0 -> 12408 bytes
+ .../NotoNastaliqUrdu-Bold.keep-layout.63A,64A,631.ttf   | Bin 0 -> 20408 bytes
+ test/subset/data/tests/layout.notonastaliqurdu.tests    |  13 +++++++++++++
+ test/subset/meson.build                                 |   1 +
+ 14 files changed, 16 insertions(+)
+
+commit 8ef4257dc8d6b59b55d0169b66c8de135d5f199b
+Author: Garret Rieger <grieger at google.com>
+Date:   Wed Mar 31 15:00:46 2021 -0700
+
+    [sanitize] change max ops to track number of bytes processed.
+    
+    Counting bytes as the operations is likely to be a better proxy for how
+    much work processing the table will cost vs. the current approach of
+    counting the number of sub-objects.
+    
+    This should allow checks for max features, max scripts, etc. to be removed.
+    
+    I tested this change against the full collection of fonts at https://github.com/google/fonts
+    and a max ops factor of 3 was sufficient to successfully sanitize all of them.
+
+ src/hb-sanitize.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 70110f6aaac541bc157eb5612b476d3b906b5d2a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 17:04:02 2021 -0600
+
+    Modify OffsetTo<>::sanitize() overflow check
+    
+    The code in question was introduced in 70eb2ff682.
+    Rewrite it to not call sanitizer check_range() as we want to use
+    check_range() for byte accounting.
+    
+    Part of https://github.com/harfbuzz/harfbuzz/pull/2923
+
+ src/hb-open-type.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 4dba749d833491ec0c73fb4647f55236be1caee3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 16:09:39 2021 -0600
+
+    Add SortedArray{16,32}Of<>
+
+ src/hb-open-type.hh            |  5 ++++-
+ src/hb-ot-cmap-table.hh        | 10 +++++-----
+ src/hb-ot-color-svg-table.hh   |  2 +-
+ src/hb-ot-layout-base-table.hh |  8 ++++----
+ src/hb-ot-layout-common.hh     |  8 ++++----
+ src/hb-ot-layout-jstf-table.hh |  2 +-
+ src/hb-ot-vorg-table.hh        |  2 +-
+ 7 files changed, 20 insertions(+), 17 deletions(-)
+
+commit 5639e253f91bd71cdb626719ebc5b8d68631cc73
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 16:04:43 2021 -0600
+
+    Add Array16Of<>
+
+ src/hb-aat-layout-common.hh                |  2 +-
+ src/hb-aat-layout-just-table.hh            |  2 +-
+ src/hb-open-type.hh                        |  6 ++--
+ src/hb-ot-gasp-table.hh                    |  2 +-
+ src/hb-ot-layout-common.hh                 | 12 +++----
+ src/hb-ot-layout-gdef-table.hh             |  4 +--
+ src/hb-ot-layout-gpos-table.hh             |  8 ++---
+ src/hb-ot-layout-gsub-table.hh             | 20 +++++------
+ src/hb-ot-layout-gsubgpos.hh               | 54 +++++++++++++++---------------
+ src/hb-ot-math-table.hh                    | 10 +++---
+ src/hb-ot-post-table.hh                    |  4 +--
+ src/hb-ot-shape-complex-arabic-fallback.hh |  2 +-
+ src/hb-ot-var-avar-table.hh                |  2 +-
+ 13 files changed, 64 insertions(+), 64 deletions(-)
+
+commit 2520a82df9116fbc287cec1be66d05874c467bbb
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 15:34:26 2021 -0600
+
+    s/LArrayOf/Array32Of/g
+
+ src/hb-aat-layout-ankr-table.hh | 2 +-
+ src/hb-aat-layout-just-table.hh | 2 +-
+ src/hb-aat-ltag-table.hh        | 2 +-
+ src/hb-open-file.hh             | 4 ++--
+ src/hb-open-type.hh             | 4 ++--
+ src/hb-ot-color-cbdt-table.hh   | 8 ++++----
+ src/hb-ot-layout-common.hh      | 2 +-
+ src/hb-ot-meta-table.hh         | 2 +-
+ 8 files changed, 13 insertions(+), 13 deletions(-)
+
+commit 5efe3609865b450305474b9abe672905bd25cc06
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 15:33:22 2021 -0600
+
+    Rename (Unsized)OffsetListOf
+
+ src/hb-aat-layout-morx-table.hh | 4 ++--
+ src/hb-open-type.hh             | 6 +++---
+ src/hb-ot-layout-common.hh      | 8 ++++----
+ src/hb-ot-layout-gpos-table.hh  | 2 +-
+ src/hb-ot-layout-gsubgpos.hh    | 2 +-
+ src/hb-ot-layout-jstf-table.hh  | 6 +++---
+ 6 files changed, 14 insertions(+), 14 deletions(-)
+
+commit 6c4e0491d7ebdc41318db59c4b0911212b299341
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 15:31:32 2021 -0600
+
+    s/OffsetArrayOf/Array16OfOffset16To/g
+
+ src/hb-open-type.hh            |  6 ++---
+ src/hb-ot-layout-base-table.hh |  2 +-
+ src/hb-ot-layout-common.hh     |  8 +++----
+ src/hb-ot-layout-gdef-table.hh |  6 ++---
+ src/hb-ot-layout-gpos-table.hh |  2 +-
+ src/hb-ot-layout-gsub-table.hh | 26 ++++++++++----------
+ src/hb-ot-layout-gsubgpos.hh   | 54 +++++++++++++++++++++---------------------
+ 7 files changed, 52 insertions(+), 52 deletions(-)
+
+commit 1fc6b69aed28aa768b65a8cf0825b79aa851a71f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 15:30:35 2021 -0600
+
+    s/UnsizedOffsetArrayOf/UnsizedArray16OfOffsetTo/g
+
+ src/hb-open-type.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 2a54c9f744b195bb1412573afcc36db806d20a4b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 15:26:42 2021 -0600
+
+    .
+
+ src/hb-open-type.hh           | 9 +++------
+ src/hb-ot-color-sbix-table.hh | 4 ++--
+ src/hb-ot-layout-common.hh    | 4 ++--
+ 3 files changed, 7 insertions(+), 10 deletions(-)
+
+commit c539afb08b1b698216541087b1eec222472699ea
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 13:28:25 2021 -0600
+
+    [CFF] Use NNOffsetTo<> instead of OffsetTo<>
+    
+    I'm pretty sure that's what is intended.
+
+ src/hb-ot-cff1-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9b4b58493b7e4c15565e4a47118181d96f517fae
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 13:27:21 2021 -0600
+
+    Fixup for recent OffsetTo<> changes
+
+ src/hb-open-type.hh          | 2 +-
+ src/hb-ot-layout-gsubgpos.hh | 8 ++++----
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+commit ad28f973f3ec6184b4c405efc0e17fba87b51062
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 12:49:14 2021 -0600
+
+    Rename offset types to be explicit about their size
+    
+    Add Offset16To<>, Offset24To<>, and Offset32To<> for most use-cases.
+
+ src/hb-aat-layout-ankr-table.hh            |  6 +--
+ src/hb-aat-layout-common.hh                |  2 +-
+ src/hb-aat-layout-feat-table.hh            |  2 +-
+ src/hb-aat-layout-just-table.hh            | 12 ++---
+ src/hb-aat-layout-kerx-table.hh            | 14 +++---
+ src/hb-aat-layout-opbd-table.hh            |  8 ++--
+ src/hb-aat-layout-trak-table.hh            |  8 ++--
+ src/hb-aat-ltag-table.hh                   |  2 +-
+ src/hb-open-file.hh                        | 12 ++---
+ src/hb-open-type.hh                        | 14 +++---
+ src/hb-ot-cmap-table.hh                    |  6 +--
+ src/hb-ot-color-cbdt-table.hh              |  4 +-
+ src/hb-ot-color-colr-table.hh              |  4 +-
+ src/hb-ot-color-cpal-table.hh              |  8 ++--
+ src/hb-ot-color-sbix-table.hh              |  4 +-
+ src/hb-ot-color-svg-table.hh               |  4 +-
+ src/hb-ot-layout-base-table.hh             | 28 ++++++------
+ src/hb-ot-layout-common.hh                 | 22 +++++-----
+ src/hb-ot-layout-gdef-table.hh             | 24 +++++-----
+ src/hb-ot-layout-gpos-table.hh             | 70 +++++++++++++++---------------
+ src/hb-ot-layout-gsub-table.hh             | 14 +++---
+ src/hb-ot-layout-gsubgpos.hh               | 64 +++++++++++++--------------
+ src/hb-ot-layout-jstf-table.hh             | 24 +++++-----
+ src/hb-ot-math-table.hh                    | 34 +++++++--------
+ src/hb-ot-meta-table.hh                    |  2 +-
+ src/hb-ot-name-table.hh                    |  4 +-
+ src/hb-ot-shape-complex-arabic-fallback.hh |  2 +-
+ src/hb-ot-stat-table.hh                    |  8 ++--
+ src/hb-ot-var-fvar-table.hh                |  2 +-
+ src/hb-ot-var-gvar-table.hh                |  6 +--
+ src/hb-ot-var-hvar-table.hh                | 10 ++---
+ src/hb-ot-var-mvar-table.hh                |  2 +-
+ 32 files changed, 214 insertions(+), 212 deletions(-)
+
+commit c5c13006a1f8e5fb9b28a3c2081e93eb4e5d4c98
+Author: Garret Rieger <grieger at google.com>
+Date:   Wed Mar 31 11:23:46 2021 -0700
+
+    [subset] fix memory leaks found in https://oss-fuzz.com/testcase-detail/5179935334465536
+
+ src/hb-repacker.hh                                      |   3 ++-
+ src/hb-vector.hh                                        |   5 +++++
+ ...testcase-minimized-hb-subset-fuzzer-5179935334465536 | Bin 0 -> 50501 bytes
+ 3 files changed, 7 insertions(+), 1 deletion(-)
+
+commit bd2950b3939d88fed998717b05367651153dc21b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 11:36:36 2021 -0600
+
+    Make VariationStore::get_delta(outer, inner) private
+
+ src/hb-ot-layout-common.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 934675a42958ba2e4e3e10aa4b55a9e772977399
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 11:34:41 2021 -0600
+
+    Use VarIdx in VariationDevice
+
+ src/hb-ot-layout-common.hh | 17 +++++++----------
+ 1 file changed, 7 insertions(+), 10 deletions(-)
+
+commit 0f7f7536b9d98e65f345398529da9c6bc365a3fb
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 11:31:49 2021 -0600
+
+    [hvar] Change variation-index types from "unsigned int" to uint32_t
+
+ src/hb-ot-var-hvar-table.hh | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+commit 9ffc46b8ff5546998fc9b74cb54dec8618ed0ac7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 11:26:18 2021 -0600
+
+    Add VarIdx
+
+ src/hb-open-type.hh | 6 ++++++
+ src/hb-static.cc    | 1 +
+ 2 files changed, 7 insertions(+)
+
+commit 2179281c406452392a2d9c7e17b81e02735fe50b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 31 11:20:21 2021 -0600
+
+    Add Offset24
+
+ src/hb-open-type.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit b3159ed8d2dbe4af584d05298448e6de62d394d6
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Mar 30 20:52:56 2021 -0600
+
+    [util] Silence compiler warning
+
+ util/helper-cairo.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit cab9d5a57dc56c47ba4db51b813fac618694c9a9
+Author: Andrzej Perczak <kartapolska at gmail.com>
+Date:   Fri Mar 19 22:10:50 2021 +0100
+
+    hb-config: Include config-override earlier
+    
+    Currently config-override.h is included at the end of this file. This caused a problem for me while undefing HB_DISABLE_DEPRECATED, namely HB_IF_NOT_DEPRECATED was defined before actual undef took place and broke the whole build. I believe it would break builds for some other defines, too. Moving config-override.h include right after predefined configs is more sane and fixes all potential problems with includes.
+
+ src/hb-config.hh | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit adca4ce071d12998deea6bb53b223daa3aa163c5
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Mar 30 13:20:50 2021 -0700
+
+    [subset] fixes https://oss-fuzz.com/testcase-detail/6173520787800064.
+    
+    Caused by incorrect bounds check in glyph closure for context lookups.
+
+ src/hb-ot-layout-gsubgpos.hh                             |   2 +-
+ ...-testcase-minimized-hb-subset-fuzzer-6173520787800064 | Bin 0 -> 1731 bytes
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+commit 9f77a0c1ff02765862d6d2bfed6b9aab78db6fff
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Mar 30 14:10:45 2021 -0700
+
+    [subset] use hb_set_clear to avoid calling clear() on null pool set.
+
+ src/hb-ot-layout-gsubgpos.hh | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 752e393ad2f5ec4f7faae84f5322fbef41ddb2ab
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Mar 29 17:23:33 2021 -0700
+
+    [subset] avoid calling clear on null pool set.
+
+ src/hb-ot-layout-gsubgpos.hh                              |   3 ++-
+ ...z-testcase-minimized-hb-subset-fuzzer-5617065093365760 | Bin 0 -> 160 bytes
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+commit 9ed5f04a7092c76744076ba65673b250aee22dcd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Mar 29 18:14:30 2021 -0600
+
+    [subset] Simplify recent out-of-memory fixes
+    
+    By checking return status of map->set().
+
+ src/hb-ot-layout-common.hh   |  8 ++++----
+ src/hb-ot-layout-gsubgpos.hh | 12 ++++++------
+ 2 files changed, 10 insertions(+), 10 deletions(-)
+
+commit a8f9f85a919543ce79b5a7d5df90c132830ae772
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Mar 29 18:12:05 2021 -0600
+
+    [map] Return success from ->set()
+
+ src/hb-map.hh | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+commit 8741914a8043757d4800b14192980fbc1ea24492
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Mar 29 16:39:44 2021 -0700
+
+    [subset] fix memory leak when map insert fails.
+
+ src/hb-ot-layout-common.hh                             |  17 ++++++++++++-----
+ ...estcase-minimized-hb-subset-fuzzer-6421315436281856 | Bin 0 -> 59 bytes
+ 2 files changed, 12 insertions(+), 5 deletions(-)
+
+commit 2397689387419f9a86b928ea5084b2318d136ac6
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Mar 29 17:34:23 2021 -0600
+
+    Remove hb_success_t
+    
+    Was not rolled-out yet.  So just expand.
+
+ src/hb-open-type.hh | 4 ++--
+ src/hb.hh           | 1 -
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+commit 7a2eda7817a26e017c9da3db4700a24dde550dde
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Mar 29 17:32:29 2021 -0600
+
+    Move code around
+
+ src/hb-open-type.hh | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+commit bcb57dccaabad4275ab96b14123413bbec6d0fec
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Mar 29 17:31:09 2021 -0600
+
+    [sanitize] Add short-circuit to ArrayOfM1
+    
+    Like the sibling ArrayOf types.
+
+ src/hb-open-type.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 5b6da6d2f0bcaeb7768705e6891f575ae73c8b41
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Mar 29 16:19:17 2021 -0700
+
+    [subset] add fuzzer test case.
+
+ ...z-testcase-minimized-hb-subset-fuzzer-5250795600740352 | Bin 0 -> 409 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 52df6b9fd8cf075f416372f0469a6915e814b0d6
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Mar 29 16:17:27 2021 -0700
+
+    [subset] check for set insertion success.
+
+ src/hb-ot-layout-gsubgpos.hh | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+commit c6adb90a273f22159b0775f798724d36d552d36c
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Mar 29 16:08:44 2021 -0700
+
+    [subset] fix nullptr deref.
+
+ src/hb-ot-layout-gsubgpos.hh | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+commit 9a3537e5f688637a2ac2ced57de9e2b7c21d90a5
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Mar 29 14:34:24 2021 -0700
+
+    [subset] invert err() return value. Undo previous change to check_success.
+
+ src/hb-serialize.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit a804a0c903f6dd230954ff5855ed7ff1dd92844d
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Mar 29 14:25:20 2021 -0700
+
+    [subset] add fuzzer test case.
+
+ ...-testcase-minimized-hb-subset-fuzzer-5887968763052032 | Bin 0 -> 3889 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit cdba5d44c28a97ab8d9298a3bef60fcbd0845000
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Mar 29 14:23:59 2021 -0700
+
+    [subset] fix incorrect handling of return value in check_success in the error case.
+
+ src/hb-serialize.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 05e845c49ad2eebf110dcc6cb0ee48a7f68ca233
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Mar 29 16:02:10 2021 -0700
+
+    Make previous commit gcc-only
+
+ src/hb.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit b5e40323921566ce8a15aa7808d22d36acac4edd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Mar 29 15:54:40 2021 -0700
+
+    -Wno-unused-result
+    
+    GCC doesn't let one turn off the warning using "(void) foo()".
+    People have introduced macros that do "unused << foo()" instead.
+    Until we do something similar, silence gcc.
+    
+    Clang on the other hand understands "(void) foo()".
+
+ src/hb.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit c30349d54e67c1ee7e1ea759e8378fcf6a6c9ff4
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Sun Mar 21 20:12:59 2021 +0200
+
+    [hb-view] Support kitty inline images protocol
+    
+    https://github.com/harfbuzz/harfbuzz/issues/2758
+
+ util/helper-cairo.cc | 36 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+commit f7d5889b3ea9012d23407b83a176bcd54a94e21b
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Sun Mar 21 18:16:33 2021 +0200
+
+    [hb-view] Support iTerm2 inline images protocol
+    
+    https://github.com/harfbuzz/harfbuzz/issues/2758
+
+ util/helper-cairo.cc | 85 +++++++++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 78 insertions(+), 7 deletions(-)
+
+commit 743baf35436d8de937984e09467f453cdfba102e
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Mon Mar 22 15:51:17 2021 +0200
+
+    [build] Don’t look for FontConfig
+    
+    We don’t currently use it anywhere. It was used briefly for the
+    hb-fc-list tool, but this tool have not been built since 2015:
+    
+    commit cd042fc8c4a3984c3647cd22a27c34f00636f6e8
+    Author: Behdad Esfahbod <behdad at behdad.org>
+    Date:   Thu Jun 18 10:55:13 2015 -0700
+    
+        [util] Disable hb-fc-list for now
+    
+        Until I figure out what to do about the API, and finalize
+        the tool.
+
+ .circleci/config.yml                 |  2 +-
+ Makefile.am                          |  1 -
+ configure.ac                         | 19 -------------------
+ docs/usermanual-install-harfbuzz.xml | 20 --------------------
+ meson.build                          |  7 -------
+ meson_options.txt                    |  2 --
+ subprojects/.gitignore               |  1 -
+ subprojects/fontconfig.wrap          |  6 ------
+ 8 files changed, 1 insertion(+), 57 deletions(-)
+
+commit 95230e291dddc20185e6a34b69836631d894c0d8
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Mar 18 17:41:25 2021 -0700
+
+    [subset] support subsetting GSUB8
+
+ src/hb-ot-layout-gsub-table.hh                     |  73 ++++++++++++++++++++-
+ test/subset/data/Makefile.am                       |   1 +
+ test/subset/data/Makefile.sources                  |   1 +
+ ...yout-retain-gids.41,42,43,44,45,46,47,48,49.otf | Bin 0 -> 3172 bytes
+ ...eep-layout-retain-gids.41,42,43,44,45,46,47.otf | Bin 0 -> 2796 bytes
+ ...eep-layout-retain-gids.41,42,43,44,45,46,4D.otf | Bin 0 -> 2860 bytes
+ ...eep-layout-retain-gids.41,42,43,44,45,46,51.otf | Bin 0 -> 2864 bytes
+ ...d.keep-layout-retain-gids.41,42,43,44,45,46.otf | Bin 0 -> 2540 bytes
+ ...ly_created.keep-layout-retain-gids.41,42,43.otf | Bin 0 -> 1984 bytes
+ ...manually_created.keep-layout-retain-gids.41.otf | Bin 0 -> 1872 bytes
+ ...manually_created.keep-layout-retain-gids.61.otf | Bin 0 -> 2584 bytes
+ ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3832 bytes
+ ...ated.keep-layout.41,42,43,44,45,46,47,48,49.otf | Bin 0 -> 2384 bytes
+ ...ly_created.keep-layout.41,42,43,44,45,46,47.otf | Bin 0 -> 1996 bytes
+ ...ly_created.keep-layout.41,42,43,44,45,46,4D.otf | Bin 0 -> 1996 bytes
+ ...ly_created.keep-layout.41,42,43,44,45,46,51.otf | Bin 0 -> 2044 bytes
+ ...ually_created.keep-layout.41,42,43,44,45,46.otf | Bin 0 -> 1832 bytes
+ ...gsub8_manually_created.keep-layout.41,42,43.otf | Bin 0 -> 1284 bytes
+ .../gsub8_manually_created.keep-layout.41.otf      | Bin 0 -> 1172 bytes
+ .../gsub8_manually_created.keep-layout.61.otf      | Bin 0 -> 1540 bytes
+ ...ly_created.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3832 bytes
+ test/subset/data/fonts/gsub8_manually_created.otf  | Bin 0 -> 4824 bytes
+ test/subset/data/tests/layout.gsub8.tests          |  17 +++++
+ test/subset/meson.build                            |   1 +
+ 24 files changed, 91 insertions(+), 2 deletions(-)
+
+commit d18915f920a0d9ab7ce5cfec4654d3d610b1d082
+Author: David Corbett <corbett.dav at northeastern.edu>
+Date:   Sun Mar 28 10:09:13 2021 -0400
+
+    Reformat gen-tag-table.py
+
+ src/gen-tag-table.py | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 deletions(-)
+
+commit 3c8273ab68e37ed5b08b4edacac995fc451d5732
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Mar 25 11:39:57 2021 -0700
+
+    Check for alloc failures on the gsub/gpos_langsys maps in subset plan creation.
+
+ src/hb-subset-plan.cc | 46 ++++++++++++++++++++++++++++------------------
+ src/hb-subset.cc      |  4 +++-
+ 2 files changed, 31 insertions(+), 19 deletions(-)
+
+commit 29708e959a04ee003b9c0738f0c5330584f15b4f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Mar 22 15:22:15 2021 -0700
+
+    [aat] Fix offsetToIndex math for out-of-bounds values
+    
+    Previously, some bad font data was accidentally being interpretted as
+    legit if it happened to not fall out of memory bounds. The intention
+    of the code was what this commit does.  I'm surprised we weren't getting
+    a "arithmetic between signed and unsigned values" warning / error
+    before.
+
+ src/hb-aat-layout-common.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit c5d6bdb4bf2d8d595f5c762c3e618444621803ae
+Merge: a7d120aea 46bf03d69
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Mar 18 14:38:55 2021 -0700
+
+    Merge pull request #2857 from googlefonts/repacker
+    
+    [subset] add a GSUB/GPOS table repacker to resolve offset overflows.
+
+commit 46bf03d6919087e4ce8f0626a3d342380346dc97
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Mar 18 14:35:36 2021 -0700
+
+    [subset] add NODISCARD to error checking methods on serializer.
+
+ src/hb-serialize.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 3827a3eb567b424e8144564a42a22df74a20a7c6
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Mar 18 11:20:03 2021 -0700
+
+    [subset] rename serializer::set_error() to err().
+
+ src/hb-repacker.hh  |  4 ++--
+ src/hb-serialize.hh | 15 +++++++--------
+ 2 files changed, 9 insertions(+), 10 deletions(-)
+
+commit f561fa6e4c5572c60c8fcf40e617919e531e6ee3
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Mar 18 11:13:47 2021 -0700
+
+    Change priority queue to use (priority, value) instead of (value, priority).
+
+ src/Makefile.sources       |  2 +-
+ src/hb-priority-queue.hh   | 24 +++++++++++++-----------
+ src/hb-repacker.hh         | 14 +++++++-------
+ src/test-priority-queue.cc | 40 ++++++++++++++++++++--------------------
+ 4 files changed, 41 insertions(+), 39 deletions(-)
+
+commit b14475d2ae488acf3c2a169126a4901796401157
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Mar 18 10:51:26 2021 -0700
+
+    [subset] further changes to serializer error handling.
+    
+    - Rename enum type and enum members.
+    - in_errors() now returns true for any error having been set. hb-subset now looks for offset overflow only errors to divert to repacker.
+    - Added INT_OVERFLOW and ARRAY_OVERFLOW enum values.
+
+ src/hb-cff-interp-common.hh    |  2 +-
+ src/hb-open-type.hh            |  8 +++----
+ src/hb-ot-cmap-table.hh        | 11 +++++-----
+ src/hb-ot-hmtx-table.hh        |  2 +-
+ src/hb-ot-layout-gpos-table.hh |  8 +++----
+ src/hb-ot-layout-gsub-table.hh |  2 +-
+ src/hb-repacker.hh             |  4 ++--
+ src/hb-serialize.hh            | 50 ++++++++++++++++++++++++------------------
+ src/hb-subset.cc               |  4 ++--
+ 9 files changed, 50 insertions(+), 41 deletions(-)
+
+commit 73ed59f7a68fc5363ef444b6de131c92cc5ca836
+Author: Garret Rieger <grieger at google.com>
+Date:   Wed Mar 17 15:53:10 2021 -0700
+
+    [subset] store errors in the serializer as a flag set.
+    
+    Make check_assign/check_equal specify the type of error to set.
+
+ src/hb-cff-interp-common.hh    |  2 +-
+ src/hb-open-type.hh            | 10 ++++---
+ src/hb-ot-cmap-table.hh        | 17 +++++++----
+ src/hb-ot-hdmx-table.hh        |  2 +-
+ src/hb-ot-hmtx-table.hh        |  2 +-
+ src/hb-ot-layout-gpos-table.hh |  8 +++---
+ src/hb-ot-layout-gsub-table.hh |  4 +--
+ src/hb-ot-name-table.hh        |  3 +-
+ src/hb-repacker.hh             |  4 +--
+ src/hb-serialize.hh            | 64 +++++++++++++++++++++++++-----------------
+ src/hb-subset.cc               |  8 +++---
+ src/test-repacker.cc           |  4 +--
+ 12 files changed, 76 insertions(+), 52 deletions(-)
+
+commit b9ecc7420df811e94413d77e6d70140e18d6ebe6
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Feb 16 13:39:10 2021 -0800
+
+    [subset] init offset_overflow in hb_serialize_context_t.
+
+ src/hb-serialize.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit cf79fc342d7e59966fc7ba3e8460d58083b33966
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Feb 16 13:24:43 2021 -0800
+
+    [subset] limit priority bumps to 16.
+
+ src/hb-repacker.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 0104409959b15ca8dc344df4a60ce36fc7f40105
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Feb 16 11:38:14 2021 -0800
+
+    Fix repack_tests for distcheck.
+
+ test/subset/data/repack_tests/Makefile.am | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit e2f14e81bd20cc944bdecba7fcea20a4b4eddec0
+Author: Garret Rieger <grieger at google.com>
+Date:   Wed Nov 11 13:55:35 2020 -0800
+
+    [subset] fix memory leaks in test-repacker.
+
+ src/test-repacker.cc | 19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+commit d3e2ba7c01b26da9cc5fac49a204fae8a54a3eb1
+Author: Garret Rieger <grieger at google.com>
+Date:   Wed Nov 11 13:50:18 2020 -0800
+
+    [subset] comment cleanup in hb-repacker.hh
+
+ src/hb-repacker.hh | 35 ++++++++++++++++++++++++-----------
+ 1 file changed, 24 insertions(+), 11 deletions(-)
+
+commit 832f2b599b3d4fad5eea6d0eeef77377d3e0bad0
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Nov 10 16:15:37 2020 -0800
+
+    [subset] Refactor _subset () to reduce nesting and eliminate the use of 'goto'.
+
+ src/hb-serialize.hh |   9 ++++
+ src/hb-subset.cc    | 134 +++++++++++++++++++++++++++++++---------------------
+ src/meson.build     |   1 +
+ 3 files changed, 90 insertions(+), 54 deletions(-)
+
+commit bb5c80a7c2d2454bba745a155146e7eaad912474
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Nov 10 14:11:57 2020 -0800
+
+    [subset] add error tracking to the repacker.
+    Also check for allocation failures as needed.
+
+ src/hb-repacker.hh | 93 ++++++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 62 insertions(+), 31 deletions(-)
+
+commit b8b8c58b9ff9b51108caf47f5d98a15801b39058
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Nov 10 11:56:09 2020 -0800
+
+    [subset] add tests that check for successful repacking of a real font file.
+
+ configure.ac                                       |   1 +
+ test/subset/Makefile.am                            |   2 +
+ test/subset/data/Makefile.am                       |   2 +-
+ test/subset/data/fonts/NotoNastaliqUrdu-Bold.ttf   | Bin 0 -> 459600 bytes
+ test/subset/data/repack_tests/Makefile.am          |  22 +++++
+ test/subset/data/repack_tests/Makefile.sources     |  12 +++
+ .../repack_tests/advanced_prioritization.tests     |  72 ++++++++++++++
+ test/subset/data/repack_tests/basic.tests          |  52 +++++++++++
+ test/subset/data/repack_tests/prioritization.tests |  77 +++++++++++++++
+ .../data/repack_tests/table_duplication.tests      |  97 +++++++++++++++++++
+ test/subset/meson.build                            |  22 +++++
+ test/subset/repack_test.py                         |  36 +++++++
+ test/subset/run-repack-tests.py                    | 104 +++++++++++++++++++++
+ 13 files changed, 498 insertions(+), 1 deletion(-)
+
+commit 6e9468fcfb71c731b0ec5a5e9c434119f16245e9
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Nov 9 16:52:36 2020 -0800
+
+    [subset] cleanup memory leaks in the repacker.
+
+ src/hb-repacker.hh |  7 ++++++-
+ src/hb-subset.cc   | 12 ++++++++----
+ 2 files changed, 14 insertions(+), 5 deletions(-)
+
+commit a7a86a6eb4da25822cf0d42d7dd1668a15325a8f
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Nov 6 16:22:48 2020 -0800
+
+    [subset] Add prioritization offset resolution.
+    Vertices can now be prioritized to force them to sort closer to their parent. The resolver will attempt to use this for overflows on non-shared vertices.
+
+ src/hb-repacker.hh   | 107 +++++++++++++++++++++++++++++++++++++++++----------
+ src/test-repacker.cc |   1 +
+ 2 files changed, 88 insertions(+), 20 deletions(-)
+
+commit b452b2c76c9f76c9ea3501e8eb6534cb172f59ce
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Nov 6 15:37:05 2020 -0800
+
+    [subset] refactor repacker graph to cache edge count and distances of vertices.
+
+ src/hb-repacker.hh   | 315 ++++++++++++++++++++++++++++++---------------------
+ src/test-repacker.cc | 158 +++++++++++++-------------
+ 2 files changed, 265 insertions(+), 208 deletions(-)
+
+commit 75414e82b52d5a3adeb1eb48e64f43472913cba2
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Nov 5 16:39:23 2020 -0800
+
+    [subset] Add table duplication overflow resolution.
+
+ src/hb-debug.hh      |   4 ++
+ src/hb-repacker.hh   | 181 ++++++++++++++++++++++++++++++++++++++++-------
+ src/test-repacker.cc | 196 +++++++++++++++++++++++++++++++++++++++++++++++++--
+ 3 files changed, 347 insertions(+), 34 deletions(-)
+
+commit 8286bd80940a7d136ee503dd1b1142190c6695ff
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Nov 5 14:23:29 2020 -0800
+
+    [subset] use vectors instead of hashmaps throughout the repacker since all keys will be mapped for these use cases.
+
+ src/hb-repacker.hh | 65 ++++++++++++++++++++++++++----------------------------
+ 1 file changed, 31 insertions(+), 34 deletions(-)
+
+commit 519ae96617e1e2867122c5dbbdc8f1bbce89cb24
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Nov 5 11:22:16 2020 -0800
+
+    [subset] switch sort_shortest_distance() to use priority queue.
+
+ src/hb-repacker.hh | 35 +++++++++++++----------------------
+ 1 file changed, 13 insertions(+), 22 deletions(-)
+
+commit 5d3511e5b13eb825ea9914aa2400cc040edef8a7
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Nov 5 10:34:26 2020 -0800
+
+    [subset] Change compute_distances() to use a priority queue.
+
+ src/hb-repacker.hh | 38 ++++++++++++++++++++++++++++----------
+ src/meson.build    |  1 +
+ 2 files changed, 29 insertions(+), 10 deletions(-)
+
+commit 59ac0a0d0a99e91a75d18a3884ae276309370997
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Nov 5 10:29:56 2020 -0800
+
+    [subset] Use priority for comparison in heap.
+
+ src/hb-priority-queue.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 4c8dd41ed90292d4516c539be23c16d625d69a41
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Nov 5 09:21:25 2020 -0800
+
+    [subset] re-write compute distances to use an array lookup for the distance map.
+
+ src/hb-priority-queue.hh |  4 ++--
+ src/hb-repacker.hh       | 55 ++++++++++++++++++++----------------------------
+ src/test-repacker.cc     |  2 ++
+ 3 files changed, 27 insertions(+), 34 deletions(-)
+
+commit 5c4e0ffd9768de0c51a42baa35d9c29636fdd99a
+Author: Garret Rieger <grieger at google.com>
+Date:   Wed Nov 4 16:08:01 2020 -0800
+
+    [subset] Add a basic priority queue datastructure (binary heap).
+
+ src/Makefile.am            |   6 +-
+ src/Makefile.sources       |   1 +
+ src/hb-priority-queue.hh   | 149 +++++++++++++++++++++++++++++++++++++++++++++
+ src/test-priority-queue.cc |  89 +++++++++++++++++++++++++++
+ 4 files changed, 244 insertions(+), 1 deletion(-)
+
+commit dd8e5d0e1b0c52190bf16ab091ee3756b30d4d97
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Nov 3 14:01:42 2020 -0800
+
+    [subset] Only run the repacker for GSUB/GPOS.
+
+ src/hb-subset.cc | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+commit aaa7873d425a6267b1df16f5a1f3750578b438f0
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Nov 2 16:16:27 2020 -0800
+
+    [subset] add topological sort by closest distance via Dijkstra's algorithm.
+
+ src/hb-repacker.hh   | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/test-repacker.cc |  37 ++++++++++++++-
+ 2 files changed, 160 insertions(+), 2 deletions(-)
+
+commit 8ebe5d734f3543b7a1266f252fe96188efc69531
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Nov 2 14:51:39 2020 -0800
+
+    Implement will_overflow ().
+
+ src/hb-repacker.hh   | 73 +++++++++++++++++++++++++++++++++++++++++++++++++---
+ src/test-repacker.cc | 45 ++++++++++++++++++++++++++++++++
+ 2 files changed, 114 insertions(+), 4 deletions(-)
+
+commit 6b1ea4cbe724af10309763b708abc36c968f14a7
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Oct 30 12:16:26 2020 -0700
+
+    [subset] hook up the repacker to run if offset overflows are encountered during subsetting.
+
+ src/hb-serialize.hh | 13 +++++++++++--
+ src/hb-subset.cc    | 30 +++++++++++++++++++++++++++++-
+ 2 files changed, 40 insertions(+), 3 deletions(-)
+
+commit f4c78cc7dd11c83aa3f3a3516e75f4fe689aff19
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Oct 30 10:29:51 2020 -0700
+
+    [subset] Implement Kahn's algo for topological sorting instead of BFS.
+
+ src/hb-repacker.hh   | 88 +++++++++++++++++++++++++++++++++++-----------------
+ src/test-repacker.cc | 69 +++++++++++++++++++++++++++++++++++++---
+ 2 files changed, 124 insertions(+), 33 deletions(-)
+
+commit 00f393dc3fdd40a761df4fe988745ecb0e62df4b
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Oct 29 14:58:34 2020 -0700
+
+    [subset] finish up BFS sort implementation.
+
+ src/hb-repacker.hh   | 93 +++++++++++++++++++++++++++++++++++++++-----------
+ src/test-repacker.cc | 95 ++++++++++++++++++++++++++++++++++++++++++----------
+ 2 files changed, 151 insertions(+), 37 deletions(-)
+
+commit 1584d3cb8faf244ae439cd59eac5f3d006d7a106
+Author: Garret Rieger <grieger at google.com>
+Date:   Wed Oct 28 17:49:09 2020 -0700
+
+    [subset] Start a proof of concept implementation of the GSUB/GPOS offset overflow resolver.
+
+ src/Makefile.am      |   6 +-
+ src/Makefile.sources |   1 +
+ src/hb-repacker.hh   | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-serialize.hh  |   3 +
+ src/test-repacker.cc |  87 +++++++++++++++++++++++++
+ 5 files changed, 276 insertions(+), 1 deletion(-)
+
+commit a7d120aeabbae6a08f3cdd39a5ef1d435c3a4854
+Merge: 69d772e52 56ca43578
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 17 14:33:33 2021 -0700
+
+    Merge pull request #2835 from googlefonts/remove_redundant_sys
+    
+    [subset] Remove redundant LangSys
+
+commit 56ca435787c1686fcfe01bf4db822bb91d9ba769
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Jan 28 15:21:26 2021 -0800
+
+    [subset] fix for collect_features and remove_redundant_lamngsys
+    
+    previously remove_redundant_sys () is missing in harfbuzz, after
+    redundant langsys removal, some features are removed as well in
+    prune_features() in fonttools. This change is trying to get the same
+    result between harfbuzz and fonttools.
+
+ src/hb-ot-layout-common.hh                         | 182 +++++++++++++++++++--
+ src/hb-ot-layout-gpos-table.hh                     |   2 +-
+ src/hb-ot-layout-gsub-table.hh                     |   2 +-
+ src/hb-ot-layout-gsubgpos.hh                       |  75 ++++++++-
+ src/hb-subset-plan.cc                              |  43 ++++-
+ src/hb-subset-plan.hh                              |   6 +-
+ ...-retain-gids.627,644,623,62D,644,627,645,2E.ttf | Bin 48640 -> 48596 bytes
+ ...lar.keep-layout-retain-gids.627,644,62D,628.ttf | Bin 42884 -> 42836 bytes
+ ...iri-Regular.keep-layout-retain-gids.627,644.ttf | Bin 36940 -> 36892 bytes
+ ...yout-retain-gids.633,645,627,621,20,644,627.ttf | Bin 46724 -> 46680 bytes
+ ...Regular.keep-layout-retain-gids.63A,64A,631.ttf | Bin 42896 -> 42896 bytes
+ ....keep-layout.627,644,623,62D,644,627,645,2E.ttf | Bin 13332 -> 13288 bytes
+ .../Amiri-Regular.keep-layout.627,644,62D,628.ttf  | Bin 10232 -> 10188 bytes
+ .../Amiri-Regular.keep-layout.627,644.ttf          | Bin 4412 -> 4364 bytes
+ ...ular.keep-layout.633,645,627,621,20,644,627.ttf | Bin 10372 -> 10324 bytes
+ .../Amiri-Regular.keep-layout.63A,64A,631.ttf      | Bin 7824 -> 7824 bytes
+ test/subset/data/fonts/Amiri-Regular.ttf           | Bin 562684 -> 562980 bytes
+ 17 files changed, 284 insertions(+), 26 deletions(-)
+
+commit 69d772e522c60aa9d73b6ccd550f4a834e7bd9b8
+Author: Garret Rieger <grieger at google.com>
+Date:   Wed Mar 17 14:11:16 2021 -0700
+
+    [subset] Fixed test gsub5 test files.
+
+ ...2.keep-layout-retain-gids.retain-all-codepoint.otf | Bin 3752 -> 3808 bytes
+ ...e_subrules_f2.keep-layout.retain-all-codepoint.otf | Bin 3752 -> 3808 bytes
+ ...2.keep-layout-retain-gids.retain-all-codepoint.otf | Bin 3768 -> 3824 bytes
+ ...e_subrules_f2.keep-layout.retain-all-codepoint.otf | Bin 3768 -> 3824 bytes
+ ...1.keep-layout-retain-gids.retain-all-codepoint.otf | Bin 3772 -> 3828 bytes
+ ...successive_f1.keep-layout.retain-all-codepoint.otf | Bin 3772 -> 3828 bytes
+ 6 files changed, 0 insertions(+), 0 deletions(-)
+
+commit 0e1c0fa404e2ad087265dc59130dbec1c4682258
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue Jan 12 10:17:14 2021 -0800
+
+    [subset] optimize glyph closure method: step 5
+    
+    add testcase and some fixes
+
+ src/hb-ot-layout-common.hh                         |  35 ++++----
+ src/hb-ot-layout-gsub-table.hh                     |  10 +--
+ src/hb-ot-layout-gsubgpos.hh                       |  95 +++++++++++++++------
+ src/hb-ot-layout.cc                                |  18 +++-
+ test/subset/data/Makefile.am                       |   1 +
+ test/subset/data/Makefile.sources                  |   1 +
+ ...ubrules_f2.keep-layout-retain-gids.41,42,43.otf | Bin 0 -> 2248 bytes
+ ...e_subrules_f2.keep-layout-retain-gids.41,42.otf | Bin 0 -> 2224 bytes
+ ...e_subrules_f2.keep-layout-retain-gids.41,43.otf | Bin 0 -> 2060 bytes
+ ...iple_subrules_f2.keep-layout-retain-gids.41.otf | Bin 0 -> 1928 bytes
+ ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3752 bytes
+ ...1_multiple_subrules_f2.keep-layout.41,42,43.otf | Bin 0 -> 1460 bytes
+ ...ext1_multiple_subrules_f2.keep-layout.41,42.otf | Bin 0 -> 1420 bytes
+ ...ext1_multiple_subrules_f2.keep-layout.41,43.otf | Bin 0 -> 1344 bytes
+ ...ontext1_multiple_subrules_f2.keep-layout.41.otf | Bin 0 -> 1228 bytes
+ ...ubrules_f2.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3752 bytes
+ ...ubrules_f2.keep-layout-retain-gids.41,42,43.otf | Bin 0 -> 2264 bytes
+ ...e_subrules_f2.keep-layout-retain-gids.41,42.otf | Bin 0 -> 2236 bytes
+ ...e_subrules_f2.keep-layout-retain-gids.41,43.otf | Bin 0 -> 2060 bytes
+ ...iple_subrules_f2.keep-layout-retain-gids.41.otf | Bin 0 -> 1928 bytes
+ ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3768 bytes
+ ...2_multiple_subrules_f2.keep-layout.41,42,43.otf | Bin 0 -> 1476 bytes
+ ...ext2_multiple_subrules_f2.keep-layout.41,42.otf | Bin 0 -> 1432 bytes
+ ...ext2_multiple_subrules_f2.keep-layout.41,43.otf | Bin 0 -> 1344 bytes
+ ...ontext2_multiple_subrules_f2.keep-layout.41.otf | Bin 0 -> 1228 bytes
+ ...ubrules_f2.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3768 bytes
+ ...cessive_f1.keep-layout-retain-gids.41,42,43.otf | Bin 0 -> 2028 bytes
+ ...successive_f1.keep-layout-retain-gids.41,42.otf | Bin 0 -> 1932 bytes
+ ...successive_f1.keep-layout-retain-gids.41,43.otf | Bin 0 -> 2048 bytes
+ ...t3_successive_f1.keep-layout-retain-gids.41.otf | Bin 0 -> 1916 bytes
+ ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3772 bytes
+ ...context3_successive_f1.keep-layout.41,42,43.otf | Bin 0 -> 1328 bytes
+ ...ub_context3_successive_f1.keep-layout.41,42.otf | Bin 0 -> 1228 bytes
+ ...ub_context3_successive_f1.keep-layout.41,43.otf | Bin 0 -> 1332 bytes
+ .../gsub_context3_successive_f1.keep-layout.41.otf | Bin 0 -> 1216 bytes
+ ...cessive_f1.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3772 bytes
+ .../fonts/gsub_context1_multiple_subrules_f2.otf   | Bin 0 -> 4776 bytes
+ .../fonts/gsub_context2_multiple_subrules_f2.otf   | Bin 0 -> 4796 bytes
+ .../data/fonts/gsub_context3_successive_f1.otf     | Bin 0 -> 4760 bytes
+ test/subset/data/tests/layout.gsub5.tests          |  15 ++++
+ test/subset/meson.build                            |   1 +
+ 41 files changed, 124 insertions(+), 52 deletions(-)
+
+commit b8a58a0c0b7d62c33b106ad119a567b6d86d1d36
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Sun Jan 10 15:50:04 2021 -0800
+
+    [subset] optimize glyph closure method: step 4
+    
+    optimize recurse_lookups in Context/ChainContext
+    glyph closure, only the glyphs that the parent lookup
+    can apply the recursion to can participate in recursing
+    the lookup.
+
+ src/hb-ot-layout-gsub-table.hh |  84 ++++------------
+ src/hb-ot-layout-gsubgpos.hh   | 219 +++++++++++++++++++++++++++++++----------
+ 2 files changed, 186 insertions(+), 117 deletions(-)
+
+commit 62423504ee6dcf282177ea0b91268df4e7a1e30b
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue Jan 5 14:54:40 2021 -0800
+
+    [subset] optimize glyph closure method: step 3
+    
+    Add function intersects_coverage_glyphs that collects
+    set of matching glyphs in Coverage table
+
+ src/hb-ot-layout-common.hh | 39 ++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 34 insertions(+), 5 deletions(-)
+
+commit ef78d0f92345eb452e94c73301bc929822755b27
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue Jan 5 10:16:50 2021 -0800
+
+    [subset] optimize glyph closure method: step 2
+    Add function intersects_class_glyphs that collects
+    set of glyphs matching class in ClassDef table
+
+ src/hb-ot-layout-common.hh | 75 ++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 75 insertions(+)
+
+commit b4fc593c3c34c45521c684cb6d0d24079d553e3a
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Wed Dec 9 10:44:18 2020 -0800
+
+    [subset] optimize glyph closure method: step1
+    
+    Previous GSUB glyph closure is done by recursively visiting
+    all reachable lookup tables that apply to any glyphs in the
+    current/input glyph set, but actually only the glyphs that
+    the parent lookup can apply the recursion to can participate
+    in recursing the lookup. This is step 1 for glyph closure
+    optimization:
+    1. Add stack of currently active glyph set pointers into hb_closure_context_t
+    2. Update closure() method in simple GSUB tables to use
+    this stack in order not to change current glyph set at different stages
+    of recursion
+    3. Add function may_have_non_1to1() to GSUB tables
+
+ src/hb-ot-layout-gsub-table.hh | 100 ++++++++++++++++++++++++++++++++++++++---
+ src/hb-ot-layout-gsubgpos.hh   |  57 ++++++++++++++++++++++-
+ 2 files changed, 150 insertions(+), 7 deletions(-)
+
+commit 5f4c321d4aae659f83178143d5a4df0d2d6b4d02
+Merge: 03538e872 1b79b8cd2
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Mar 17 10:20:59 2021 -0700
+
+    Merge pull request #2894 from googlefonts/gpos_2
+    
+    [subset] Update PairPosFormat2 subsetting to match fontTools
+
+commit 1b79b8cd2daebc99acd9310742755f02162e5ed0
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Mar 16 15:23:11 2021 -0700
+
+    [subset] update gpos tests to reflect updated behaviour.
+
+ test/api/fonts/AdobeVFPrototype.WA.gpos.otf | Bin 3948 -> 4148 bytes
+ test/api/fonts/Roboto-Regular-gpos-aw.ttf   | Bin 2232 -> 2236 bytes
+ test/api/test-subset-gpos.c                 |   5 -----
+ 3 files changed, 5 deletions(-)
+
+commit 2df39bcae7e34630361a49c44e9d295233367ce0
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Mar 16 14:20:49 2021 -0700
+
+    [subset] don't allocate a set to use as a glyph filter for PairPosFormat2.
+
+ src/hb-ot-layout-common.hh     | 34 ++++++++++++++++++++++------------
+ src/hb-ot-layout-gpos-table.hh |  7 +------
+ 2 files changed, 23 insertions(+), 18 deletions(-)
+
+commit b1b1486d07f8fe3c7a1fb4bc87e6f037ff5b47d3
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Mar 16 13:32:23 2021 -0700
+
+    [subset] update expected files to not include cmap12 pruning.
+
+ .../Roboto-Regular.keep-gdef-gpos.1E00,303.ttf      | Bin 2648 -> 2648 bytes
+ .../Roboto-Regular.keep-gdef-gpos.41,42,43.ttf      | Bin 2736 -> 2728 bytes
+ ...os2_2_font5.keep-layout-retain-gids.21,23,25.otf | Bin 1824 -> 1816 bytes
+ .../gpos2_2_font5.keep-layout-retain-gids.21,23.otf | Bin 1692 -> 1684 bytes
+ .../gpos2_2_font5.keep-layout-retain-gids.2E,23.otf | Bin 2024 -> 1944 bytes
+ ...keep-layout-retain-gids.retain-all-codepoint.otf | Bin 3732 -> 3724 bytes
+ .../gpos2_2_font5.keep-layout.21,23,25.otf          | Bin 1488 -> 1480 bytes
+ .../gpos2_2_font5.keep-layout.21,23.otf             | Bin 1368 -> 1360 bytes
+ .../gpos2_2_font5.keep-layout.2E,23.otf             | Bin 1588 -> 1508 bytes
+ ...os2_2_font5.keep-layout.retain-all-codepoint.otf | Bin 3732 -> 3724 bytes
+ ...t-retain-gids.627,644,623,62D,644,627,645,2E.ttf | Bin 48640 -> 48640 bytes
+ ...r.keep-layout.627,644,623,62D,644,627,645,2E.ttf | Bin 13332 -> 13332 bytes
+ 12 files changed, 0 insertions(+), 0 deletions(-)
+
+commit bb54e1047d2d501459bb366e47f24f51824c8db7
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Mar 16 13:19:26 2021 -0700
+
+    [subset] Also filter class1 by coverage when collecting variation indices for PairPosFormat2.
+
+ src/hb-ot-layout-gpos-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 190b7a98f8af54cc42d3ccdb6979e432dfd41aa9
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Oct 8 14:44:54 2020 -0700
+
+    [subset] Update PairPosFormat2 subsetting to match fontTools updated subsetting (https://github.com/fonttools/fonttools/pull/2221)
+    
+    - subset class def 1 against the coverage table.
+    - Don't re-use class 0 in class def 2.
+    - Ignore class 0 glyphs for the purposes of determing format 1 vs format 2 encoding for ClassDef.
+    
+    Add an additional test case which demonstrates these issues.
+
+ src/hb-ot-layout-common.hh                         |  43 +++++++++++++--------
+ src/hb-ot-layout-gpos-table.hh                     |  14 +++++--
+ ...AdobeVFPrototype.keep-gdef-gpos.41,42,43,57.otf | Bin 5444 -> 5400 bytes
+ .../AdobeVFPrototype.keep-gdef-gpos.41,42,43.otf   | Bin 4916 -> 4872 bytes
+ .../AdobeVFPrototype.keep-gdef-gpos.41,42.otf      | Bin 4436 -> 4392 bytes
+ .../AdobeVFPrototype.keep-gdef-gpos.41,56,57.otf   | Bin 4556 -> 4540 bytes
+ .../AdobeVFPrototype.keep-gdef-gpos.41.otf         | Bin 3692 -> 3688 bytes
+ .../AdobeVFPrototype.keep-gdef-gpos.42,57.otf      | Bin 4556 -> 4524 bytes
+ ...gpos2_1_font7.keep-layout-retain-gids.2E,23.otf | Bin 0 -> 1944 bytes
+ .../gpos2_1_font7.keep-layout.2E,23.otf            | Bin 0 -> 1508 bytes
+ ...s2_2_font5.keep-layout-retain-gids.21,23,25.otf | Bin 1776 -> 1824 bytes
+ ...gpos2_2_font5.keep-layout-retain-gids.21,23.otf | Bin 1644 -> 1692 bytes
+ ...gpos2_2_font5.keep-layout-retain-gids.2E,23.otf | Bin 0 -> 2024 bytes
+ ...s2_2_font5.keep-layout-retain-gids.41,42,43.otf | Bin 1988 -> 1988 bytes
+ ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 3684 -> 3732 bytes
+ .../gpos2_2_font5.keep-layout.21,23,25.otf         | Bin 1440 -> 1488 bytes
+ .../gpos2_2_font5.keep-layout.21,23.otf            | Bin 1320 -> 1368 bytes
+ .../gpos2_2_font5.keep-layout.2E,23.otf            | Bin 0 -> 1588 bytes
+ .../gpos2_2_font5.keep-layout.41,42,43.otf         | Bin 1288 -> 1288 bytes
+ ...s2_2_font5.keep-layout.retain-all-codepoint.otf | Bin 3684 -> 3732 bytes
+ test/subset/data/fonts/gpos2_2_font5.otf           | Bin 4580 -> 4632 bytes
+ test/subset/data/tests/layout.gpos2.tests          |   1 +
+ 22 files changed, 38 insertions(+), 20 deletions(-)
+
 commit 03538e872a0610a65fad692b33d3646f387cf578
 Author: Khaled Hosny <khaled at aliftype.com>
 Date:   Tue Mar 16 19:28:35 2021 +0200

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/Makefile.am
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/Makefile.am	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/Makefile.am	2021-05-05 22:28:05 UTC (rev 59092)
@@ -20,7 +20,6 @@
 	meson.build \
 	meson_options.txt \
 	subprojects/expat.wrap \
-	subprojects/fontconfig.wrap \
 	subprojects/freetype2.wrap \
 	subprojects/glib.wrap \
 	subprojects/libffi.wrap \

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS	2021-05-05 22:28:05 UTC (rev 59092)
@@ -1,3 +1,12 @@
+Overview of changes leading to 2.8.1
+Tuesday, May 4, 2021
+====================================
+- Subsetter now fully supports GSUB/GPOS/GDEF tables (including variations); as
+  such, layout tables are retained by subsetter by default. (Garret Rieger, Qunxin Liu)
+- Build scripts no longer check for FontConfig as HarfBuzz does not use it.
+- hb-view supports iTerm2 and kitty inline image protocols (Khaled Hosny),
+  it can also use Chafa for terminal graphics if available (Hans Petter Jansson).
+
 Overview of changes leading to 2.8.0
 Tuesday, March 16, 2021
 ====================================

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in	2021-05-05 22:28:05 UTC (rev 59092)
@@ -12,6 +12,9 @@
 /* Have cairo-ft support in cairo graphics library */
 #undef HAVE_CAIRO_FT
 
+/* Have chafa terminal graphics library */
+#undef HAVE_CHAFA
+
 /* Have Core Text backend */
 #undef HAVE_CORETEXT
 
@@ -27,9 +30,6 @@
 /* Define to 1 if you have the <dwrite.h> header file. */
 #undef HAVE_DWRITE_H
 
-/* Have fontconfig library */
-#undef HAVE_FONTCONFIG
-
 /* Have FreeType 2 library */
 #undef HAVE_FREETYPE
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac	2021-05-05 22:28:05 UTC (rev 59092)
@@ -1,6 +1,6 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [2.8.0],
+        [2.8.1],
         [https://github.com/harfbuzz/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
@@ -214,21 +214,21 @@
 
 dnl ==========================================================================
 
-AC_ARG_WITH(fontconfig,
-	[AS_HELP_STRING([--with-fontconfig=@<:@yes/no/auto@:>@],
-			[Use fontconfig @<:@default=auto@:>@])],,
-	[with_fontconfig=auto])
-have_fontconfig=false
-if test "x$with_fontconfig" = "xyes" -o "x$with_fontconfig" = "xauto"; then
-	PKG_CHECK_MODULES(FONTCONFIG, fontconfig, have_fontconfig=true, :)
+AC_ARG_WITH(chafa,
+	[AS_HELP_STRING([--with-chafa=@<:@yes/no/auto@:>@],
+			[Use chafa @<:@default=auto@:>@])],,
+	[with_chafa=auto])
+have_chafa=false
+if test "x$with_chafa" = "xyes" -o "x$with_chafa" = "xauto"; then
+	PKG_CHECK_MODULES(CHAFA, chafa >= 1.6.0, have_chafa=true, :)
 fi
-if test "x$with_fontconfig" = "xyes" -a "x$have_fontconfig" != "xtrue"; then
-	AC_MSG_ERROR([fontconfig support requested but not found])
+if test "x$with_chafa" = "xyes" -a "x$have_chafa" != "xtrue"; then
+	AC_MSG_ERROR([chafa support requested but not found])
 fi
-if $have_fontconfig; then
-	AC_DEFINE(HAVE_FONTCONFIG, 1, [Have fontconfig library])
+if $have_chafa; then
+	AC_DEFINE(HAVE_CHAFA, 1, [Have chafa terminal graphics library])
 fi
-AM_CONDITIONAL(HAVE_FONTCONFIG, $have_fontconfig)
+AM_CONDITIONAL(HAVE_CHAFA, $have_chafa)
 
 dnl ==========================================================================
 
@@ -432,6 +432,7 @@
 test/shaping/data/text-rendering-tests/Makefile
 test/subset/Makefile
 test/subset/data/Makefile
+test/subset/data/repack_tests/Makefile
 docs/Makefile
 docs/version.xml
 ])
@@ -465,7 +466,7 @@
 
 Tools used for command-line utilities:
 	Cairo:			${have_cairo}
-	Fontconfig:		${have_fontconfig}
+	Chafa:			${have_chafa}
 
 Additional shapers:
 	Graphite2:		${have_graphite2}

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build	2021-05-05 22:28:05 UTC (rev 59092)
@@ -1,6 +1,6 @@
 project('harfbuzz', 'c', 'cpp',
   meson_version: '>= 0.47.0',
-  version: '2.8.0',
+  version: '2.8.1',
   default_options: [
     'cpp_eh=none',          # Just to support msvc, we are passing -fno-rtti also anyway
     'cpp_rtti=false',       # Just to support msvc, we are passing -fno-exceptions also anyway
@@ -95,8 +95,6 @@
                       fallback: ['glib', 'libglib_dep'])
 gobject_dep = dependency('gobject-2.0', required: get_option('gobject'),
                          fallback: ['glib', 'libgobject_dep'])
-fontconfig_dep = dependency('fontconfig', required: get_option('fontconfig'),
-                            fallback: ['fontconfig', 'fontconfig_dep'])
 graphite2_dep = dependency('graphite2', required: get_option('graphite'))
 
 icu_dep = null_dep
@@ -156,6 +154,8 @@
   endif
 endif
 
+chafa_dep = dependency('chafa', version: '>= 1.6.0', required: get_option('chafa'))
+
 conf = configuration_data()
 incconfig = include_directories('.')
 
@@ -183,6 +183,10 @@
   conf.set('HAVE_CAIRO_FT', 1)
 endif
 
+if chafa_dep.found()
+  conf.set('HAVE_CHAFA', 1)
+endif
+
 if graphite2_dep.found()
   conf.set('HAVE_GRAPHITE2', 1)
 endif
@@ -217,10 +221,6 @@
   endif
 endif
 
-if fontconfig_dep.found()
-  conf.set('HAVE_FONTCONFIG', 1)
-endif
-
 gdi_uniscribe_deps = []
 # GDI (Uniscribe) (Windows)
 if host_machine.system() == 'windows' and not get_option('gdi').disabled()
@@ -369,7 +369,7 @@
     },
   'Dependencies used for command-line utilities':
     {'Cairo': conf.get('HAVE_CAIRO', 0) == 1,
-     'Fontconfig': conf.get('HAVE_FONTCONFIG', 0) == 1,
+     'Chafa': conf.get('HAVE_CHAFA', 0) == 1,
     },
   'Additional shapers':
     {'Graphite2': conf.get('HAVE_GRAPHITE2', 0) == 1,

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt	2021-05-05 22:28:05 UTC (rev 59092)
@@ -5,8 +5,8 @@
   description: 'Enable GObject bindings')
 option('cairo', type: 'feature', value: 'auto',
   description: 'Use Cairo graphics library')
-option('fontconfig', type: 'feature', value: 'auto',
-  description: 'Use fontconfig')
+option('chafa', type: 'feature', value: 'auto',
+  description: 'Use Chafa terminal graphics library')
 option('icu', type: 'feature', value: 'auto',
   description: 'Enable ICU library unicode functions')
 option('graphite', type: 'feature', value: 'disabled',

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am	2021-05-05 22:28:05 UTC (rev 59092)
@@ -342,7 +342,7 @@
 test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
 test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
 
-COMPILED_TESTS = test-algs test-array test-iter test-meta test-number test-ot-tag test-unicode-ranges test-bimap
+COMPILED_TESTS = test-algs test-array test-iter test-meta test-number test-ot-tag test-priority-queue test-unicode-ranges test-bimap test-repacker
 COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
 COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
 check_PROGRAMS += $(COMPILED_TESTS)
@@ -356,6 +356,14 @@
 test_array_CPPFLAGS = $(HBCFLAGS)
 test_array_LDADD = libharfbuzz.la $(HBLIBS)
 
+test_priority_queue_SOURCES = test-priority-queue.cc hb-static.cc
+test_priority_queue_CPPFLAGS = $(HBCFLAGS)
+test_priority_queue_LDADD = libharfbuzz.la $(HBLIBS)
+
+test_repacker_SOURCES = test-repacker.cc hb-static.cc
+test_repacker_CPPFLAGS = $(HBCFLAGS)
+test_repacker_LDADD = libharfbuzz.la libharfbuzz-subset.la $(HBLIBS)
+
 test_iter_SOURCES = test-iter.cc hb-static.cc
 test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
 test_iter_LDADD = $(COMPILED_TESTS_LDADD)

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources	2021-05-05 22:28:05 UTC (rev 59092)
@@ -167,6 +167,7 @@
 	hb-unicode.hh \
 	hb-utf.hh \
 	hb-vector.hh \
+	hb-priority-queue.hh \
 	hb.hh \
 	$(NULL)
 
@@ -268,6 +269,7 @@
 	hb-subset-plan.hh \
 	hb-subset.cc \
 	hb-subset.hh \
+	hb-repacker.hh \
 	$(NULL)
 
 HB_SUBSET_headers = \

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py	2021-05-05 22:28:05 UTC (rev 59092)
@@ -25,10 +25,8 @@
 """
 
 import collections
+import html
 from html.parser import HTMLParser
-def write (s):
-	sys.stdout.flush ()
-	sys.stdout.buffer.write (s.encode ('utf-8'))
 import itertools
 import re
 import sys
@@ -37,10 +35,6 @@
 if len (sys.argv) != 3:
 	sys.exit (__doc__)
 
-from html import unescape
-def html_unescape (parser, entity):
-	return unescape (entity)
-
 def expect (condition, message=None):
 	if not condition:
 		if message is None:
@@ -47,6 +41,10 @@
 			raise AssertionError
 		raise AssertionError (message)
 
+def write (s):
+	sys.stdout.flush ()
+	sys.stdout.buffer.write (s.encode ('utf-8'))
+
 DEFAULT_LANGUAGE_SYSTEM = ''
 
 # from https://www-01.sil.org/iso639-3/iso-639-3.tab
@@ -383,10 +381,10 @@
 			self._current_tr[-1] += data
 
 	def handle_charref (self, name):
-		self.handle_data (html_unescape (self, '&#%s;' % name))
+		self.handle_data (html.unescape ('&#%s;' % name))
 
 	def handle_entityref (self, name):
-		self.handle_data (html_unescape (self, '&%s;' % name))
+		self.handle_data (html.unescape ('&%s;' % name))
 
 	def parse (self, filename):
 		"""Parse the OpenType language system tag registry.

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-ankr-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-ankr-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-ankr-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -54,7 +54,7 @@
   DEFINE_SIZE_STATIC (4);
 };
 
-typedef LArrayOf<Anchor> GlyphAnchors;
+typedef Array32Of<Anchor> GlyphAnchors;
 
 struct ankr
 {
@@ -64,7 +64,7 @@
 			    unsigned int i,
 			    unsigned int num_glyphs) const
   {
-    const NNOffsetTo<GlyphAnchors> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs);
+    const NNOffset16To<GlyphAnchors> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs);
     if (!offset)
       return Null (Anchor);
     const GlyphAnchors &anchors = &(this+anchorData) + *offset;
@@ -83,9 +83,9 @@
   protected:
   HBUINT16	version;	/* Version number (set to zero) */
   HBUINT16	flags;		/* Flags (currently unused; set to zero) */
-  LOffsetTo<Lookup<NNOffsetTo<GlyphAnchors>>>
+  Offset32To<Lookup<NNOffset16To<GlyphAnchors>>>
 		lookupTable;	/* Offset to the table's lookup table */
-  LNNOffsetTo<HBUINT8>
+  NNOffset32To<HBUINT8>
 		anchorData;	/* Offset to the glyph data table */
 
   public:

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -164,7 +164,7 @@
 
   HBGlyphID	last;		/* Last GlyphID in this segment */
   HBGlyphID	first;		/* First GlyphID in this segment */
-  NNOffsetTo<UnsizedArrayOf<T>>
+  NNOffset16To<UnsizedArrayOf<T>>
 		valuesZ;	/* A 16-bit offset from the start of
 				 * the table to the data. */
   public:
@@ -659,7 +659,7 @@
   }
   protected:
   HBGlyphID		firstGlyph;	/* First glyph index included in the trimmed array. */
-  ArrayOf<HBUCHAR>	classArray;	/* The class codes (indexed by glyph index minus
+  Array16Of<HBUCHAR>	classArray;	/* The class codes (indexed by glyph index minus
 					 * firstGlyph). */
   public:
   DEFINE_SIZE_ARRAY (4, classArray);
@@ -678,7 +678,8 @@
 				     const void *base,
 				     const T *array)
   {
-    return (offset - ((const char *) array - (const char *) base)) / T::static_size;
+    /* https://github.com/harfbuzz/harfbuzz/issues/2816 */
+    return (offset - unsigned ((const char *) array - (const char *) base)) / T::static_size;
   }
   template <typename T>
   static unsigned int byteOffsetToIndex (unsigned int offset,

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-feat-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-feat-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-feat-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -144,7 +144,7 @@
   protected:
   HBUINT16	feature;	/* Feature type. */
   HBUINT16	nSettings;	/* The number of records in the setting name array. */
-  LNNOffsetTo<UnsizedArrayOf<SettingName>>
+  NNOffset32To<UnsizedArrayOf<SettingName>>
 		settingTableZ;	/* Offset in bytes from the beginning of this table to
 				 * this feature's setting name array. The actual type of
 				 * record this offset refers to will depend on the

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-just-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-just-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-just-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -79,7 +79,7 @@
 				 * to decompose before more frequent ones. The ligatures
 				 * on the line of text will decompose in increasing
 				 * value of this field. */
-  ArrayOf<HBUINT16>
+  Array16Of<HBUINT16>
 		decomposedglyphs;
 				/* Number of 16-bit glyph indexes that follow;
 				 * the ligature will be decomposed into these glyphs.
@@ -310,7 +310,7 @@
   DEFINE_SIZE_STATIC (24);
 };
 
-typedef OT::LArrayOf<WidthDeltaPair> WidthDeltaCluster;
+typedef OT::Array32Of<WidthDeltaPair> WidthDeltaCluster;
 
 struct JustificationCategory
 {
@@ -358,20 +358,20 @@
   }
 
   protected:
-  OffsetTo<JustificationCategory>
+  Offset16To<JustificationCategory>
 		justClassTable;	/* Offset to the justification category state table. */
-  OffsetTo<WidthDeltaCluster>
+  Offset16To<WidthDeltaCluster>
 		wdcTable;	/* Offset from start of justification table to start
 				 * of the subtable containing the width delta factors
 				 * for the glyphs in your font.
 				 *
 				 * The width delta clusters table. */
-  OffsetTo<PostcompensationActionChain>
+  Offset16To<PostcompensationActionChain>
 		pcTable;	/* Offset from start of justification table to start
 				 * of postcompensation subtable (set to zero if none).
 				 *
 				 * The postcompensation subtable, if present in the font. */
-  Lookup<OffsetTo<WidthDeltaCluster>>
+  Lookup<Offset16To<WidthDeltaCluster>>
 		lookupTable;	/* Lookup table associating glyphs with width delta
 				 * clusters. See the description of Width Delta Clusters
 				 * table for details on how to interpret the lookup values. */
@@ -398,13 +398,13 @@
   FixedVersion<>version;	/* Version of the justification table
 				 * (0x00010000u for version 1.0). */
   HBUINT16	format;		/* Format of the justification table (set to 0). */
-  OffsetTo<JustificationHeader>
+  Offset16To<JustificationHeader>
 		horizData;	/* Byte offset from the start of the justification table
 				 * to the header for tables that contain justification
 				 * information for horizontal text.
 				 * If you are not including this information,
 				 * store 0. */
-  OffsetTo<JustificationHeader>
+  Offset16To<JustificationHeader>
 		vertData;	/* ditto, vertical */
 
   public:

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -710,18 +710,18 @@
   {
     struct Long
     {
-      LNNOffsetTo<Lookup<HBUINT32>>		rowIndexTable;
-      LNNOffsetTo<Lookup<HBUINT32>>		columnIndexTable;
-      LNNOffsetTo<UnsizedArrayOf<FWORD32>>	array;
+      NNOffset32To<Lookup<HBUINT32>>		rowIndexTable;
+      NNOffset32To<Lookup<HBUINT32>>		columnIndexTable;
+      NNOffset32To<UnsizedArrayOf<FWORD32>>	array;
     } l;
     struct Short
     {
-      LNNOffsetTo<Lookup<HBUINT16>>		rowIndexTable;
-      LNNOffsetTo<Lookup<HBUINT16>>		columnIndexTable;
-      LNNOffsetTo<UnsizedArrayOf<FWORD>>	array;
+      NNOffset32To<Lookup<HBUINT16>>		rowIndexTable;
+      NNOffset32To<Lookup<HBUINT16>>		columnIndexTable;
+      NNOffset32To<UnsizedArrayOf<FWORD>>	array;
     } s;
   } u;
-  LNNOffsetTo<UnsizedArrayOf<FWORD>>	vector;
+  NNOffset32To<UnsizedArrayOf<FWORD>>	vector;
   public:
   DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 24);
 };

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -304,7 +304,7 @@
     bool mark_set;
     unsigned int mark;
     const ContextualSubtable *table;
-    const UnsizedOffsetListOf<Lookup<HBGlyphID>, HBUINT, false> &subs;
+    const UnsizedListOfOffset16To<Lookup<HBGlyphID>, HBUINT, false> &subs;
   };
 
   bool apply (hb_aat_apply_context_t *c) const
@@ -348,7 +348,7 @@
   protected:
   StateTable<Types, EntryData>
 		machine;
-  NNOffsetTo<UnsizedOffsetListOf<Lookup<HBGlyphID>, HBUINT, false>, HBUINT>
+  NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID>, HBUINT, false>, HBUINT>
 		substitutionTables;
   public:
   DEFINE_SIZE_STATIC (20);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-opbd-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-opbd-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-opbd-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -58,7 +58,7 @@
   bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
 		   hb_glyph_extents_t *extents, const void *base) const
   {
-    const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
+    const Offset16To<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
     if (!bounds_offset) return false;
     const OpticalBounds &bounds = base+*bounds_offset;
 
@@ -79,7 +79,7 @@
   }
 
   protected:
-  Lookup<OffsetTo<OpticalBounds>>
+  Lookup<Offset16To<OpticalBounds>>
 		lookupTable;	/* Lookup table associating glyphs with the four
 				 * int16 values for the left-side, top-side,
 				 * right-side, and bottom-side optical bounds. */
@@ -92,7 +92,7 @@
   bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
 		   hb_glyph_extents_t *extents, const void *base) const
   {
-    const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
+    const Offset16To<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
     if (!bounds_offset) return false;
     const OpticalBounds &bounds = base+*bounds_offset;
 
@@ -116,7 +116,7 @@
   }
 
   protected:
-  Lookup<OffsetTo<OpticalBounds>>
+  Lookup<Offset16To<OpticalBounds>>
 		lookupTable;	/* Lookup table associating glyphs with the four
 				 * int16 values for the left-side, top-side,
 				 * right-side, and bottom-side optical bounds. */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -66,7 +66,7 @@
   NameID	trackNameID;	/* The 'name' table index for this track.
 				 * (a short word or phrase like "loose"
 				 * or "very tight") */
-  NNOffsetTo<UnsizedArrayOf<FWORD>>
+  NNOffset16To<UnsizedArrayOf<FWORD>>
 		valuesZ;	/* Offset from start of tracking table to
 				 * per-size tracking values for this track. */
 
@@ -141,7 +141,7 @@
   protected:
   HBUINT16	nTracks;	/* Number of separate tracks included in this table. */
   HBUINT16	nSizes;		/* Number of point sizes included in this table. */
-  LNNOffsetTo<UnsizedArrayOf<HBFixed>>
+  NNOffset32To<UnsizedArrayOf<HBFixed>>
 		sizeTable;	/* Offset from start of the tracking table to
 				 * Array[nSizes] of size values.. */
   UnsizedArrayOf<TrackTableEntry>
@@ -212,10 +212,10 @@
   FixedVersion<>version;	/* Version of the tracking table
 				 * (0x00010000u for version 1.0). */
   HBUINT16	format;		/* Format of the tracking table (set to 0). */
-  OffsetTo<TrackData>
+  Offset16To<TrackData>
 		horizData;	/* Offset from start of tracking table to TrackData
 				 * for horizontal text (or 0 if none). */
-  OffsetTo<TrackData>
+  Offset16To<TrackData>
 		vertData;	/* Offset from start of tracking table to TrackData
 				 * for vertical text (or 0 if none). */
   HBUINT16	reserved;	/* Reserved. Set to 0. */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-ltag-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-ltag-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-ltag-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -50,7 +50,7 @@
   }
 
   protected:
-  NNOffsetTo<UnsizedArrayOf<HBUINT8>>
+  NNOffset16To<UnsizedArrayOf<HBUINT8>>
 		tag;		/* Offset from the start of the table to
 				 * the beginning of the string */
   HBUINT16	length;		/* String length (in bytes) */
@@ -80,7 +80,7 @@
   protected:
   HBUINT32	version;	/* Table version; currently 1 */
   HBUINT32	flags;		/* Table flags; currently none defined */
-  LArrayOf<FTStringRange>
+  Array32Of<FTStringRange>
 		tagRanges;	/* Range for each tag's string */
   public:
   DEFINE_SIZE_ARRAY (12, tagRanges);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -219,7 +219,7 @@
 	    unsigned P = sizeof (Type),
 	    hb_enable_if (P == 1)>
   const T *as () const
-  { return length < hb_null_size (T) ? &Null (T) : reinterpret_cast<const T *> (arrayZ); }
+  { return length < hb_min_size (T) ? &Null (T) : reinterpret_cast<const T *> (arrayZ); }
 
   template <typename T,
 	    unsigned P = sizeof (Type),

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -263,7 +263,7 @@
 
     T *ip = c->allocate_size<T> (T::static_size);
     if (unlikely (!ip)) return_trace (false);
-    return_trace (c->check_assign (*ip, value));
+    return_trace (c->check_assign (*ip, value, HB_SERIALIZE_ERROR_INT_OVERFLOW));
   }
 
   template <typename V>

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -86,6 +86,9 @@
 #define HB_NO_LEGACY
 #endif
 
+#ifdef HAVE_CONFIG_OVERRIDE_H
+#include "config-override.h"
+#endif
 
 /* Closure of options. */
 
@@ -155,9 +158,5 @@
 #endif
 #endif
 
-#ifdef HAVE_CONFIG_OVERRIDE_H
-#include "config-override.h"
-#endif
 
-
 #endif /* HB_CONFIG_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -438,6 +438,10 @@
 #define TRACE_SUBSET(this) hb_no_trace_t<bool> trace
 #endif
 
+#ifndef HB_DEBUG_SUBSET_REPACK
+#define HB_DEBUG_SUBSET_REPACK (HB_DEBUG+0)
+#endif
+
 #ifndef HB_DEBUG_DISPATCH
 #define HB_DEBUG_DISPATCH ( \
 	HB_DEBUG_APPLY + \

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc	2021-05-05 22:28:05 UTC (rev 59092)
@@ -623,7 +623,7 @@
   * but we never attempt to shape a word longer than 64K characters
   * in a single gfxShapedWord, so we cannot exceed that limit.
   */
-  uint32_t textLength = buffer->len;
+  uint32_t textLength = chars_len;
 
   TextAnalysis analysis (textString, textLength, nullptr, readingDirection);
   TextAnalysis::Run *runHead;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -140,9 +140,9 @@
     return true;
   }
 
-  void set (K key, V value)
+  bool set (K key, V value)
   {
-    set_with_hash (key, hb_hash (key), value);
+    return set_with_hash (key, hb_hash (key), value);
   }
 
   V get (K key) const
@@ -211,15 +211,15 @@
 
   protected:
 
-  void set_with_hash (K key, uint32_t hash, V value)
+  bool 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;
+    if (unlikely (!successful)) return false;
+    if (unlikely (key == kINVALID)) return true;
+    if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
     unsigned int i = bucket_for_hash (key, hash);
 
     if (value == vINVALID && items[i].key != key)
-      return; /* Trying to delete non-existent key. */
+      return true; /* Trying to delete non-existent key. */
 
     if (!items[i].is_unused ())
     {
@@ -235,6 +235,8 @@
     occupancy++;
     if (!items[i].is_tombstone ())
       population++;
+
+    return true;
   }
 
   unsigned int bucket_for (K key) const

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -39,8 +39,11 @@
 
 #define HB_NULL_POOL_SIZE 384
 
-/* Use SFINAE to sniff whether T has min_size; in which case return T::null_size,
- * otherwise return sizeof(T). */
+/* Use SFINAE to sniff whether T has min_size; in which case return the larger
+ * of sizeof(T) and T::null_size, otherwise return sizeof(T).
+ *
+ * The main purpose of this is to let structs communicate that they are not nullable,
+ * by defining min_size but *not* null_size. */
 
 /* The hard way...
  * https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
@@ -49,8 +52,9 @@
 template <typename T, typename>
 struct _hb_null_size : hb_integral_constant<unsigned, sizeof (T)> {};
 template <typename T>
-struct _hb_null_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::null_size> {};
-
+struct _hb_null_size<T, hb_void_t<decltype (T::min_size)>>
+	: hb_integral_constant<unsigned,
+			       (sizeof (T) > T::null_size ? sizeof (T) : T::null_size)> {};
 template <typename T>
 using hb_null_size = _hb_null_size<T, void>;
 #define hb_null_size(T) hb_null_size<T>::value
@@ -68,7 +72,15 @@
 using hb_static_size = _hb_static_size<T, void>;
 #define hb_static_size(T) hb_static_size<T>::value
 
+template <typename T, typename>
+struct _hb_min_size : hb_integral_constant<unsigned, sizeof (T)> {};
+template <typename T>
+struct _hb_min_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::min_size> {};
+template <typename T>
+using hb_min_size = _hb_min_size<T, void>;
+#define hb_min_size(T) hb_min_size<T>::value
 
+
 /*
  * Null()
  */

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -218,7 +218,7 @@
   Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
   FixedVersion<>version;	/* Version of the TTC Header (1.0),
 				 * 0x00010000u */
-  LArrayOf<LOffsetTo<OpenTypeOffsetTable>>
+  Array32Of<Offset32To<OpenTypeOffsetTable>>
 		table;		/* Array of offsets to the OffsetTable for each font
 				 * from the beginning of the file */
   public:
@@ -295,7 +295,7 @@
   HBINT16	nameOffset;	/* Offset from beginning of resource name list
 				 * to resource name, -1 means there is none. */
   HBUINT8	attrs;		/* Resource attributes */
-  NNOffsetTo<LArrayOf<HBUINT8>, HBUINT24>
+  NNOffset24To<Array32Of<HBUINT8>>
 		offset;		/* Offset from beginning of data block to
 				 * data for this resource */
   HBUINT32	reserved;	/* Reserved for handle to resource */
@@ -330,7 +330,7 @@
   protected:
   Tag		tag;		/* Resource type. */
   HBUINT16	resCountM1;	/* Number of resources minus 1. */
-  NNOffsetTo<UnsizedArrayOf<ResourceRecord>>
+  NNOffset16To<UnsizedArrayOf<ResourceRecord>>
 		resourcesZ;	/* Offset from beginning of resource type list
 				 * to reference item list for this type. */
   public:
@@ -386,7 +386,7 @@
   HBUINT32	reserved1;	/* Reserved for handle to next resource map */
   HBUINT16	resreved2;	/* Reserved for file reference number */
   HBUINT16	attrs;		/* Resource fork attribute */
-  NNOffsetTo<ArrayOfM1<ResourceTypeRecord>>
+  NNOffset16To<ArrayOfM1<ResourceTypeRecord>>
 		typeList;	/* Offset from beginning of map to
 				 * resource type list */
   Offset16	nameList;	/* Offset from beginning of map to
@@ -418,10 +418,10 @@
   }
 
   protected:
-  LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
+  NNOffset32To<UnsizedArrayOf<HBUINT8>>
 		data;		/* Offset from beginning of resource fork
 				 * to resource data */
-  LNNOffsetTo<ResourceMap >
+  NNOffset32To<ResourceMap >
 		map;		/* Offset from beginning of resource fork
 				 * to resource map */
   HBUINT32	dataLen;	/* Length of resource data */

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -196,6 +196,12 @@
 
 typedef Index NameID;
 
+struct VarIdx : HBUINT32 {
+  static constexpr unsigned NO_VARIATION = 0xFFFFFFFFu;
+  VarIdx& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; }
+};
+DECLARE_NULL_NAMESPACE_BYTES (OT, VarIdx);
+
 /* Offset, Null offset = 0 */
 template <typename Type, bool has_null=true>
 struct Offset : Type
@@ -209,7 +215,9 @@
   void *serialize (hb_serialize_context_t *c, const void *base)
   {
     void *t = c->start_embed<void> ();
-    c->check_assign (*this, (unsigned) ((char *) t - (char *) base));
+    c->check_assign (*this,
+                     (unsigned) ((char *) t - (char *) base),
+                     HB_SERIALIZE_ERROR_OFFSET_OVERFLOW);
     return t;
   }
 
@@ -218,6 +226,7 @@
 };
 
 typedef Offset<HBUINT16> Offset16;
+typedef Offset<HBUINT24> Offset24;
 typedef Offset<HBUINT32> Offset32;
 
 
@@ -287,7 +296,7 @@
   static       Type *get_crap () { return &Crap (Type); }
 };
 
-template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
+template <typename Type, typename OffsetType, bool has_null=true>
 struct OffsetTo : Offset<OffsetType, has_null>
 {
   HB_DELETE_COPY_ASSIGN (OffsetTo);
@@ -378,7 +387,7 @@
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this))) return_trace (false);
     if (unlikely (this->is_null ())) return_trace (true);
-    if (unlikely (!c->check_range (base, *this))) return_trace (false);
+    if (unlikely ((const char *) base + (unsigned) *this < (const char *) base)) return_trace (false);
     return_trace (true);
   }
 
@@ -401,14 +410,16 @@
   DEFINE_SIZE_STATIC (sizeof (OffsetType));
 };
 /* Partial specializations. */
-template <typename Type, bool has_null=true>
-using LOffsetTo = OffsetTo<Type, HBUINT32, has_null>;
-template <typename Type, typename OffsetType=HBUINT16>
-using NNOffsetTo = OffsetTo<Type, OffsetType, false>;
-template <typename Type>
-using LNNOffsetTo = LOffsetTo<Type, false>;
+template <typename Type, bool has_null=true> using Offset16To = OffsetTo<Type, HBUINT16, has_null>;
+template <typename Type, bool has_null=true> using Offset24To = OffsetTo<Type, HBUINT24, has_null>;
+template <typename Type, bool has_null=true> using Offset32To = OffsetTo<Type, HBUINT32, has_null>;
 
+template <typename Type, typename OffsetType> using NNOffsetTo = OffsetTo<Type, OffsetType, false>;
+template <typename Type> using NNOffset16To = Offset16To<Type, false>;
+template <typename Type> using NNOffset24To = Offset24To<Type, false>;
+template <typename Type> using NNOffset32To = Offset32To<Type, false>;
 
+
 /*
  * Array Types
  */
@@ -513,11 +524,11 @@
 
 /* Unsized array of offset's */
 template <typename Type, typename OffsetType, bool has_null=true>
-using UnsizedOffsetArrayOf = UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null>>;
+using UnsizedArray16OfOffsetTo = UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null>>;
 
 /* Unsized array of offsets relative to the beginning of the array itself. */
 template <typename Type, typename OffsetType, bool has_null=true>
-struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
+struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, has_null>
 {
   const Type& operator [] (int i_) const
   {
@@ -538,7 +549,7 @@
   bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
-    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>
+    return_trace ((UnsizedArray16OfOffsetTo<Type, OffsetType, has_null>
 		   ::sanitize (c, count, this, hb_forward<Ts> (ds)...)));
   }
 };
@@ -569,7 +580,7 @@
 
 
 /* An array with a number of elements. */
-template <typename Type, typename LenType=HBUINT16>
+template <typename Type, typename LenType>
 struct ArrayOf
 {
   typedef Type item_t;
@@ -617,17 +628,30 @@
   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
   { return as_array ().sub_array (start_offset, count); }
 
-  hb_success_t serialize (hb_serialize_context_t *c, unsigned items_len)
+  template <typename T>
+  Type &lsearch (const T &x, Type &not_found = Crap (Type))
+  { return *as_array ().lsearch (x, &not_found); }
+  template <typename T>
+  const Type &lsearch (const T &x, const Type &not_found = Null (Type)) const
+  { return *as_array ().lsearch (x, &not_found); }
+  template <typename T>
+  bool lfind (const T &x, unsigned *pos = nullptr) const
+  { return as_array ().lfind (x, pos); }
+
+  void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
+  { as_array ().qsort (start, end); }
+
+  HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    c->check_assign (len, items_len);
+    c->check_assign (len, items_len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
     if (unlikely (!c->extend (*this))) return_trace (false);
     return_trace (true);
   }
   template <typename Iterator,
 	    hb_requires (hb_is_source_of (Iterator, Type))>
-  hb_success_t serialize (hb_serialize_context_t *c, Iterator items)
+  HB_NODISCARD bool serialize (hb_serialize_context_t *c, Iterator items)
   {
     TRACE_SERIALIZE (this);
     unsigned count = items.len ();
@@ -656,7 +680,7 @@
     TRACE_SERIALIZE (this);
     auto *out = c->start_embed (this);
     if (unlikely (!c->extend_min (out))) return_trace (nullptr);
-    c->check_assign (out->len, len);
+    c->check_assign (out->len, len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
     if (unlikely (!as_array ().copy (c))) return_trace (nullptr);
     return_trace (out);
   }
@@ -674,19 +698,6 @@
     return_trace (true);
   }
 
-  template <typename T>
-  Type &lsearch (const T &x, Type &not_found = Crap (Type))
-  { return *as_array ().lsearch (x, &not_found); }
-  template <typename T>
-  const Type &lsearch (const T &x, const Type &not_found = Null (Type)) const
-  { return *as_array ().lsearch (x, &not_found); }
-  template <typename T>
-  bool lfind (const T &x, unsigned *pos = nullptr) const
-  { return as_array ().lfind (x, pos); }
-
-  void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
-  { as_array ().qsort (start, end); }
-
   bool sanitize_shallow (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -699,21 +710,18 @@
   public:
   DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
 };
-template <typename Type>
-using LArrayOf = ArrayOf<Type, HBUINT32>;
+template <typename Type> using Array16Of = ArrayOf<Type, HBUINT16>;
+template <typename Type> using Array32Of = ArrayOf<Type, HBUINT32>;
 using PString = ArrayOf<HBUINT8, HBUINT8>;
 
 /* Array of Offset's */
-template <typename Type>
-using OffsetArrayOf = ArrayOf<OffsetTo<Type, HBUINT16>>;
-template <typename Type>
-using LOffsetArrayOf = ArrayOf<OffsetTo<Type, HBUINT32>>;
-template <typename Type>
-using LOffsetLArrayOf = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>;
+template <typename Type> using Array16OfOffset16To = ArrayOf<OffsetTo<Type, HBUINT16>, HBUINT16>;
+template <typename Type> using Array16OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT16>;
+template <typename Type> using Array32OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>;
 
 /* Array of offsets relative to the beginning of the array itself. */
 template <typename Type>
-struct OffsetListOf : OffsetArrayOf<Type>
+struct List16OfOffset16To : Array16OfOffset16To<Type>
 {
   const Type& operator [] (int i_) const
   {
@@ -731,7 +739,7 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    struct OffsetListOf<Type> *out = c->serializer->embed (*this);
+    struct List16OfOffset16To<Type> *out = c->serializer->embed (*this);
     if (unlikely (!out)) return_trace (false);
     unsigned int count = this->len;
     for (unsigned int i = 0; i < count; i++)
@@ -743,7 +751,7 @@
   bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
-    return_trace (OffsetArrayOf<Type>::sanitize (c, this, hb_forward<Ts> (ds)...));
+    return_trace (Array16OfOffset16To<Type>::sanitize (c, this, hb_forward<Ts> (ds)...));
   }
 };
 
@@ -787,7 +795,7 @@
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    c->check_assign (lenP1, items_len + 1);
+    c->check_assign (lenP1, items_len + 1, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
     if (unlikely (!c->extend (*this))) return_trace (false);
     return_trace (true);
   }
@@ -859,6 +867,7 @@
   {
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
     unsigned int count = lenM1 + 1;
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
@@ -882,7 +891,7 @@
 };
 
 /* An array with sorted elements.  Supports binary searching. */
-template <typename Type, typename LenType=HBUINT16>
+template <typename Type, typename LenType>
 struct SortedArrayOf : ArrayOf<Type, LenType>
 {
   hb_sorted_array_t<      Type> as_array ()       { return hb_sorted_array (this->arrayZ, this->len); }
@@ -933,6 +942,9 @@
   { return as_array ().bfind (x, i, not_found, to_store); }
 };
 
+template <typename Type> using SortedArray16Of = SortedArrayOf<Type, HBUINT16>;
+template <typename Type> using SortedArray32Of = SortedArrayOf<Type, HBUINT32>;
+
 /*
  * Binary-search arrays
  */

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -1390,7 +1390,7 @@
 
   public:
   FixedVersion<HBUINT8> version;	  /* Version of CFF table. set to 0x0100u */
-  OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
+  NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
   HBUINT8	       offSize;	  /* offset size (unused?) */
 
   public:

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -276,7 +276,9 @@
     HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount);
     if (unlikely (!c->check_success (idRangeOffset))) return;
 
-    if (unlikely (!c->check_assign(this->length, c->length () - table_initpos))) return;
+    if (unlikely (!c->check_assign(this->length,
+                                   c->length () - table_initpos,
+                                   HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
     this->segCountX2 = segcount * 2;
     this->entrySelector = hb_max (1u, hb_bit_storage (segcount)) - 1;
     this->searchRange = 2 * (1u << this->entrySelector);
@@ -670,7 +672,7 @@
   HBUINT16	reserved;	/* Reserved; set to 0. */
   HBUINT32	length;		/* Byte length of this subtable. */
   HBUINT32	language;	/* Ignore. */
-  SortedArrayOf<CmapSubtableLongGroup, HBUINT32>
+  SortedArray32Of<CmapSubtableLongGroup>
 		groups;		/* Groupings. */
   public:
   DEFINE_SIZE_ARRAY (16, groups);
@@ -784,7 +786,7 @@
   DEFINE_SIZE_STATIC (4);
 };
 
-struct DefaultUVS : SortedArrayOf<UnicodeValueRange, HBUINT32>
+struct DefaultUVS : SortedArray32Of<UnicodeValueRange>
 {
   void collect_unicodes (hb_set_t *out) const
   {
@@ -850,7 +852,9 @@
     }
     else
     {
-      if (unlikely (!c->check_assign (out->len, (c->length () - init_len) / UnicodeValueRange::static_size))) return nullptr;
+      if (unlikely (!c->check_assign (out->len,
+                                      (c->length () - init_len) / UnicodeValueRange::static_size,
+                                      HB_SERIALIZE_ERROR_INT_OVERFLOW))) return nullptr;
       return out;
     }
   }
@@ -876,23 +880,21 @@
   DEFINE_SIZE_STATIC (5);
 };
 
-struct NonDefaultUVS : SortedArrayOf<UVSMapping, HBUINT32>
+struct NonDefaultUVS : SortedArray32Of<UVSMapping>
 {
   void collect_unicodes (hb_set_t *out) const
   {
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      out->add (arrayZ[i].unicodeValue);
+    for (const auto& a : as_array ())
+      out->add (a.unicodeValue);
   }
 
   void collect_mapping (hb_set_t *unicodes, /* OUT */
 			hb_map_t *mapping /* OUT */) const
   {
-    unsigned count = len;
-    for (unsigned i = 0; i < count; i++)
+    for (const auto& a : as_array ())
     {
-      hb_codepoint_t unicode = arrayZ[i].unicodeValue;
-      hb_codepoint_t glyphid = arrayZ[i].glyphID;
+      hb_codepoint_t unicode = a.unicodeValue;
+      hb_codepoint_t glyphid = a.glyphID;
       unicodes->add (unicode);
       mapping->set (unicode, glyphid);
     }
@@ -1041,9 +1043,9 @@
   }
 
   HBUINT24	varSelector;	/* Variation selector. */
-  LOffsetTo<DefaultUVS>
+  Offset32To<DefaultUVS>
 		defaultUVS;	/* Offset to Default UVS Table.  May be 0. */
-  LOffsetTo<NonDefaultUVS>
+  Offset32To<NonDefaultUVS>
 		nonDefaultUVS;	/* Offset to Non-Default UVS Table.  May be 0. */
   public:
   DEFINE_SIZE_STATIC (11);
@@ -1058,9 +1060,8 @@
 
   void collect_variation_selectors (hb_set_t *out) const
   {
-    unsigned int count = record.len;
-    for (unsigned int i = 0; i < count; i++)
-      out->add (record.arrayZ[i].varSelector);
+    for (const auto& a : record.as_array ())
+      out->add (a.varSelector);
   }
   void collect_variation_unicodes (hb_codepoint_t variation_selector,
 				   hb_set_t *out) const
@@ -1112,10 +1113,12 @@
       return;
 
     int tail_len = init_tail - c->tail;
-    c->check_assign (this->length, c->length () - table_initpos + tail_len);
+    c->check_assign (this->length, c->length () - table_initpos + tail_len,
+                     HB_SERIALIZE_ERROR_INT_OVERFLOW);
     c->check_assign (this->record.len,
 		     (c->length () - table_initpos - CmapSubtableFormat14::min_size) /
-		     VariationSelectorRecord::static_size);
+		     VariationSelectorRecord::static_size,
+                     HB_SERIALIZE_ERROR_INT_OVERFLOW);
 
     /* Correct the incorrect write order by reversing the order of the variation
        records array. */
@@ -1180,7 +1183,7 @@
   protected:
   HBUINT16	format;		/* Format number is set to 14. */
   HBUINT32	length;		/* Byte length of this subtable. */
-  SortedArrayOf<VariationSelectorRecord, HBUINT32>
+  SortedArray32Of<VariationSelectorRecord>
 		record;		/* Variation selector records; sorted
 				 * in increasing order of `varSelector'. */
   public:
@@ -1338,7 +1341,7 @@
 
   HBUINT16	platformID;	/* Platform ID. */
   HBUINT16	encodingID;	/* Platform-specific encoding ID. */
-  LOffsetTo<CmapSubtable>
+  Offset32To<CmapSubtable>
 		subtable;	/* Byte offset from beginning of table to the subtable for this encoding. */
   public:
   DEFINE_SIZE_STATIC (8);
@@ -1401,7 +1404,9 @@
       }
     }
 
-    c->check_assign(this->encodingRecord.len, (c->length () - cmap::min_size)/EncodingRecord::static_size);
+    c->check_assign(this->encodingRecord.len,
+                    (c->length () - cmap::min_size)/EncodingRecord::static_size,
+                    HB_SERIALIZE_ERROR_INT_OVERFLOW);
   }
 
   void closure_glyphs (const hb_set_t      *unicodes,
@@ -1697,7 +1702,7 @@
 
   protected:
   HBUINT16	version;	/* Table version number (0). */
-  SortedArrayOf<EncodingRecord>
+  SortedArray16Of<EncodingRecord>
 		encodingRecord;	/* Encoding tables. */
   public:
   DEFINE_SIZE_ARRAY (4, encodingRecord);

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -510,7 +510,7 @@
 
   HBGlyphID			firstGlyphIndex;
   HBGlyphID			lastGlyphIndex;
-  LOffsetTo<IndexSubtable>	offsetToSubtable;
+  Offset32To<IndexSubtable>	offsetToSubtable;
   public:
   DEFINE_SIZE_STATIC (8);
 };
@@ -672,7 +672,7 @@
   }
 
   protected:
-  LNNOffsetTo<IndexSubtableArray>
+  NNOffset32To<IndexSubtableArray>
 			indexSubtableArrayOffset;
   HBUINT32		indexTablesSize;
   HBUINT32		numberOfIndexSubtables;
@@ -697,7 +697,7 @@
 struct GlyphBitmapDataFormat17
 {
   SmallGlyphMetrics	glyphMetrics;
-  LArrayOf<HBUINT8>	data;
+  Array32Of<HBUINT8>	data;
   public:
   DEFINE_SIZE_ARRAY (9, data);
 };
@@ -705,7 +705,7 @@
 struct GlyphBitmapDataFormat18
 {
   BigGlyphMetrics	glyphMetrics;
-  LArrayOf<HBUINT8>	data;
+  Array32Of<HBUINT8>	data;
   public:
   DEFINE_SIZE_ARRAY (12, data);
 };
@@ -712,7 +712,7 @@
 
 struct GlyphBitmapDataFormat19
 {
-  LArrayOf<HBUINT8>	data;
+  Array32Of<HBUINT8>	data;
   public:
   DEFINE_SIZE_ARRAY (4, data);
 };
@@ -798,7 +798,7 @@
 
   protected:
   FixedVersion<>		version;
-  LArrayOf<BitmapSizeTable>	sizeTables;
+  Array32Of<BitmapSizeTable>	sizeTables;
   public:
   DEFINE_SIZE_ARRAY (8, sizeTables);
 };

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -29,6 +29,7 @@
 #define HB_OT_COLOR_COLR_TABLE_HH
 
 #include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
 
 /*
  * COLR -- Color
@@ -39,7 +40,6 @@
 
 namespace OT {
 
-
 struct LayerRecord
 {
   operator hb_ot_color_layer_t () const { return {glyphId, colorIdx}; }
@@ -90,6 +90,467 @@
   DEFINE_SIZE_STATIC (6);
 };
 
+template <typename T>
+struct Variable
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  T      value;
+  VarIdx varIdx;
+  public:
+  DEFINE_SIZE_STATIC (4 + T::static_size);
+};
+
+template <typename T>
+struct NoVariable
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  T      value;
+  public:
+  DEFINE_SIZE_STATIC (T::static_size);
+};
+
+// Color structures
+
+template <template<typename> class Var>
+struct ColorIndex
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT16	paletteIndex;
+  Var<F2DOT14>	alpha;
+  public:
+  DEFINE_SIZE_STATIC (2 + Var<F2DOT14>::static_size);
+};
+
+template <template<typename> class Var>
+struct ColorStop
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  Var<F2DOT14>		stopOffset;
+  ColorIndex<Var>		color;
+  public:
+  DEFINE_SIZE_STATIC (Var<F2DOT14>::static_size + ColorIndex<Var>::static_size);
+};
+
+struct Extend : HBUINT8
+{
+  enum {
+    EXTEND_PAD     = 0,
+    EXTEND_REPEAT  = 1,
+    EXTEND_REFLECT = 2,
+  };
+  public:
+  DEFINE_SIZE_STATIC (1);
+};
+
+template <template<typename> class Var>
+struct ColorLine
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  stops.sanitize (c));
+  }
+
+  Extend			extend;
+  Array16Of<ColorStop<Var>>	stops;
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (3, stops);
+};
+
+// Composition modes
+
+// Compositing modes are taken from https://www.w3.org/TR/compositing-1/
+// NOTE: a brief audit of major implementations suggests most support most
+// or all of the specified modes.
+struct CompositeMode : HBUINT8
+{
+  enum {
+    // Porter-Duff modes
+    // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators
+    COMPOSITE_CLEAR          =  0,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_clear
+    COMPOSITE_SRC            =  1,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_src
+    COMPOSITE_DEST           =  2,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dst
+    COMPOSITE_SRC_OVER       =  3,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcover
+    COMPOSITE_DEST_OVER      =  4,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstover
+    COMPOSITE_SRC_IN         =  5,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcin
+    COMPOSITE_DEST_IN        =  6,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstin
+    COMPOSITE_SRC_OUT        =  7,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcout
+    COMPOSITE_DEST_OUT       =  8,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstout
+    COMPOSITE_SRC_ATOP       =  9,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcatop
+    COMPOSITE_DEST_ATOP      = 10,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstatop
+    COMPOSITE_XOR            = 11,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_xor
+    COMPOSITE_PLUS           = 12,  // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_plus
+  
+    // Blend modes
+    // https://www.w3.org/TR/compositing-1/#blending
+    COMPOSITE_SCREEN         = 13,  // https://www.w3.org/TR/compositing-1/#blendingscreen
+    COMPOSITE_OVERLAY        = 14,  // https://www.w3.org/TR/compositing-1/#blendingoverlay
+    COMPOSITE_DARKEN         = 15,  // https://www.w3.org/TR/compositing-1/#blendingdarken
+    COMPOSITE_LIGHTEN        = 16,  // https://www.w3.org/TR/compositing-1/#blendinglighten
+    COMPOSITE_COLOR_DODGE    = 17,  // https://www.w3.org/TR/compositing-1/#blendingcolordodge
+    COMPOSITE_COLOR_BURN     = 18,  // https://www.w3.org/TR/compositing-1/#blendingcolorburn
+    COMPOSITE_HARD_LIGHT     = 19,  // https://www.w3.org/TR/compositing-1/#blendinghardlight
+    COMPOSITE_SOFT_LIGHT     = 20,  // https://www.w3.org/TR/compositing-1/#blendingsoftlight
+    COMPOSITE_DIFFERENCE     = 21,  // https://www.w3.org/TR/compositing-1/#blendingdifference
+    COMPOSITE_EXCLUSION      = 22,  // https://www.w3.org/TR/compositing-1/#blendingexclusion
+    COMPOSITE_MULTIPLY       = 23,  // https://www.w3.org/TR/compositing-1/#blendingmultiply
+  
+    // Modes that, uniquely, do not operate on components
+    // https://www.w3.org/TR/compositing-1/#blendingnonseparable
+    COMPOSITE_HSL_HUE        = 24,  // https://www.w3.org/TR/compositing-1/#blendinghue
+    COMPOSITE_HSL_SATURATION = 25,  // https://www.w3.org/TR/compositing-1/#blendingsaturation
+    COMPOSITE_HSL_COLOR      = 26,  // https://www.w3.org/TR/compositing-1/#blendingcolor
+    COMPOSITE_HSL_LUMINOSITY = 27,  // https://www.w3.org/TR/compositing-1/#blendingluminosity
+  };
+  public:
+  DEFINE_SIZE_STATIC (1);
+};
+
+template <template<typename> class Var>
+struct Affine2x3
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  Var<HBFixed> xx;
+  Var<HBFixed> yx;
+  Var<HBFixed> xy;
+  Var<HBFixed> yy;
+  Var<HBFixed> dx;
+  Var<HBFixed> dy;
+  public:
+  DEFINE_SIZE_STATIC (6 * Var<HBFixed>::static_size);
+};
+
+struct PaintColrLayers
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT8	format; /* format = 1 */
+  HBUINT8	numLayers;
+  HBUINT32	firstLayerIndex;  /* index into COLRv1::layersV1 */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+template <template<typename> class Var>
+struct PaintSolid
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT8		format; /* format = 2(noVar) or 3(Var)*/
+  ColorIndex<Var>	color;
+  public:
+  DEFINE_SIZE_STATIC (1 + ColorIndex<Var>::static_size);
+};
+
+template <template<typename> class Var>
+struct PaintLinearGradient
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
+  }
+
+  HBUINT8			format; /* format = 4(noVar) or 5 (Var) */
+  Offset24To<ColorLine<Var>>	colorLine; /* Offset (from beginning of PaintLinearGradient
+                                            * table) to ColorLine subtable. */
+  Var<FWORD>			x0;
+  Var<FWORD>			y0;
+  Var<FWORD>			x1;
+  Var<FWORD>			y1;
+  Var<FWORD>			x2;
+  Var<FWORD>			y2;
+  public:
+  DEFINE_SIZE_STATIC (4 + 6 * Var<FWORD>::static_size);
+};
+
+template <template<typename> class Var>
+struct PaintRadialGradient
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
+  }
+
+  HBUINT8			format; /* format = 6(noVar) or 7 (Var) */
+  Offset24To<ColorLine<Var>>	colorLine; /* Offset (from beginning of PaintRadialGradient
+                                            * table) to ColorLine subtable. */
+  Var<FWORD>			x0;
+  Var<FWORD>			y0;
+  Var<UFWORD>			radius0;
+  Var<FWORD>			x1;
+  Var<FWORD>			y1;
+  Var<UFWORD>			radius1;
+  public:
+  DEFINE_SIZE_STATIC (4 + 6 * Var<FWORD>::static_size);
+};
+
+template <template<typename> class Var>
+struct PaintSweepGradient
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
+  }
+
+  HBUINT8			format; /* format = 8(noVar) or 9 (Var) */
+  Offset24To<ColorLine<Var>>	colorLine; /* Offset (from beginning of PaintSweepGradient
+                                            * table) to ColorLine subtable. */
+  Var<FWORD>			centerX;
+  Var<FWORD>			centerY;
+  Var<HBFixed>			startAngle;
+  Var<HBFixed>			endAngle;
+  public:
+  DEFINE_SIZE_STATIC (2 * Var<FWORD>::static_size + 2 * Var<HBFixed>::static_size);
+};
+
+struct Paint;
+// Paint a non-COLR glyph, filled as indicated by paint.
+struct PaintGlyph
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && paint.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 10 */
+  Offset24To<Paint>	paint;  /* Offset (from beginning of PaintGlyph table) to Paint subtable. */
+  HBUINT16		gid;
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct PaintColrGlyph
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT8	format; /* format = 11 */
+  HBUINT16	gid;
+  public:
+  DEFINE_SIZE_STATIC (3);
+};
+
+template <template<typename> class Var>
+struct PaintTransform
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && src.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 12(noVar) or 13 (Var) */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */
+  Affine2x3<Var>	transform;
+  public:
+  DEFINE_SIZE_STATIC (4 + Affine2x3<Var>::static_size);
+};
+
+template <template<typename> class Var>
+struct PaintTranslate
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && src.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 14(noVar) or 15 (Var) */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintTranslate table) to Paint subtable. */
+  Var<HBFixed>		dx;
+  Var<HBFixed>		dy;
+  public:
+  DEFINE_SIZE_STATIC (4 + Var<HBFixed>::static_size);
+};
+
+template <template<typename> class Var>
+struct PaintRotate
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && src.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 16 (noVar) or 17(Var) */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintRotate table) to Paint subtable. */
+  Var<HBFixed>		angle;
+  Var<HBFixed>		centerX;
+  Var<HBFixed>		centerY;
+  public:
+  DEFINE_SIZE_STATIC (4 + 3 * Var<HBFixed>::static_size);
+};
+
+template <template<typename> class Var>
+struct PaintSkew
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && src.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 18(noVar) or 19 (Var) */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintSkew table) to Paint subtable. */
+  Var<HBFixed>		xSkewAngle;
+  Var<HBFixed>		ySkewAngle;
+  Var<HBFixed>		centerX;
+  Var<HBFixed>		centerY;
+  public:
+  DEFINE_SIZE_STATIC (4 + 4 * Var<HBFixed>::static_size);
+};
+
+struct PaintComposite
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  src.sanitize (c, this) &&
+                  backdrop.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 20 */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintComposite table) to source Paint subtable. */
+  CompositeMode		mode;   /* If mode is unrecognized use COMPOSITE_CLEAR */
+  Offset24To<Paint>	backdrop; /* Offset (from beginning of PaintComposite table) to backdrop Paint subtable. */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct Paint
+{
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+  {
+    TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+    switch (u.format) {
+    case 1: return_trace (c->dispatch (u.paintformat1, hb_forward<Ts> (ds)...));
+    case 2: return_trace (c->dispatch (u.paintformat2, hb_forward<Ts> (ds)...));
+    case 3: return_trace (c->dispatch (u.paintformat3, hb_forward<Ts> (ds)...));
+    case 4: return_trace (c->dispatch (u.paintformat4, hb_forward<Ts> (ds)...));
+    case 5: return_trace (c->dispatch (u.paintformat5, hb_forward<Ts> (ds)...));
+    case 6: return_trace (c->dispatch (u.paintformat6, hb_forward<Ts> (ds)...));
+    case 7: return_trace (c->dispatch (u.paintformat7, hb_forward<Ts> (ds)...));
+    case 8: return_trace (c->dispatch (u.paintformat8, hb_forward<Ts> (ds)...));
+    case 9: return_trace (c->dispatch (u.paintformat9, hb_forward<Ts> (ds)...));
+    case 10: return_trace (c->dispatch (u.paintformat10, hb_forward<Ts> (ds)...));
+    case 11: return_trace (c->dispatch (u.paintformat11, hb_forward<Ts> (ds)...));
+    case 12: return_trace (c->dispatch (u.paintformat12, hb_forward<Ts> (ds)...));
+    case 13: return_trace (c->dispatch (u.paintformat13, hb_forward<Ts> (ds)...));
+    case 14: return_trace (c->dispatch (u.paintformat14, hb_forward<Ts> (ds)...));
+    case 15: return_trace (c->dispatch (u.paintformat15, hb_forward<Ts> (ds)...));
+    case 16: return_trace (c->dispatch (u.paintformat16, hb_forward<Ts> (ds)...));
+    case 17: return_trace (c->dispatch (u.paintformat17, hb_forward<Ts> (ds)...));
+    case 18: return_trace (c->dispatch (u.paintformat18, hb_forward<Ts> (ds)...));
+    case 19: return_trace (c->dispatch (u.paintformat19, hb_forward<Ts> (ds)...));
+    case 20: return_trace (c->dispatch (u.paintformat20, hb_forward<Ts> (ds)...));
+    default:return_trace (c->default_return_value ());
+    }
+  }
+
+  protected:
+  union {
+  HBUINT8				format;
+  PaintColrLayers			paintformat1;
+  PaintSolid<NoVariable>		paintformat2;
+  PaintSolid<Variable>			paintformat3;
+  PaintLinearGradient<NoVariable>	paintformat4;
+  PaintLinearGradient<Variable>		paintformat5;
+  PaintRadialGradient<NoVariable>	paintformat6;
+  PaintRadialGradient<Variable>		paintformat7;
+  PaintSweepGradient<NoVariable>	paintformat8;
+  PaintSweepGradient<Variable>		paintformat9;
+  PaintGlyph				paintformat10;
+  PaintColrGlyph			paintformat11;
+  PaintTransform<NoVariable>		paintformat12;
+  PaintTransform<Variable>		paintformat13;
+  PaintTranslate<NoVariable>		paintformat14;
+  PaintTranslate<Variable>		paintformat15;
+  PaintRotate<NoVariable>		paintformat16;
+  PaintRotate<Variable>			paintformat17;
+  PaintSkew<NoVariable>			paintformat18;
+  PaintSkew<Variable>			paintformat19;
+  PaintComposite			paintformat20;
+  } u;
+};
+
+struct BaseGlyphV1Record
+{
+  int cmp (hb_codepoint_t g) const
+  { return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) && paint.sanitize (c, this)));
+  }
+
+  public:
+  HBGlyphID		glyphId;    /* Glyph ID of reference glyph */
+  Offset32To<Paint>	paint;      /* Offset (from beginning of BaseGlyphV1Record) to Paint,
+                                     * Typically PaintColrLayers */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+typedef SortedArray32Of<BaseGlyphV1Record> BaseGlyphV1List;
+
+struct LayerV1List : Array32OfOffset32To<Paint>
+{
+  const Paint& get_paint (unsigned i) const
+  { return this+(*this)[i]; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (Array32OfOffset32To<Paint>::sanitize (c, this));
+  }
+};
+
 struct COLR
 {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
@@ -150,9 +611,13 @@
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-			  (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
-			  (this+layersZ).sanitize (c, numLayers)));
+    return_trace (c->check_struct (this) &&
+                  (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
+                  (this+layersZ).sanitize (c, numLayers) &&
+                  (version == 0 || (version == 1 &&
+                                    baseGlyphsV1List.sanitize (c, this) &&
+                                    layersV1.sanitize (c, this) &&
+                                    varStore.sanitize (c, this))));
   }
 
   template<typename BaseIterator, typename LayerIterator,
@@ -263,13 +728,17 @@
   protected:
   HBUINT16	version;	/* Table version number (starts at 0). */
   HBUINT16	numBaseGlyphs;	/* Number of Base Glyph Records. */
-  LNNOffsetTo<SortedUnsizedArrayOf<BaseGlyphRecord>>
+  NNOffset32To<SortedUnsizedArrayOf<BaseGlyphRecord>>
 		baseGlyphsZ;	/* Offset to Base Glyph records. */
-  LNNOffsetTo<UnsizedArrayOf<LayerRecord>>
+  NNOffset32To<UnsizedArrayOf<LayerRecord>>
 		layersZ;	/* Offset to Layer Records. */
   HBUINT16	numLayers;	/* Number of Layer Records. */
+  // Version-1 additions
+  Offset32To<BaseGlyphV1List>		baseGlyphsV1List;
+  Offset32To<LayerV1List>		layersV1;
+  Offset32To<VariationStore>		varStore;
   public:
-  DEFINE_SIZE_STATIC (14);
+  DEFINE_SIZE_MIN (14);
 };
 
 } /* namespace OT */

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -87,15 +87,15 @@
   }
 
   protected:
-  LNNOffsetTo<UnsizedArrayOf<HBUINT32>>
+  NNOffset32To<UnsizedArrayOf<HBUINT32>>
 		paletteFlagsZ;		/* Offset from the beginning of CPAL table to
 					 * the Palette Type Array. Set to 0 if no array
 					 * is provided. */
-  LNNOffsetTo<UnsizedArrayOf<NameID>>
+  NNOffset32To<UnsizedArrayOf<NameID>>
 		paletteLabelsZ;		/* Offset from the beginning of CPAL table to
 					 * the palette labels array. Set to 0 if no
 					 * array is provided. */
-  LNNOffsetTo<UnsizedArrayOf<NameID>>
+  NNOffset32To<UnsizedArrayOf<NameID>>
 		colorLabelsZ;		/* Offset from the beginning of CPAL table to
 					 * the color labels array. Set to 0
 					 * if no array is provided. */
@@ -173,7 +173,7 @@
   HBUINT16	numPalettes;		/* Number of palettes in the table. */
   HBUINT16	numColorRecords;	/* Total number of color records, combined for
 					 * all palettes. */
-  LNNOffsetTo<UnsizedArrayOf<BGRAColor>>
+  NNOffset32To<UnsizedArrayOf<BGRAColor>>
 		colorRecordsZ;		/* Offset from the beginning of CPAL table to
 					 * the first ColorRecord. */
   UnsizedArrayOf<HBUINT16>

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-sbix-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -185,7 +185,7 @@
   HBUINT16	resolution;	/* The device pixel density (in PPI) for which this
 				 * strike was designed. (E.g., 96 PPI, 192 PPI.) */
   protected:
-  UnsizedArrayOf<LOffsetTo<SBIXGlyph>>
+  UnsizedArrayOf<Offset32To<SBIXGlyph>>
 		imageOffsetsZ;	/* Offset from the beginning of the strike data header
 				 * to bitmap data for an individual glyph ID. */
   public:
@@ -352,11 +352,11 @@
   {
     TRACE_SERIALIZE (this);
 
-    auto *out = c->serializer->start_embed<LOffsetLArrayOf<SBIXStrike>> ();
+    auto *out = c->serializer->start_embed<Array32OfOffset32To<SBIXStrike>> ();
     if (unlikely (!out)) return_trace (false);
     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
 
-    hb_vector_t<LOffsetTo<SBIXStrike>*> new_strikes;
+    hb_vector_t<Offset32To<SBIXStrike>*> new_strikes;
     hb_vector_t<hb_serialize_context_t::objidx_t> objidxs;
     for (int i = strikes.len - 1; i >= 0; --i)
     {
@@ -400,7 +400,7 @@
   HBUINT16	version;	/* Table version number — set to 1 */
   HBUINT16	flags;		/* Bit 0: Set to 1. Bit 1: Draw outlines.
 				 * Bits 2 to 15: reserved (set to 0). */
-  LOffsetLArrayOf<SBIXStrike>
+  Array32OfOffset32To<SBIXStrike>
 		strikes;	/* Offsets from the beginning of the 'sbix'
 				 * table to data for each individual bitmap strike. */
   public:

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -62,7 +62,7 @@
 				 * this index entry. */
   HBUINT16	endGlyphID;	/* The last glyph ID in the range described by
 				 * this index entry. Must be >= startGlyphID. */
-  LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
+  NNOffset32To<UnsizedArrayOf<HBUINT8>>
 		svgDoc;		/* Offset from the beginning of the SVG Document Index
 				 * to an SVG document. Must be non-zero. */
   HBUINT32	svgDocLength;	/* Length of the SVG document.
@@ -107,7 +107,7 @@
 
   protected:
   HBUINT16	version;	/* Table version (starting at 0). */
-  LOffsetTo<SortedArrayOf<SVGDocumentIndexEntry>>
+  Offset32To<SortedArray16Of<SVGDocumentIndexEntry>>
 		svgDocEntries;	/* Offset (relative to the start of the SVG table) to the
 				 * SVG Documents Index. Must be non-zero. */
 				/* Array of SVG Document Index Entries. */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-gasp-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-gasp-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-gasp-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -71,7 +71,7 @@
 
   protected:
   HBUINT16	version;	/* Version number (set to 1) */
-  ArrayOf<GaspRange>
+  Array16Of<GaspRange>
 		gaspRanges;	/* Number of records to follow
 				 * Sorted by ppem */
   public:

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -110,7 +110,7 @@
     for (const hb_item_type<Iterator>& _ : +it)
       c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second);
 
-    return_trace (c->successful);
+    return_trace (c->successful ());
   }
 
 

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -146,7 +146,7 @@
 
     _mtx.fini ();
 
-    if (unlikely (c->serializer->ran_out_of_room || c->serializer->in_error ()))
+    if (unlikely (c->serializer->in_error ()))
       return_trace (false);
 
     // Amend header num hmetrics

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -103,7 +103,7 @@
   protected:
   HBUINT16	format;		/* Format identifier--format = 3 */
   FWORD		coordinate;	/* X or Y value, in design units */
-  OffsetTo<Device>
+  Offset16To<Device>
 		deviceTable;	/* Offset to Device table for X or
 				 * Y value, from beginning of
 				 * BaseCoord table (may be NULL). */
@@ -173,11 +173,11 @@
   protected:
   Tag		tag;		/* 4-byte feature identification tag--must
 				 * match feature tag in FeatureList */
-  OffsetTo<BaseCoord>
+  Offset16To<BaseCoord>
 		minCoord;	/* Offset to BaseCoord table that defines
 				 * the minimum extent value, from beginning
 				 * of MinMax table (may be NULL) */
-  OffsetTo<BaseCoord>
+  Offset16To<BaseCoord>
 		maxCoord;	/* Offset to BaseCoord table that defines
 				 * the maximum extent value, from beginning
 				 * of MinMax table (may be NULL) */
@@ -212,15 +212,15 @@
   }
 
   protected:
-  OffsetTo<BaseCoord>
+  Offset16To<BaseCoord>
 		minCoord;	/* Offset to BaseCoord table that defines
 				 * minimum extent value, from the beginning
 				 * of MinMax table (may be NULL) */
-  OffsetTo<BaseCoord>
+  Offset16To<BaseCoord>
 		maxCoord;	/* Offset to BaseCoord table that defines
 				 * maximum extent value, from the beginning
 				 * of MinMax table (may be NULL) */
-  SortedArrayOf<FeatMinMaxRecord>
+  SortedArray16Of<FeatMinMaxRecord>
 		featMinMaxRecords;
 				/* Array of FeatMinMaxRecords, in alphabetical
 				 * order by featureTableTag */
@@ -247,7 +247,7 @@
   Index		defaultIndex;	/* Index number of default baseline for this
 				 * script — equals index position of baseline tag
 				 * in baselineTags array of the BaseTagList */
-  OffsetArrayOf<BaseCoord>
+  Array16OfOffset16To<BaseCoord>
 		baseCoords;	/* Number of BaseCoord tables defined — should equal
 				 * baseTagCount in the BaseTagList
 				 *
@@ -275,7 +275,7 @@
 
   protected:
   Tag		baseLangSysTag;	/* 4-byte language system identification tag */
-  OffsetTo<MinMax>
+  Offset16To<MinMax>
 		minMax;		/* Offset to MinMax table, from beginning
 				 * of BaseScript table */
   public:
@@ -305,13 +305,13 @@
   }
 
   protected:
-  OffsetTo<BaseValues>
+  Offset16To<BaseValues>
 		baseValues;	/* Offset to BaseValues table, from beginning
 				 * of BaseScript table (may be NULL) */
-  OffsetTo<MinMax>
+  Offset16To<MinMax>
 		defaultMinMax;	/* Offset to MinMax table, from beginning of
 				 * BaseScript table (may be NULL) */
-  SortedArrayOf<BaseLangSysRecord>
+  SortedArray16Of<BaseLangSysRecord>
 		baseLangSysRecords;
 				/* Number of BaseLangSysRecords
 				 * defined — may be zero (0) */
@@ -339,7 +339,7 @@
 
   protected:
   Tag		baseScriptTag;	/* 4-byte script identification tag */
-  OffsetTo<BaseScript>
+  Offset16To<BaseScript>
 		baseScript;	/* Offset to BaseScript table, from beginning
 				 * of BaseScriptList */
 
@@ -364,7 +364,7 @@
   }
 
   protected:
-  SortedArrayOf<BaseScriptRecord>
+  SortedArray16Of<BaseScriptRecord>
 			baseScriptRecords;
 
   public:
@@ -426,12 +426,12 @@
   }
 
   protected:
-  OffsetTo<SortedArrayOf<Tag>>
+  Offset16To<SortedArray16Of<Tag>>
 		baseTagList;	/* Offset to BaseTagList table, from beginning
 				 * of Axis table (may be NULL)
 				 * Array of 4-byte baseline identification tags — must
 				 * be in alphabetical order */
-  OffsetTo<BaseScriptList>
+  Offset16To<BaseScriptList>
 		baseScriptList;	/* Offset to BaseScriptList table, from beginning
 				 * of Axis table
 				 * Array of BaseScriptRecords, in alphabetical order
@@ -501,11 +501,11 @@
 
   protected:
   FixedVersion<>version;	/* Version of the BASE table */
-  OffsetTo<Axis>hAxis;		/* Offset to horizontal Axis table, from beginning
+  Offset16To<Axis>hAxis;		/* Offset to horizontal Axis table, from beginning
 				 * of BASE table (may be NULL) */
-  OffsetTo<Axis>vAxis;		/* Offset to vertical Axis table, from beginning
+  Offset16To<Axis>vAxis;		/* Offset to vertical Axis table, from beginning
 				 * of BASE table (may be NULL) */
-  LOffsetTo<VariationStore>
+  Offset32To<VariationStore>
 		varStore;	/* Offset to the table of Item Variation
 				 * Store--from beginning of BASE
 				 * header (may be NULL).  Introduced

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -88,12 +88,66 @@
 				       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,
 					  const hb_set_t &klasses,
+					  bool use_class_zero,
 					  hb_map_t *klass_map /*INOUT*/);
 
+
+struct hb_prune_langsys_context_t
+{
+  hb_prune_langsys_context_t (const void         *table_,
+                              hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map_,
+                              const hb_map_t     *duplicate_feature_map_,
+                              hb_set_t           *new_collected_feature_indexes_)
+      :table (table_),
+      script_langsys_map (script_langsys_map_),
+      duplicate_feature_map (duplicate_feature_map_),
+      new_feature_indexes (new_collected_feature_indexes_),
+      script_count (0),langsys_count (0) {}
+
+  bool visitedScript (const void *s)
+  {
+    if (script_count++ > HB_MAX_SCRIPTS)
+      return true;
+
+    return visited (s, visited_script);
+  }
+
+  bool visitedLangsys (const void *l)
+  {
+    if (langsys_count++ > HB_MAX_LANGSYS)
+      return true;
+
+    return visited (l, visited_langsys);
+  }
+
+  private:
+  template <typename T>
+  bool visited (const T *p, hb_set_t &visited_set)
+  {
+    hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) p - (uintptr_t) table);
+     if (visited_set.has (delta))
+      return true;
+
+    visited_set.add (delta);
+    return false;
+  }
+
+  public:
+  const void *table;
+  hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map;
+  const hb_map_t     *duplicate_feature_map;
+  hb_set_t           *new_feature_indexes;
+
+  private:
+  hb_set_t visited_script;
+  hb_set_t visited_langsys;
+  unsigned script_count;
+  unsigned langsys_count;
+};
+
 struct hb_subset_layout_context_t :
   hb_dispatch_context_t<hb_subset_layout_context_t, hb_empty_t, HB_DEBUG_SUBSET>
 {
@@ -125,16 +179,21 @@
   hb_subset_context_t *subset_context;
   const hb_tag_t table_tag;
   const hb_map_t *lookup_index_map;
+  const hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map;
   const hb_map_t *feature_index_map;
+  unsigned cur_script_index;
 
   hb_subset_layout_context_t (hb_subset_context_t *c_,
 			      hb_tag_t tag_,
 			      hb_map_t *lookup_map_,
-			      hb_map_t *feature_map_) :
+			      hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map_,
+			      hb_map_t *feature_index_map_) :
 				subset_context (c_),
 				table_tag (tag_),
 				lookup_index_map (lookup_map_),
-				feature_index_map (feature_map_),
+				script_langsys_map (script_langsys_map_),
+				feature_index_map (feature_index_map_),
+				cur_script_index (0xFFFFu),
 				script_count (0),
 				langsys_count (0),
 				feature_index_count (0),
@@ -325,7 +384,7 @@
   }
 
   Tag		tag;		/* 4-byte Tag identifier */
-  OffsetTo<Type>
+  Offset16To<Type>
 		offset;		/* Offset from beginning of object holding
 				 * the Record */
   public:
@@ -333,11 +392,11 @@
 };
 
 template <typename Type>
-struct RecordArrayOf : SortedArrayOf<Record<Type>>
+struct RecordArrayOf : SortedArray16Of<Record<Type>>
 {
-  const OffsetTo<Type>& get_offset (unsigned int i) const
+  const Offset16To<Type>& get_offset (unsigned int i) const
   { return (*this)[i].offset; }
-  OffsetTo<Type>& get_offset (unsigned int i)
+  Offset16To<Type>& get_offset (unsigned int i)
   { return (*this)[i].offset; }
   const Tag& get_tag (unsigned int i) const
   { return (*this)[i].tag; }
@@ -407,6 +466,30 @@
   }
 };
 
+struct Script;
+struct RecordListOfScript : RecordListOf<Script>
+{
+  bool subset (hb_subset_context_t *c,
+               hb_subset_layout_context_t *l) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+    unsigned count = this->len;
+    for (auto _ : + hb_zip (*this, hb_range (count)))
+    {
+      auto snap = c->serializer->snapshot ();
+      l->cur_script_index = _.second;
+      bool ret = _.first.subset (l, this);
+      if (!ret) c->serializer->revert (snap);
+      else out->len++;
+    }
+
+    return_trace (true);
+  }
+};
+
 struct RangeRecord
 {
   int cmp (hb_codepoint_t g) const
@@ -434,7 +517,7 @@
 DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
 
 
-struct IndexArray : ArrayOf<Index>
+struct IndexArray : Array16Of<Index>
 {
   bool intersects (const hb_map_t *indexes) const
   { return hb_any (*this, indexes); }
@@ -474,7 +557,7 @@
 
   void add_indexes_to (hb_set_t* output /* OUT */) const
   {
-    output->add_array (arrayZ, len);
+    output->add_array (as_array ());
   }
 };
 
@@ -506,18 +589,46 @@
     return_trace (c->embed (*this));
   }
 
-  bool operator == (const LangSys& o) const
+  bool compare (const LangSys& o, const hb_map_t *feature_index_map) const
   {
-    if (featureIndex.len != o.featureIndex.len ||
-	reqFeatureIndex != o.reqFeatureIndex)
+    if (reqFeatureIndex != o.reqFeatureIndex)
       return false;
 
-    for (const auto _ : + hb_zip (featureIndex, o.featureIndex))
+    auto iter =
+    + hb_iter (featureIndex)
+    | hb_filter (feature_index_map)
+    | hb_map (feature_index_map)
+    ;
+
+    auto o_iter =
+    + hb_iter (o.featureIndex)
+    | hb_filter (feature_index_map)
+    | hb_map (feature_index_map)
+    ;
+
+    if (iter.len () != o_iter.len ())
+      return false;
+
+    for (const auto _ : + hb_zip (iter, o_iter))
       if (_.first != _.second) return false;
 
     return true;
   }
 
+  void collect_features (hb_prune_langsys_context_t *c) const
+  {
+    if (!has_required_feature () && !get_feature_count ()) return;
+    if (c->visitedLangsys (this)) return;
+    if (has_required_feature () &&
+        c->duplicate_feature_map->has (reqFeatureIndex))
+      c->new_feature_indexes->add (get_required_feature_index ());
+
+    + hb_iter (featureIndex)
+    | hb_filter (c->duplicate_feature_map)
+    | hb_sink (c->new_feature_indexes)
+    ;
+  }
+
   bool subset (hb_subset_context_t        *c,
 	       hb_subset_layout_context_t *l,
 	       const Tag                  *tag = nullptr) const
@@ -581,6 +692,49 @@
   bool has_default_lang_sys () const           { return defaultLangSys != 0; }
   const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
 
+  void prune_langsys (hb_prune_langsys_context_t *c,
+                      unsigned script_index) const
+  {
+    if (!has_default_lang_sys () && !get_lang_sys_count ()) return;
+    if (c->visitedScript (this)) return;
+
+    if (!c->script_langsys_map->has (script_index))
+    {
+      hb_set_t* empty_set = hb_set_create ();
+      if (unlikely (!c->script_langsys_map->set (script_index, empty_set)))
+      {
+	hb_set_destroy (empty_set);
+	return;
+      }
+    }
+
+    unsigned langsys_count = get_lang_sys_count ();
+    if (has_default_lang_sys ())
+    {
+      //only collect features from non-redundant langsys
+      const LangSys& d = get_default_lang_sys ();
+      d.collect_features (c);
+
+      for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
+      {
+        const LangSys& l = this+_.first.offset;
+        if (l.compare (d, c->duplicate_feature_map)) continue;
+
+        l.collect_features (c);
+        c->script_langsys_map->get (script_index)->add (_.second);
+      }
+    }
+    else
+    {
+      for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
+      {
+        const LangSys& l = this+_.first.offset;
+        l.collect_features (c);
+        c->script_langsys_map->get (script_index)->add (_.second);
+      }
+    }
+  }
+
   bool subset (hb_subset_context_t         *c,
 	       hb_subset_layout_context_t  *l,
 	       const Tag                   *tag) const
@@ -609,16 +763,17 @@
       }
     }
 
-    + langSys.iter ()
-    | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
-    | hb_filter ([&] (const Record<LangSys>& record)
-		 {
-		   const LangSys& d = this+defaultLangSys;
-		   const LangSys& l = this+record.offset;
-		   return !(l == d);
-		 })
-    | hb_apply (subset_record_array (l, &(out->langSys), this))
-    ;
+    const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index);
+    if (active_langsys)
+    {
+      unsigned count = langSys.len;
+      + hb_zip (langSys, hb_range (count))
+      | hb_filter (active_langsys, hb_second)
+      | hb_map (hb_first)
+      | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
+      | hb_apply (subset_record_array (l, &(out->langSys), this))
+      ;
+    }
 
     return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB);
   }
@@ -631,7 +786,7 @@
   }
 
   protected:
-  OffsetTo<LangSys>
+  Offset16To<LangSys>
 		defaultLangSys;	/* Offset to DefaultLangSys table--from
 				 * beginning of Script table--may be Null */
   RecordArrayOf<LangSys>
@@ -641,7 +796,7 @@
   DEFINE_SIZE_ARRAY_SIZED (4, langSys);
 };
 
-typedef RecordListOf<Script> ScriptList;
+typedef RecordListOfScript ScriptList;
 
 
 /* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
@@ -856,7 +1011,7 @@
 					 * user-interface labels for the
 					 * feature parameters. (Must be zero
 					 * if numParameters is zero.) */
-  ArrayOf<HBUINT24>
+  Array16Of<HBUINT24>
 		characters;		/* Array of the Unicode Scalar Value
 					 * of the characters for which this
 					 * feature provides glyph variants.
@@ -953,7 +1108,7 @@
     auto *out = c->serializer->start_embed (*this);
     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
 
-    bool subset_featureParams = out->featureParams.serialize_subset (c, featureParams, this, tag);
+    out->featureParams.serialize_subset (c, featureParams, this, tag);
 
     auto it =
     + hb_iter (lookupIndex)
@@ -962,8 +1117,9 @@
     ;
 
     out->lookupIndex.serialize (c->serializer, l, it);
-    return_trace (bool (it) || subset_featureParams
-		  || (tag && *tag == HB_TAG ('p', 'r', 'e', 'f')));
+    // The decision to keep or drop this feature is already made before we get here
+    // so always retain it.
+    return_trace (true);
   }
 
   bool sanitize (hb_sanitize_context_t *c,
@@ -998,7 +1154,7 @@
       unsigned int new_offset_int = orig_offset -
 				    (((char *) this) - ((char *) closure->list_base));
 
-      OffsetTo<FeatureParams> new_offset;
+      Offset16To<FeatureParams> new_offset;
       /* Check that it would not overflow. */
       new_offset = new_offset_int;
       if (new_offset == new_offset_int &&
@@ -1010,7 +1166,7 @@
     return_trace (true);
   }
 
-  OffsetTo<FeatureParams>
+  Offset16To<FeatureParams>
 		 featureParams;	/* Offset to Feature Parameters table (if one
 				 * has been defined for the feature), relative
 				 * to the beginning of the Feature Table; = Null
@@ -1049,11 +1205,11 @@
   unsigned int get_subtable_count () const { return subTable.len; }
 
   template <typename TSubTable>
-  const OffsetArrayOf<TSubTable>& get_subtables () const
-  { return reinterpret_cast<const OffsetArrayOf<TSubTable> &> (subTable); }
+  const Array16OfOffset16To<TSubTable>& get_subtables () const
+  { return reinterpret_cast<const Array16OfOffset16To<TSubTable> &> (subTable); }
   template <typename TSubTable>
-  OffsetArrayOf<TSubTable>& get_subtables ()
-  { return reinterpret_cast<OffsetArrayOf<TSubTable> &> (subTable); }
+  Array16OfOffset16To<TSubTable>& get_subtables ()
+  { return reinterpret_cast<Array16OfOffset16To<TSubTable> &> (subTable); }
 
   template <typename TSubTable>
   const TSubTable& get_subtable (unsigned int i) const
@@ -1131,10 +1287,18 @@
     const hb_set_t *glyphset = c->plan->glyphset_gsub ();
     unsigned int lookup_type = get_type ();
     + hb_iter (get_subtables <TSubTable> ())
-    | hb_filter ([this, glyphset, lookup_type] (const OffsetTo<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); })
+    | hb_filter ([this, glyphset, lookup_type] (const Offset16To<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); })
     | hb_apply (subset_offset_array (c, out->get_subtables<TSubTable> (), this, lookup_type))
     ;
 
+    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
+    {
+      if (unlikely (!c->serializer->extend (out))) return_trace (false);
+      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
+      HBUINT16 &outMarkFilteringSet = StructAfter<HBUINT16> (out->subTable);
+      outMarkFilteringSet = markFilteringSet;
+    }
+
     return_trace (true);
   }
 
@@ -1179,7 +1343,7 @@
   private:
   HBUINT16	lookupType;		/* Different enumerations for GSUB and GPOS */
   HBUINT16	lookupFlag;		/* Lookup qualifiers */
-  ArrayOf<Offset16>
+  Array16Of<Offset16>
 		subTable;		/* Array of SubTables */
 /*HBUINT16	markFilteringSetX[HB_VAR_ARRAY];*//* Index (base 0) into GDEF mark glyph sets
 					 * structure. This field is only present if bit
@@ -1188,10 +1352,10 @@
   DEFINE_SIZE_ARRAY (6, subTable);
 };
 
-typedef OffsetListOf<Lookup> LookupList;
+typedef List16OfOffset16To<Lookup> LookupList;
 
 template <typename TLookup>
-struct LookupOffsetList : OffsetListOf<TLookup>
+struct LookupOffsetList : List16OfOffset16To<TLookup>
 {
   bool subset (hb_subset_context_t        *c,
 	       hb_subset_layout_context_t *l) const
@@ -1212,7 +1376,7 @@
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (OffsetListOf<TLookup>::sanitize (c, this));
+    return_trace (List16OfOffset16To<TLookup>::sanitize (c, this));
   }
 };
 
@@ -1250,10 +1414,8 @@
   bool intersects (const hb_set_t *glyphs) const
   {
     /* TODO Speed up, using hb_set_next() and bsearch()? */
-    unsigned int count = glyphArray.len;
-    const HBGlyphID *arr = glyphArray.arrayZ;
-    for (unsigned int i = 0; i < count; i++)
-      if (glyphs->has (arr[i]))
+    for (const auto& g : glyphArray.as_array ())
+      if (glyphs->has (g))
 	return true;
     return false;
   }
@@ -1260,9 +1422,17 @@
   bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
   { return glyphs->has (glyphArray[index]); }
 
+  void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const
+  {
+    unsigned count = glyphArray.len;
+    for (unsigned i = 0; i < count; i++)
+      if (glyphs->has (glyphArray[i]))
+        intersect_glyphs->add (glyphArray[i]);
+  }
+
   template <typename set_t>
   bool collect_coverage (set_t *glyphs) const
-  { return glyphs->add_sorted_array (glyphArray.arrayZ, glyphArray.len); }
+  { return glyphs->add_sorted_array (glyphArray.as_array ()); }
 
   public:
   /* Older compilers need this to be public. */
@@ -1284,7 +1454,7 @@
 
   protected:
   HBUINT16	coverageFormat;	/* Format identifier--format = 1 */
-  SortedArrayOf<HBGlyphID>
+  SortedArray16Of<HBGlyphID>
 		glyphArray;	/* Array of GlyphIDs--in numerical order */
   public:
   DEFINE_SIZE_ARRAY (4, glyphArray);
@@ -1358,10 +1528,8 @@
   {
     /* TODO Speed up, using hb_set_next() and bsearch()? */
     /* TODO(iter) Rewrite as dagger. */
-    unsigned count = rangeRecord.len;
-    const RangeRecord *arr = rangeRecord.arrayZ;
-    for (unsigned i = 0; i < count; i++)
-      if (arr[i].intersects (glyphs))
+    for (const auto& range : rangeRecord.as_array ())
+      if (range.intersects (glyphs))
 	return true;
     return false;
   }
@@ -1368,10 +1536,8 @@
   bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
   {
     /* TODO(iter) Rewrite as dagger. */
-    unsigned count = rangeRecord.len;
-    const RangeRecord *arr = rangeRecord.arrayZ;
-    for (unsigned i = 0; i < count; i++) {
-      const RangeRecord &range = arr[i];
+    for (const auto& range : rangeRecord.as_array ())
+    {
       if (range.value <= index &&
 	  index < (unsigned int) range.value + (range.last - range.first) &&
 	  range.intersects (glyphs))
@@ -1382,6 +1548,16 @@
     return false;
   }
 
+  void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const
+  {
+    for (const auto& range : rangeRecord.as_array ())
+    {
+      if (!range.intersects (glyphs)) continue;
+      for (hb_codepoint_t g = range.first; g <= range.last; g++)
+        if (glyphs->has (g)) intersect_glyphs->add (g);
+    }
+  }
+
   template <typename set_t>
   bool collect_coverage (set_t *glyphs) const
   {
@@ -1448,7 +1624,7 @@
 
   protected:
   HBUINT16	coverageFormat;	/* Format identifier--format = 2 */
-  SortedArrayOf<RangeRecord>
+  SortedArray16Of<RangeRecord>
 		rangeRecord;	/* Array of glyph ranges--ordered by
 				 * Start GlyphID. rangeCount entries
 				 * long */
@@ -1564,6 +1740,16 @@
     }
   }
 
+  void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const
+  {
+    switch (u.format)
+    {
+    case 1: return u.format1.intersected_coverage_glyphs (glyphs, intersect_glyphs);
+    case 2: return u.format2.intersected_coverage_glyphs (glyphs, intersect_glyphs);
+    default:return ;
+    }
+  }
+
   struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
   {
     static constexpr bool is_sorted_iterator = true;
@@ -1645,10 +1831,10 @@
 { 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,
 					  const hb_set_t &klasses,
+                                          bool use_class_zero,
 					  hb_map_t *klass_map /*INOUT*/)
 {
   if (!klass_map)
@@ -1660,7 +1846,7 @@
 
   /* any glyph not assigned a class value falls into Class zero (0),
    * if any glyph assigned to class 0, remapping must start with 0->0*/
-  if (glyphset.get_population () > gid_klass_map.get_population ())
+  if (!use_class_zero)
     klass_map->set (0, 0);
 
   unsigned idx = klass_map->has (0) ? 1 : 0;
@@ -1708,6 +1894,7 @@
 
     if (unlikely (!it))
     {
+      classFormat = 1;
       startGlyph = 0;
       classValue.len = 0;
       return_trace (true);
@@ -1730,7 +1917,10 @@
   }
 
   bool subset (hb_subset_context_t *c,
-	       hb_map_t *klass_map = nullptr /*OUT*/) const
+	       hb_map_t *klass_map = nullptr /*OUT*/,
+               bool keep_empty_table = true,
+               bool use_class_zero = true,
+               const Coverage* glyph_filter = nullptr) const
   {
     TRACE_SUBSET (this);
     const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
@@ -1742,9 +1932,12 @@
 
     hb_codepoint_t start = startGlyph;
     hb_codepoint_t end   = start + classValue.len;
+
     for (const hb_codepoint_t gid : + hb_range (start, end)
-				    | hb_filter (glyphset))
+                                    | hb_filter (glyphset))
     {
+      if (glyph_filter && !glyph_filter->has(gid)) continue;
+
       unsigned klass = classValue[gid - start];
       if (!klass) continue;
 
@@ -1753,9 +1946,13 @@
       orig_klasses.add (klass);
     }
 
-    ClassDef_remap_and_serialize (c->serializer, glyphset, gid_org_klass_map,
-				  glyphs, orig_klasses, klass_map);
-    return_trace ((bool) glyphs);
+    unsigned glyph_count = glyph_filter
+                           ? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter))
+                           : glyphset.get_population ();
+    use_class_zero = use_class_zero && glyph_count <= gid_org_klass_map.get_population ();
+    ClassDef_remap_and_serialize (c->serializer, gid_org_klass_map,
+				  glyphs, orig_klasses, use_class_zero, klass_map);
+    return_trace (keep_empty_table || (bool) glyphs);
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -1829,10 +2026,28 @@
     return false;
   }
 
+  void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const
+  {
+    unsigned count = classValue.len;
+    if (klass == 0)
+    {
+      hb_codepoint_t endGlyph = startGlyph + count -1;
+      for (hb_codepoint_t g : glyphs->iter ())
+        if (g < startGlyph || g > endGlyph)
+          intersect_glyphs->add (g);
+
+      return;
+    }
+
+    for (unsigned i = 0; i < count; i++)
+      if (classValue[i] == klass && glyphs->has (startGlyph + i))
+        intersect_glyphs->add (startGlyph + i);
+  }
+
   protected:
   HBUINT16	classFormat;	/* Format identifier--format = 1 */
   HBGlyphID	startGlyph;	/* First GlyphID of the classValueArray */
-  ArrayOf<HBUINT16>
+  Array16Of<HBUINT16>
 		classValue;	/* Array of Class Values--one per GlyphID */
   public:
   DEFINE_SIZE_ARRAY (6, classValue);
@@ -1858,6 +2073,7 @@
 
     if (unlikely (!it))
     {
+      classFormat = 2;
       rangeRecord.len = 0;
       return_trace (true);
     }
@@ -1903,7 +2119,10 @@
   }
 
   bool subset (hb_subset_context_t *c,
-	       hb_map_t *klass_map = nullptr /*OUT*/) const
+	       hb_map_t *klass_map = nullptr /*OUT*/,
+               bool keep_empty_table = true,
+               bool use_class_zero = true,
+               const Coverage* glyph_filter = nullptr) const
   {
     TRACE_SUBSET (this);
     const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
@@ -1923,6 +2142,7 @@
       for (hb_codepoint_t g = start; g < end; g++)
       {
 	if (!glyphset.has (g)) continue;
+        if (glyph_filter && !glyph_filter->has (g)) continue;
 	glyphs.push (glyph_map[g]);
 	gid_org_klass_map.set (glyph_map[g], klass);
 	orig_klasses.add (klass);
@@ -1929,9 +2149,13 @@
       }
     }
 
-    ClassDef_remap_and_serialize (c->serializer, glyphset, gid_org_klass_map,
-				  glyphs, orig_klasses, klass_map);
-    return_trace ((bool) glyphs);
+    unsigned glyph_count = glyph_filter
+                           ? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter))
+                           : glyphset.get_population ();
+    use_class_zero = use_class_zero && glyph_count <= gid_org_klass_map.get_population ();
+    ClassDef_remap_and_serialize (c->serializer, gid_org_klass_map,
+				  glyphs, orig_klasses, use_class_zero, klass_map);
+    return_trace (keep_empty_table || (bool) glyphs);
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -2005,9 +2229,57 @@
     return false;
   }
 
+  void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const
+  {
+    unsigned count = rangeRecord.len;
+    if (klass == 0)
+    {
+      hb_codepoint_t g = HB_SET_VALUE_INVALID;
+      for (unsigned int i = 0; i < count; i++)
+      {
+        if (!hb_set_next (glyphs, &g))
+          break;
+        while (g != HB_SET_VALUE_INVALID && g < rangeRecord[i].first)
+        {
+          intersect_glyphs->add (g);
+          hb_set_next (glyphs, &g);
+        }
+        g = rangeRecord[i].last;
+      }
+      while (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
+        intersect_glyphs->add (g);
+
+      return;
+    }
+
+    hb_codepoint_t g = HB_SET_VALUE_INVALID;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (rangeRecord[i].value != klass) continue;
+
+      if (g != HB_SET_VALUE_INVALID)
+      {
+        if (g >= rangeRecord[i].first &&
+            g <= rangeRecord[i].last)
+          intersect_glyphs->add (g);
+        if (g > rangeRecord[i].last)
+          continue;
+      }
+
+      g = rangeRecord[i].first - 1;
+      while (hb_set_next (glyphs, &g))
+      {
+        if (g >= rangeRecord[i].first && g <= rangeRecord[i].last)
+          intersect_glyphs->add (g);
+        else if (g > rangeRecord[i].last)
+          break;
+      }
+    }
+  }
+
   protected:
   HBUINT16	classFormat;	/* Format identifier--format = 2 */
-  SortedArrayOf<RangeRecord>
+  SortedArray16Of<RangeRecord>
 		rangeRecord;	/* Array of glyph ranges--ordered by
 				 * Start GlyphID */
   public:
@@ -2036,19 +2308,20 @@
 
   template<typename Iterator,
 	   hb_requires (hb_is_iterator (Iterator))>
-  bool serialize (hb_serialize_context_t *c, Iterator it)
+  bool serialize (hb_serialize_context_t *c, Iterator it_with_class_zero)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
 
+    auto it = + it_with_class_zero | hb_filter (hb_second);
+
     unsigned format = 2;
     if (likely (it))
     {
       hb_codepoint_t glyph_min = (*it).first;
-      hb_codepoint_t glyph_max = + it
-				 | hb_map (hb_first)
-				 | hb_reduce (hb_max, 0u);
+      hb_codepoint_t glyph_max = glyph_min;
 
+      unsigned num_glyphs = 0;
       unsigned num_ranges = 1;
       hb_codepoint_t prev_gid = glyph_min;
       unsigned prev_klass = (*it).second;
@@ -2057,7 +2330,9 @@
       {
 	hb_codepoint_t cur_gid = gid_klass_pair.first;
 	unsigned cur_klass = gid_klass_pair.second;
-	if (cur_gid == glyph_min || !cur_klass) continue;
+        num_glyphs++;
+	if (cur_gid == glyph_min) continue;
+        if (cur_gid > glyph_max) glyph_max = cur_gid;
 	if (cur_gid != prev_gid + 1 ||
 	    cur_klass != prev_klass)
 	  num_ranges++;
@@ -2066,7 +2341,7 @@
 	prev_klass = cur_klass;
       }
 
-      if (1 + (glyph_max - glyph_min + 1) <= num_ranges * 3)
+      if (num_glyphs && 1 + (glyph_max - glyph_min + 1) <= num_ranges * 3)
 	format = 1;
     }
     u.format = format;
@@ -2080,12 +2355,15 @@
   }
 
   bool subset (hb_subset_context_t *c,
-	       hb_map_t *klass_map = nullptr /*OUT*/) const
+	       hb_map_t *klass_map = nullptr /*OUT*/,
+               bool keep_empty_table = true,
+               bool use_class_zero = true,
+               const Coverage* glyph_filter = nullptr) const
   {
     TRACE_SUBSET (this);
     switch (u.format) {
-    case 1: return_trace (u.format1.subset (c, klass_map));
-    case 2: return_trace (u.format2.subset (c, klass_map));
+    case 1: return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+    case 2: return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
     default:return_trace (false);
     }
   }
@@ -2142,6 +2420,15 @@
     }
   }
 
+  void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+    case 2: return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+    default:return;
+    }
+  }
+
   protected:
   union {
   HBUINT16		format;		/* Format identifier */
@@ -2439,7 +2726,7 @@
   protected:
   HBUINT16		itemCount;
   HBUINT16		shortCount;
-  ArrayOf<HBUINT16>	regionIndices;
+  Array16Of<HBUINT16>	regionIndices;
 /*UnsizedArrayOf<HBUINT8>bytesX;*/
   public:
   DEFINE_SIZE_ARRAY (6, regionIndices);
@@ -2447,6 +2734,7 @@
 
 struct VariationStore
 {
+  private:
   float get_delta (unsigned int outer, unsigned int inner,
 		   const int *coords, unsigned int coord_count) const
   {
@@ -2462,6 +2750,7 @@
 					     this+regions);
   }
 
+  public:
   float get_delta (unsigned int index,
 		   const int *coords, unsigned int coord_count) const
   {
@@ -2505,7 +2794,7 @@
 		  .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 ()
+     * List16OfOffset16To::subset () can take a custom param to be passed to VarData::serialize ()
      */
     dataSets.len = set_count;
     unsigned int set_index = 0;
@@ -2580,8 +2869,8 @@
 
   protected:
   HBUINT16				format;
-  LOffsetTo<VarRegionList>		regions;
-  LOffsetArrayOf<VarData>		dataSets;
+  Offset32To<VarRegionList>		regions;
+  Array16OfOffset32To<VarData>		dataSets;
   public:
   DEFINE_SIZE_ARRAY (8, dataSets);
 };
@@ -2684,7 +2973,8 @@
     + conditions.iter ()
     | hb_apply (subset_offset_array (c, out->conditions, this))
     ;
-    return_trace (true);
+
+    return_trace (bool (out->conditions));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -2694,7 +2984,7 @@
   }
 
   protected:
-  LOffsetArrayOf<Condition>	conditions;
+  Array16OfOffset32To<Condition>	conditions;
   public:
   DEFINE_SIZE_ARRAY (2, conditions);
 };
@@ -2719,6 +3009,12 @@
   bool subset (hb_subset_layout_context_t *c, const void *base) const
   {
     TRACE_SUBSET (this);
+    if (!c->feature_index_map->has (featureIndex)) {
+      // Feature that is being substituted is not being retained, so we don't
+      // need this.
+      return_trace (false);
+    }
+
     auto *out = c->subset_context->serializer->embed (this);
     if (unlikely (!out)) return_trace (false);
 
@@ -2735,7 +3031,7 @@
 
   protected:
   HBUINT16		featureIndex;
-  LOffsetTo<Feature>	feature;
+  Offset32To<Feature>	feature;
   public:
   DEFINE_SIZE_STATIC (6);
 };
@@ -2771,6 +3067,15 @@
       record.closure_features (this, lookup_indexes, feature_indexes);
   }
 
+  bool intersects_features (const hb_map_t *feature_index_map) const
+  {
+    for (const FeatureTableSubstitutionRecord& record : substitutions)
+    {
+      if (feature_index_map->has (record.featureIndex)) return true;
+    }
+    return false;
+  }
+
   bool subset (hb_subset_context_t        *c,
 	       hb_subset_layout_context_t *l) const
   {
@@ -2784,7 +3089,8 @@
     + substitutions.iter ()
     | hb_apply (subset_record_array (l, &(out->substitutions), this))
     ;
-    return_trace (true);
+
+    return_trace (bool (out->substitutions));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -2797,7 +3103,7 @@
 
   protected:
   FixedVersion<>	version;	/* Version--0x00010000u */
-  ArrayOf<FeatureTableSubstitutionRecord>
+  Array16Of<FeatureTableSubstitutionRecord>
 			substitutions;
   public:
   DEFINE_SIZE_ARRAY (6, substitutions);
@@ -2821,6 +3127,11 @@
     (base+substitutions).closure_features (lookup_indexes, feature_indexes);
   }
 
+  bool intersects_features (const void *base, const hb_map_t *feature_index_map) const
+  {
+    return (base+substitutions).intersects_features (feature_index_map);
+  }
+
   bool subset (hb_subset_layout_context_t *c, const void *base) const
   {
     TRACE_SUBSET (this);
@@ -2841,9 +3152,9 @@
   }
 
   protected:
-  LOffsetTo<ConditionSet>
+  Offset32To<ConditionSet>
 			conditions;
-  LOffsetTo<FeatureTableSubstitution>
+  Offset32To<FeatureTableSubstitution>
 			substitutions;
   public:
   DEFINE_SIZE_STATIC (8);
@@ -2907,9 +3218,18 @@
     out->version.major = version.major;
     out->version.minor = version.minor;
 
-    + varRecords.iter ()
-    | hb_apply (subset_record_array (l, &(out->varRecords), this))
-    ;
+    int keep_up_to = -1;
+    for (int i = varRecords.len - 1; i >= 0; i--) {
+      if (varRecords[i].intersects_features (this, l->feature_index_map)) {
+        keep_up_to = i;
+        break;
+      }
+    }
+
+    unsigned count = (unsigned) (keep_up_to + 1);
+    for (unsigned i = 0; i < count; i++) {
+      subset_record_array (l, &(out->varRecords), this) (varRecords[i]);
+    }
     return_trace (bool (out->varRecords));
   }
 
@@ -2923,7 +3243,7 @@
 
   protected:
   FixedVersion<>	version;	/* Version--0x00010000u */
-  LArrayOf<FeatureVariationRecord>
+  Array32Of<FeatureVariationRecord>
 			varRecords;
   public:
   DEFINE_SIZE_ARRAY_SIZED (8, varRecords);
@@ -3036,22 +3356,20 @@
     if (unlikely (!out)) return_trace (nullptr);
     if (!layout_variation_idx_map || layout_variation_idx_map->is_empty ()) return_trace (out);
 
-    unsigned org_idx = (outerIndex << 16) + innerIndex;
-    if (!layout_variation_idx_map->has (org_idx))
+    /* TODO Just get() and bail if NO_VARIATION. Needs to setup the map to return that. */
+    if (!layout_variation_idx_map->has (varIdx))
     {
       c->revert (snap);
       return_trace (nullptr);
     }
-    unsigned new_idx = layout_variation_idx_map->get (org_idx);
-    out->outerIndex = new_idx >> 16;
-    out->innerIndex = new_idx & 0xFFFF;
+    unsigned new_idx = layout_variation_idx_map->get (varIdx);
+    out->varIdx = new_idx;
     return_trace (out);
   }
 
   void record_variation_index (hb_set_t *layout_variation_indices) const
   {
-    unsigned var_idx = (outerIndex << 16) + innerIndex;
-    layout_variation_indices->add (var_idx);
+    layout_variation_indices->add (varIdx);
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -3064,12 +3382,11 @@
 
   float get_delta (hb_font_t *font, const VariationStore &store) const
   {
-    return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords);
+    return store.get_delta (varIdx, font->coords, font->num_coords);
   }
 
   protected:
-  HBUINT16	outerIndex;
-  HBUINT16	innerIndex;
+  VarIdx	varIdx;
   HBUINT16	deltaFormat;	/* Format identifier for this table: 0x0x8000 */
   public:
   DEFINE_SIZE_STATIC (6);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -42,7 +42,7 @@
  */
 
 /* Array of contour point indices--in increasing numerical order */
-struct AttachPoint : ArrayOf<HBUINT16>
+struct AttachPoint : Array16Of<HBUINT16>
 {
   bool subset (hb_subset_context_t *c) const
   {
@@ -110,10 +110,10 @@
   }
 
   protected:
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table -- from
 					 * beginning of AttachList table */
-  OffsetArrayOf<AttachPoint>
+  Array16OfOffset16To<AttachPoint>
 		attachPoint;		/* Array of AttachPoint tables
 					 * in Coverage Index order */
   public:
@@ -220,7 +220,7 @@
   protected:
   HBUINT16	caretValueFormat;	/* Format identifier--format = 3 */
   FWORD		coordinate;		/* X or Y value, in design units */
-  OffsetTo<Device>
+  Offset16To<Device>
 		deviceTable;		/* Offset to Device table for X or Y
 					 * value--from beginning of CaretValue
 					 * table */
@@ -329,7 +329,7 @@
 
   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
   {
-    for (const OffsetTo<CaretValue>& offset : carets.iter ())
+    for (const Offset16To<CaretValue>& offset : carets.iter ())
       (this+offset).collect_variation_indices (c->layout_variation_indices);
   }
 
@@ -340,7 +340,7 @@
   }
 
   protected:
-  OffsetArrayOf<CaretValue>
+  Array16OfOffset16To<CaretValue>
 		carets;			/* Offset array of CaretValue tables
 					 * --from beginning of LigGlyph table
 					 * --in increasing coordinate order */
@@ -408,10 +408,10 @@
   }
 
   protected:
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of LigCaretList table */
-  OffsetArrayOf<LigGlyph>
+  Array16OfOffset16To<LigGlyph>
 		ligGlyph;		/* Array of LigGlyph tables
 					 * in Coverage Index order */
   public:
@@ -432,7 +432,7 @@
     out->format = format;
 
     bool ret = true;
-    for (const LOffsetTo<Coverage>& offset : coverage.iter ())
+    for (const Offset32To<Coverage>& offset : coverage.iter ())
     {
       auto *o = out->coverage.serialize_append (c->serializer);
       if (unlikely (!o))
@@ -460,7 +460,7 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  ArrayOf<LOffsetTo<Coverage>>
+  Array16Of<Offset32To<Coverage>>
 		coverage;		/* Array of long offsets to mark set
 					 * coverage tables */
   public:
@@ -643,10 +643,10 @@
     auto *out = c->serializer->embed (*this);
     if (unlikely (!out)) return_trace (false);
 
-    bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this);
+    bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
     bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
     bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
-    bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this);
+    bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);
 
     bool subset_markglyphsetsdef = true;
     if (version.to_int () >= 0x00010002u)
@@ -687,28 +687,28 @@
   protected:
   FixedVersion<>version;		/* Version of the GDEF table--currently
 					 * 0x00010003u */
-  OffsetTo<ClassDef>
+  Offset16To<ClassDef>
 		glyphClassDef;		/* Offset to class definition table
 					 * for glyph type--from beginning of
 					 * GDEF header (may be Null) */
-  OffsetTo<AttachList>
+  Offset16To<AttachList>
 		attachList;		/* Offset to list of glyphs with
 					 * attachment points--from beginning
 					 * of GDEF header (may be Null) */
-  OffsetTo<LigCaretList>
+  Offset16To<LigCaretList>
 		ligCaretList;		/* Offset to list of positioning points
 					 * for ligature carets--from beginning
 					 * of GDEF header (may be Null) */
-  OffsetTo<ClassDef>
+  Offset16To<ClassDef>
 		markAttachClassDef;	/* Offset to class definition table for
 					 * mark attachment type--from beginning
 					 * of GDEF header (may be Null) */
-  OffsetTo<MarkGlyphSets>
+  Offset16To<MarkGlyphSets>
 		markGlyphSetsDef;	/* Offset to the table of mark set
 					 * definitions--from beginning of GDEF
 					 * header (may be NULL).  Introduced
 					 * in version 0x00010002. */
-  LOffsetTo<VariationStore>
+  Offset32To<VariationStore>
 		varStore;		/* Offset to the table of Item Variation
 					 * Store--from beginning of GDEF
 					 * header (may be NULL).  Introduced

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -89,20 +89,22 @@
   HBINT16		yAdvance;	/* Vertical adjustment for advance--in
 					 * design units (only used for vertical
 					 * writing) */
-  OffsetTo<Device>	xPlaDevice;	/* Offset to Device table for
+  Offset16To<Device>	xPlaDevice;	/* Offset to Device table for
 					 * horizontal placement--measured from
 					 * beginning of PosTable (may be NULL) */
-  OffsetTo<Device>	yPlaDevice;	/* Offset to Device table for vertical
+  Offset16To<Device>	yPlaDevice;	/* Offset to Device table for vertical
 					 * placement--measured from beginning
 					 * of PosTable (may be NULL) */
-  OffsetTo<Device>	xAdvDevice;	/* Offset to Device table for
+  Offset16To<Device>	xAdvDevice;	/* Offset to Device table for
 					 * horizontal advance--measured from
 					 * beginning of PosTable (may be NULL) */
-  OffsetTo<Device>	yAdvDevice;	/* Offset to Device table for vertical
+  Offset16To<Device>	yAdvDevice;	/* Offset to Device table for vertical
 					 * advance--measured from beginning of
 					 * PosTable (may be NULL) */
 #endif
 
+  IntType& operator = (uint16_t i) { v = i; return *this; }
+
   unsigned int get_len () const  { return hb_popcount ((unsigned int) *this); }
   unsigned int get_size () const { return get_len () * Value::static_size; }
 
@@ -160,16 +162,40 @@
     return ret;
   }
 
-  void serialize_copy (hb_serialize_context_t *c, const void *base,
-		       const Value *values, const hb_map_t *layout_variation_idx_map) const
+  unsigned int get_effective_format (const Value *values) const
   {
     unsigned int format = *this;
+    for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) {
+      if (format & flag) should_drop (*values++, (Flags) flag, &format);
+    }
+
+    return format;
+  }
+
+  template<typename Iterator,
+      hb_requires (hb_is_iterator (Iterator))>
+  unsigned int get_effective_format (Iterator it) const {
+    unsigned int new_format = 0;
+
+    for (const hb_array_t<const Value>& values : it)
+      new_format = new_format | get_effective_format (&values);
+
+    return new_format;
+  }
+
+  void copy_values (hb_serialize_context_t *c,
+                    unsigned int new_format,
+                    const void *base,
+                    const Value *values,
+                    const hb_map_t *layout_variation_idx_map) const
+  {
+    unsigned int format = *this;
     if (!format) return;
 
-    if (format & xPlacement) c->copy (*values++);
-    if (format & yPlacement) c->copy (*values++);
-    if (format & xAdvance)   c->copy (*values++);
-    if (format & yAdvance)   c->copy (*values++);
+    if (format & xPlacement) copy_value (c, new_format, xPlacement, *values++);
+    if (format & yPlacement) copy_value (c, new_format, yPlacement, *values++);
+    if (format & xAdvance)   copy_value (c, new_format, xAdvance, *values++);
+    if (format & yAdvance)   copy_value (c, new_format, yAdvance, *values++);
 
     if (format & xPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
     if (format & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
@@ -177,6 +203,16 @@
     if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
   }
 
+  void copy_value (hb_serialize_context_t *c,
+                   unsigned int new_format,
+                   Flags flag,
+                   Value value) const
+  {
+    // Filter by new format.
+    if (!(new_format & flag)) return;
+    c->copy (value);
+  }
+
   void collect_variation_indices (hb_collect_variation_indices_context_t *c,
 				  const void *base,
 				  const hb_array_t<const Value>& values) const
@@ -232,14 +268,14 @@
     return true;
   }
 
-  static inline OffsetTo<Device>& get_device (Value* value)
+  static inline Offset16To<Device>& get_device (Value* value)
   {
-    return *static_cast<OffsetTo<Device> *> (value);
+    return *static_cast<Offset16To<Device> *> (value);
   }
-  static inline const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
+  static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr)
   {
     if (worked) *worked |= bool (*value);
-    return *static_cast<const OffsetTo<Device> *> (value);
+    return *static_cast<const Offset16To<Device> *> (value);
   }
 
   bool copy_device (hb_serialize_context_t *c, const void *base,
@@ -317,13 +353,21 @@
 
     return_trace (true);
   }
+
+ private:
+
+  void should_drop (Value value, Flags flag, unsigned int* format) const
+  {
+    if (value) return;
+    *format = *format & ~flag;
+  }
+
 };
 
-template<typename Iterator>
+template<typename Iterator, typename SrcLookup>
 static void SinglePos_serialize (hb_serialize_context_t *c,
-				 const void *src,
+				 const SrcLookup *src,
 				 Iterator it,
-				 ValueFormat valFormat,
 				 const hb_map_t *layout_variation_idx_map);
 
 
@@ -346,7 +390,10 @@
   AnchorFormat1* copy (hb_serialize_context_t *c) const
   {
     TRACE_SERIALIZE (this);
-    return_trace (c->embed<AnchorFormat1> (this));
+    AnchorFormat1* out = c->embed<AnchorFormat1> (this);
+    if (!out) return_trace (out);
+    out->format = 1;
+    return_trace (out);
   }
 
   protected:
@@ -447,11 +494,11 @@
   HBUINT16	format;			/* Format identifier--format = 3 */
   FWORD		xCoordinate;		/* Horizontal value--in design units */
   FWORD		yCoordinate;		/* Vertical value--in design units */
-  OffsetTo<Device>
+  Offset16To<Device>
 		xDeviceTable;		/* Offset to Device table for X
 					 * coordinate-- from beginning of
 					 * Anchor table (may be NULL) */
-  OffsetTo<Device>
+  Offset16To<Device>
 		yDeviceTable;		/* Offset to Device table for Y
 					 * coordinate-- from beginning of
 					 * Anchor table (may be NULL) */
@@ -485,14 +532,22 @@
     }
   }
 
-  Anchor* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const
+  bool subset (hb_subset_context_t *c) const
   {
-    TRACE_SERIALIZE (this);
+    TRACE_SUBSET (this);
     switch (u.format) {
-    case 1: return_trace (reinterpret_cast<Anchor *> (u.format1.copy (c)));
-    case 2: return_trace (reinterpret_cast<Anchor *> (u.format2.copy (c)));
-    case 3: return_trace (reinterpret_cast<Anchor *> (u.format3.copy (c, layout_variation_idx_map)));
-    default:return_trace (nullptr);
+    case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
+    case 2:
+      if (c->plan->drop_hints)
+      {
+        // AnchorFormat 2 just containins extra hinting information, so
+        // if hints are being dropped convert to format 1.
+        return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
+      }
+      return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer))));
+    case 3: return_trace (bool (reinterpret_cast<Anchor *> (u.format3.copy (c->serializer,
+                                                                            c->plan->layout_variation_idx_map))));
+    default:return_trace (false);
     }
   }
 
@@ -541,51 +596,29 @@
   }
 
   template <typename Iterator,
-	    hb_requires (hb_is_iterator (Iterator))>
-  bool serialize (hb_serialize_context_t *c,
-		  unsigned                num_rows,
-		  AnchorMatrix const     *offset_matrix,
-		  const hb_map_t         *layout_variation_idx_map,
-		  Iterator                index_iter)
+      hb_requires (hb_is_iterator (Iterator))>
+  bool subset (hb_subset_context_t *c,
+               unsigned             num_rows,
+               Iterator             index_iter) const
   {
-    TRACE_SERIALIZE (this);
+    TRACE_SUBSET (this);
+
+    auto *out = c->serializer->start_embed (this);
+
     if (!index_iter) return_trace (false);
-    if (unlikely (!c->extend_min ((*this))))  return_trace (false);
+    if (unlikely (!c->serializer->extend_min (out)))  return_trace (false);
 
-    this->rows = num_rows;
+    out->rows = num_rows;
     for (const unsigned i : index_iter)
     {
-      auto *offset = c->embed (offset_matrix->matrixZ[i]);
+      auto *offset = c->serializer->embed (matrixZ[i]);
       if (!offset) return_trace (false);
-      offset->serialize_copy (c, offset_matrix->matrixZ[i],
-			      offset_matrix, c->to_bias (this),
-			      hb_serialize_context_t::Head,
-			      layout_variation_idx_map);
+      offset->serialize_subset (c, matrixZ[i], this);
     }
 
     return_trace (true);
   }
 
-  bool subset (hb_subset_context_t *c,
-	       unsigned cols,
-	       const hb_map_t *klass_mapping) const
-  {
-    TRACE_SUBSET (this);
-    auto *out = c->serializer->start_embed (*this);
-
-    auto indexes =
-    + hb_range (rows * cols)
-    | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % cols); })
-    ;
-
-    out->serialize (c->serializer,
-                    (unsigned) rows,
-                    this,
-                    c->plan->layout_variation_idx_map,
-                    indexes);
-    return_trace (true);
-  }
-
   bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
   {
     TRACE_SANITIZE (this);
@@ -599,7 +632,7 @@
   }
 
   HBUINT16	rows;			/* Number of rows */
-  UnsizedArrayOf<OffsetTo<Anchor>>
+  UnsizedArrayOf<Offset16To<Anchor>>
 		matrixZ;		/* Matrix of offsets to Anchor tables--
 					 * from beginning of AnchorMatrix table */
   public:
@@ -618,18 +651,16 @@
     return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
   }
 
-  MarkRecord *copy (hb_serialize_context_t *c,
-		    const void             *src_base,
-		    unsigned                dst_bias,
-		    const hb_map_t         *klass_mapping,
-		    const hb_map_t         *layout_variation_idx_map) const
+  MarkRecord *subset (hb_subset_context_t    *c,
+                      const void             *src_base,
+                      const hb_map_t         *klass_mapping) const
   {
-    TRACE_SERIALIZE (this);
-    auto *out = c->embed (this);
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
     if (unlikely (!out)) return_trace (nullptr);
 
     out->klass = klass_mapping->get (klass);
-    out->markAnchor.serialize_copy (c, markAnchor, src_base, dst_bias, hb_serialize_context_t::Head, layout_variation_idx_map);
+    out->markAnchor.serialize_subset (c, markAnchor, src_base);
     return_trace (out);
   }
 
@@ -641,7 +672,7 @@
 
   protected:
   HBUINT16	klass;			/* Class defined for this mark */
-  OffsetTo<Anchor>
+  Offset16To<Anchor>
 		markAnchor;		/* Offset to Anchor table--from
 					 * beginning of MarkArray table */
   public:
@@ -648,7 +679,7 @@
   DEFINE_SIZE_STATIC (4);
 };
 
-struct MarkArray : ArrayOf<MarkRecord>	/* Array of MarkRecords--in Coverage order */
+struct MarkArray : Array16Of<MarkRecord>	/* Array of MarkRecords--in Coverage order */
 {
   bool apply (hb_ot_apply_context_t *c,
 	      unsigned int mark_index, unsigned int glyph_index,
@@ -657,7 +688,7 @@
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
-    const MarkRecord &record = ArrayOf<MarkRecord>::operator[](mark_index);
+    const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index);
     unsigned int mark_class = record.klass;
 
     const Anchor& mark_anchor = this + record.markAnchor;
@@ -684,18 +715,35 @@
     return_trace (true);
   }
 
-  template<typename Iterator,
-	   hb_requires (hb_is_source_of (Iterator, MarkRecord))>
-  bool serialize (hb_serialize_context_t *c,
-		  const hb_map_t         *klass_mapping,
-		  const hb_map_t         *layout_variation_idx_map,
-		  const void             *base,
-		  Iterator                it)
+  template <typename Iterator,
+      hb_requires (hb_is_iterator (Iterator))>
+  bool subset (hb_subset_context_t *c,
+               Iterator		    coverage,
+               const hb_map_t      *klass_mapping) const
   {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!c->check_assign (len, it.len ()))) return_trace (false);
-    c->copy_all (it, base, c->to_bias (this), klass_mapping, layout_variation_idx_map);
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+
+    auto* out = c->serializer->start_embed (this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+    auto mark_iter =
+    + hb_zip (coverage, this->iter ())
+    | hb_filter (glyphset, hb_first)
+    | hb_map (hb_second)
+    ;
+
+    unsigned new_length = 0;
+    for (const auto& mark_record : mark_iter) {
+      if (unlikely (!mark_record.subset (c, this, klass_mapping)))
+        return_trace (false);
+      new_length++;
+    }
+
+    if (unlikely (!c->serializer->check_assign (out->len, new_length,
+                                                HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
+      return_trace (false);
+
     return_trace (true);
   }
 
@@ -702,7 +750,7 @@
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (ArrayOf<MarkRecord>::sanitize (c, this));
+    return_trace (Array16Of<MarkRecord>::sanitize (c, this));
   }
 };
 
@@ -733,6 +781,8 @@
 
   const Coverage &get_coverage () const { return this+coverage; }
 
+  ValueFormat get_value_format () const { return valueFormat; }
+
   bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
@@ -747,22 +797,26 @@
   }
 
   template<typename Iterator,
-	   hb_requires (hb_is_iterator (Iterator))>
+      typename SrcLookup,
+      hb_requires (hb_is_iterator (Iterator))>
   void serialize (hb_serialize_context_t *c,
-		  const void *src,
+		  const SrcLookup *src,
 		  Iterator it,
-		  ValueFormat valFormat,
+		  ValueFormat newFormat,
 		  const hb_map_t *layout_variation_idx_map)
   {
-    auto out = c->extend_min (*this);
-    if (unlikely (!out)) return;
-    if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
+    if (unlikely (!c->extend_min (*this))) return;
+    if (unlikely (!c->check_assign (valueFormat,
+                                    newFormat,
+                                    HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
 
-    + it
-    | hb_map (hb_second)
-    | hb_apply ([&] (hb_array_t<const Value> _)
-		{ valFormat.serialize_copy (c, src, &_, layout_variation_idx_map); })
-    ;
+    for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second))
+    {
+      src->get_value_format ().copy_values (c, newFormat, src,  &_, layout_variation_idx_map);
+      // Only serialize the first entry in the iterator, the rest are assumed to
+      // be the same.
+      break;
+    }
 
     auto glyphs =
     + it
@@ -769,6 +823,7 @@
     | hb_map_retains_sorting (hb_first)
     ;
 
+    // TODO(garretrieger): serialize_subset this.
     coverage.serialize (c, this).serialize (c, glyphs);
   }
 
@@ -786,7 +841,7 @@
     ;
 
     bool ret = bool (it);
-    SinglePos_serialize (c->serializer, this, it, valueFormat, c->plan->layout_variation_idx_map);
+    SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
     return_trace (ret);
   }
 
@@ -800,7 +855,7 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ValueFormat	valueFormat;		/* Defines the types of data in the
@@ -843,6 +898,8 @@
 
   const Coverage &get_coverage () const { return this+coverage; }
 
+  ValueFormat get_value_format () const { return valueFormat; }
+
   bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
@@ -861,22 +918,23 @@
   }
 
   template<typename Iterator,
-	   hb_requires (hb_is_iterator (Iterator))>
+      typename SrcLookup,
+      hb_requires (hb_is_iterator (Iterator))>
   void serialize (hb_serialize_context_t *c,
-		  const void *src,
+		  const SrcLookup *src,
 		  Iterator it,
-		  ValueFormat valFormat,
+		  ValueFormat newFormat,
 		  const hb_map_t *layout_variation_idx_map)
   {
     auto out = c->extend_min (*this);
     if (unlikely (!out)) return;
-    if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
-    if (unlikely (!c->check_assign (valueCount, it.len ()))) return;
+    if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
+    if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return;
 
     + it
     | hb_map (hb_second)
     | hb_apply ([&] (hb_array_t<const Value> _)
-		{ valFormat.serialize_copy (c, src, &_, layout_variation_idx_map); })
+    { src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); })
     ;
 
     auto glyphs =
@@ -908,7 +966,7 @@
     ;
 
     bool ret = bool (it);
-    SinglePos_serialize (c->serializer, this, it, valueFormat, c->plan->layout_variation_idx_map);
+    SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
     return_trace (ret);
   }
 
@@ -922,7 +980,7 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 2 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ValueFormat	valueFormat;		/* Defines the types of data in the
@@ -952,24 +1010,37 @@
 
 
   template<typename Iterator,
-	   hb_requires (hb_is_iterator (Iterator))>
+      typename SrcLookup,
+      hb_requires (hb_is_iterator (Iterator))>
   void serialize (hb_serialize_context_t *c,
-		  const void *src,
+		  const SrcLookup* src,
 		  Iterator glyph_val_iter_pairs,
-		  ValueFormat valFormat,
 		  const hb_map_t *layout_variation_idx_map)
   {
     if (unlikely (!c->extend_min (u.format))) return;
     unsigned format = 2;
+    ValueFormat new_format = src->get_value_format ();
 
-    if (glyph_val_iter_pairs) format = get_format (glyph_val_iter_pairs);
+    if (glyph_val_iter_pairs)
+    {
+      format = get_format (glyph_val_iter_pairs);
+      new_format = src->get_value_format ().get_effective_format (+ glyph_val_iter_pairs | hb_map (hb_second));
+    }
 
     u.format = format;
     switch (u.format) {
-    case 1: u.format1.serialize (c, src, glyph_val_iter_pairs, valFormat, layout_variation_idx_map);
-	    return;
-    case 2: u.format2.serialize (c, src, glyph_val_iter_pairs, valFormat, layout_variation_idx_map);
-	    return;
+    case 1: u.format1.serialize (c,
+                                 src,
+                                 glyph_val_iter_pairs,
+                                 new_format,
+                                 layout_variation_idx_map);
+      return;
+    case 2: u.format2.serialize (c,
+                                 src,
+                                 glyph_val_iter_pairs,
+                                 new_format,
+                                 layout_variation_idx_map);
+      return;
     default:return;
     }
   }
@@ -994,14 +1065,13 @@
   } u;
 };
 
-template<typename Iterator>
+template<typename Iterator, typename SrcLookup>
 static void
 SinglePos_serialize (hb_serialize_context_t *c,
-		     const void *src,
+		     const SrcLookup *src,
 		     Iterator it,
-		     ValueFormat valFormat,
 		     const hb_map_t *layout_variation_idx_map)
-{ c->start_embed<SinglePos> ()->serialize (c, src, it, valFormat, layout_variation_idx_map); }
+{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_map); }
 
 
 struct PairValueRecord
@@ -1011,26 +1081,35 @@
   int cmp (hb_codepoint_t k) const
   { return secondGlyph.cmp (k); }
 
-  struct serialize_closure_t
+  struct context_t
   {
     const void 		*base;
     const ValueFormat	*valueFormats;
+    const ValueFormat	*newFormats;
     unsigned		len1; /* valueFormats[0].get_len() */
     const hb_map_t 	*glyph_map;
     const hb_map_t      *layout_variation_idx_map;
   };
 
-  bool serialize (hb_serialize_context_t *c,
-		  serialize_closure_t *closure) const
+  bool subset (hb_subset_context_t *c,
+               context_t *closure) const
   {
     TRACE_SERIALIZE (this);
-    auto *out = c->start_embed (*this);
-    if (unlikely (!c->extend_min (out))) return_trace (false);
+    auto *s = c->serializer;
+    auto *out = s->start_embed (*this);
+    if (unlikely (!s->extend_min (out))) return_trace (false);
 
     out->secondGlyph = (*closure->glyph_map)[secondGlyph];
 
-    closure->valueFormats[0].serialize_copy (c, closure->base, &values[0], closure->layout_variation_idx_map);
-    closure->valueFormats[1].serialize_copy (c, closure->base, &values[closure->len1], closure->layout_variation_idx_map);
+    closure->valueFormats[0].copy_values (s,
+                                          closure->newFormats[0],
+                                          closure->base, &values[0],
+                                          closure->layout_variation_idx_map);
+    closure->valueFormats[1].copy_values (s,
+                                          closure->newFormats[1],
+                                          closure->base,
+                                          &values[closure->len1],
+                                          closure->layout_variation_idx_map);
 
     return_trace (true);
   }
@@ -1050,6 +1129,21 @@
       valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len));
   }
 
+  bool intersects (const hb_set_t& glyphset) const
+  {
+    return glyphset.has(secondGlyph);
+  }
+
+  const Value* get_values_1 () const
+  {
+    return &values[0];
+  }
+
+  const Value* get_values_2 (ValueFormat format1) const
+  {
+    return &values[format1.get_len ()];
+  }
+
   protected:
   HBGlyphID	secondGlyph;		/* GlyphID of second glyph in the
 					 * pair--first glyph is listed in the
@@ -1140,7 +1234,8 @@
   }
 
   bool subset (hb_subset_context_t *c,
-	       const ValueFormat valueFormats[2]) const
+	       const ValueFormat valueFormats[2],
+               const ValueFormat newFormats[2]) const
   {
     TRACE_SUBSET (this);
     auto snap = c->serializer->snapshot ();
@@ -1156,10 +1251,11 @@
     unsigned len2 = valueFormats[1].get_len ();
     unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
 
-    PairValueRecord::serialize_closure_t closure =
+    PairValueRecord::context_t context =
     {
       this,
       valueFormats,
+      newFormats,
       len1,
       &glyph_map,
       c->plan->layout_variation_idx_map
@@ -1170,7 +1266,7 @@
     for (unsigned i = 0; i < count; i++)
     {
       if (glyphset.has (record->secondGlyph)
-	 && record->serialize (c->serializer, &closure)) num++;
+	 && record->subset (c, &context)) num++;
       record = &StructAtOffset<const PairValueRecord> (record, record_size);
     }
 
@@ -1218,7 +1314,7 @@
     + hb_zip (this+coverage, pairSet)
     | hb_filter (*glyphs, hb_first)
     | hb_map (hb_second)
-    | hb_map ([glyphs, this] (const OffsetTo<PairSet> &_)
+    | hb_map ([glyphs, this] (const Offset16To<PairSet> &_)
 	      { return (this+_).intersects (glyphs, valueFormat); })
     | hb_any
     ;
@@ -1278,17 +1374,23 @@
     out->format = format;
     out->valueFormat[0] = valueFormat[0];
     out->valueFormat[1] = valueFormat[1];
+    if (c->plan->drop_hints)
+    {
+      hb_pair_t<unsigned, unsigned> newFormats = compute_effective_value_formats (glyphset);
+      out->valueFormat[0] = newFormats.first;
+      out->valueFormat[1] = newFormats.second;
+    }
 
     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>& _)
+    | hb_filter ([this, c, out] (const Offset16To<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, valueFormat);
+		   bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat);
 		   if (!ret)
 		   {
 		     out->pairSet.pop ();
@@ -1308,6 +1410,36 @@
     return_trace (bool (new_coverage));
   }
 
+
+  hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const
+  {
+    unsigned len1 = valueFormat[0].get_len ();
+    unsigned len2 = valueFormat[1].get_len ();
+    unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
+
+    unsigned format1 = 0;
+    unsigned format2 = 0;
+    for (const Offset16To<PairSet>& _ :
+             + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second))
+    {
+      const PairSet& set = (this + _);
+      const PairValueRecord *record = &set.firstPairValueRecord;
+
+      for (unsigned i = 0; i < set.len; i++)
+      {
+        if (record->intersects (glyphset))
+        {
+          format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 ());
+          format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]));
+        }
+        record = &StructAtOffset<const PairValueRecord> (record, record_size);
+      }
+    }
+
+    return hb_pair (format1, format2);
+  }
+
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -1328,7 +1460,7 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ValueFormat	valueFormat[2];		/* [0] Defines the types of data in
@@ -1337,7 +1469,7 @@
 					/* [1] Defines the types of data in
 					 * ValueRecord2--for the second glyph
 					 * in the pair--may be zero (0) */
-  OffsetArrayOf<PairSet>
+  Array16OfOffset16To<PairSet>
 		pairSet;		/* Array of PairSet tables
 					 * ordered by Coverage Index */
   public:
@@ -1355,18 +1487,35 @@
   void closure_lookups (hb_closure_lookups_context_t *c) const {}
   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
   {
+    if (!intersects (c->glyph_set)) return;
     if ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return;
 
+    hb_set_t klass1_glyphs, klass2_glyphs;
+    if (!(this+classDef1).collect_coverage (&klass1_glyphs)) return;
+    if (!(this+classDef2).collect_coverage (&klass2_glyphs)) return;
+
     hb_set_t class1_set, class2_set;
-    for (const unsigned cp : c->glyph_set->iter ())
+    for (const unsigned cp : + c->glyph_set->iter () | hb_filter (this + coverage))
     {
-      unsigned klass1 = (this+classDef1).get (cp);
+      if (!klass1_glyphs.has (cp)) class1_set.add (0);
+      else
+      {
+        unsigned klass1 = (this+classDef1).get (cp);
+        class1_set.add (klass1);
+      }
+    }
+
+    class2_set.add (0);
+    for (const unsigned cp : + c->glyph_set->iter () | hb_filter (klass2_glyphs))
+    {
       unsigned klass2 = (this+classDef2).get (cp);
-      class1_set.add (klass1);
       class2_set.add (klass2);
     }
 
-    if (class1_set.is_empty () || class2_set.is_empty ()) return;
+    if (class1_set.is_empty ()
+        || class2_set.is_empty ()
+        || (class2_set.get_population() == 1 && class2_set.has(0)))
+      return;
 
     unsigned len1 = valueFormat1.get_len ();
     unsigned len2 = valueFormat2.get_len ();
@@ -1431,36 +1580,35 @@
     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, &klass1_map);
+    out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, true, &(this + coverage));
     out->class1Count = klass1_map.get_population ();
 
     hb_map_t klass2_map;
-    out->classDef2.serialize_subset (c, classDef2, this, &klass2_map);
+    out->classDef2.serialize_subset (c, classDef2, this, &klass2_map, true, false);
     out->class2Count = klass2_map.get_population ();
 
     unsigned len1 = valueFormat1.get_len ();
     unsigned len2 = 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) * (len1 + len2);
-				valueFormat1.serialize_copy (c->serializer, this, &values[idx], c->plan->layout_variation_idx_map);
-				valueFormat2.serialize_copy (c->serializer, this, &values[idx + len1], c->plan->layout_variation_idx_map);
-			      })
-		  ;
-		})
-    ;
+    hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2);
+    if (c->plan->drop_hints)
+      newFormats = compute_effective_value_formats (klass1_map, klass2_map);
 
+    out->valueFormat1 = newFormats.first;
+    out->valueFormat2 = newFormats.second;
+
+    for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
+    {
+      for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
+      {
+        unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+        valueFormat1.copy_values (c->serializer, newFormats.first, this, &values[idx], c->plan->layout_variation_idx_map);
+        valueFormat2.copy_values (c->serializer, newFormats.second, this, &values[idx + len1], c->plan->layout_variation_idx_map);
+      }
+    }
+
     const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
     const hb_map_t &glyph_map = *c->plan->glyph_map;
 
@@ -1474,6 +1622,30 @@
     return_trace (out->class1Count && out->class2Count && bool (it));
   }
 
+
+  hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map,
+                                                                 const hb_map_t& klass2_map) const
+  {
+    unsigned len1 = valueFormat1.get_len ();
+    unsigned len2 = valueFormat2.get_len ();
+
+    unsigned format1 = 0;
+    unsigned format2 = 0;
+
+    for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
+    {
+      for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
+      {
+        unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+        format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
+        format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
+      }
+    }
+
+    return hb_pair (format1, format2);
+  }
+
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -1496,7 +1668,7 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 2 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
   ValueFormat	valueFormat1;		/* ValueRecord definition--for the
@@ -1505,11 +1677,11 @@
   ValueFormat	valueFormat2;		/* ValueRecord definition--for the
 					 * second glyph of the pair--may be
 					 * zero (0) */
-  OffsetTo<ClassDef>
+  Offset16To<ClassDef>
 		classDef1;		/* Offset to ClassDef table--from
 					 * beginning of PairPos subtable--for
 					 * the first glyph of the pair */
-  OffsetTo<ClassDef>
+  Offset16To<ClassDef>
 		classDef2;		/* Offset to ClassDef table--from
 					 * beginning of PairPos subtable--for
 					 * the second glyph of the pair */
@@ -1564,26 +1736,24 @@
     (src_base+exitAnchor).collect_variation_indices (c);
   }
 
-  EntryExitRecord* copy (hb_serialize_context_t *c,
-			 const void *src_base,
-			 const void *dst_base,
-			 const hb_map_t *layout_variation_idx_map) const
+  EntryExitRecord* subset (hb_subset_context_t *c,
+                           const void *src_base) const
   {
     TRACE_SERIALIZE (this);
-    auto *out = c->embed (this);
+    auto *out = c->serializer->embed (this);
     if (unlikely (!out)) return_trace (nullptr);
 
-    out->entryAnchor.serialize_copy (c, entryAnchor, src_base, c->to_bias (dst_base), hb_serialize_context_t::Head, layout_variation_idx_map);
-    out->exitAnchor.serialize_copy (c, exitAnchor, src_base, c->to_bias (dst_base), hb_serialize_context_t::Head, layout_variation_idx_map);
+    out->entryAnchor.serialize_subset (c, entryAnchor, src_base);
+    out->exitAnchor.serialize_subset (c, exitAnchor, src_base);
     return_trace (out);
   }
 
   protected:
-  OffsetTo<Anchor>
+  Offset16To<Anchor>
 		entryAnchor;		/* Offset to EntryAnchor table--from
 					 * beginning of CursivePos
 					 * subtable--may be NULL */
-  OffsetTo<Anchor>
+  Offset16To<Anchor>
 		exitAnchor;		/* Offset to ExitAnchor table--from
 					 * beginning of CursivePos
 					 * subtable--may be NULL */
@@ -1724,18 +1894,17 @@
 
   template <typename Iterator,
 	    hb_requires (hb_is_iterator (Iterator))>
-  void serialize (hb_serialize_context_t *c,
+  void serialize (hb_subset_context_t *c,
 		  Iterator it,
-		  const void *src_base,
-		  const hb_map_t *layout_variation_idx_map)
+		  const void *src_base)
   {
-    if (unlikely (!c->extend_min ((*this)))) return;
+    if (unlikely (!c->serializer->extend_min ((*this)))) return;
     this->format = 1;
     this->entryExitRecord.len = it.len ();
 
     for (const EntryExitRecord& entry_record : + it
 					       | hb_map (hb_second))
-      c->copy (entry_record, src_base, this, layout_variation_idx_map);
+      entry_record.subset (c, src_base);
 
     auto glyphs =
     + it
@@ -1742,7 +1911,7 @@
     | hb_map_retains_sorting (hb_first)
     ;
 
-    coverage.serialize (c, this).serialize (c, glyphs);
+    coverage.serialize (c->serializer, this).serialize (c->serializer, glyphs);
   }
 
   bool subset (hb_subset_context_t *c) const
@@ -1762,7 +1931,7 @@
     ;
 
     bool ret = bool (it);
-    out->serialize (c->serializer, it, this, c->plan->layout_variation_idx_map);
+    out->serialize (c, it, this);
     return_trace (ret);
   }
 
@@ -1774,10 +1943,10 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
-  ArrayOf<EntryExitRecord>
+  Array16Of<EntryExitRecord>
 		entryExitRecord;	/* Array of EntryExit records--in
 					 * Coverage Index order */
   public:
@@ -1953,9 +2122,9 @@
 			  .serialize (c->serializer, new_coverage.iter ()))
       return_trace (false);
 
-    out->markArray.serialize (c->serializer, out)
-		  .serialize (c->serializer, &klass_mapping, c->plan->layout_variation_idx_map, &(this+markArray), + mark_iter
-										                                   | hb_map (hb_second));
+    out->markArray.serialize_subset (c, markArray, this,
+                                     (this+markCoverage).iter (),
+                                     &klass_mapping);
 
     unsigned basecount = (this+baseArray).rows;
     auto base_iter =
@@ -1984,9 +2153,11 @@
       | hb_sink (base_indexes)
       ;
     }
-    out->baseArray.serialize (c->serializer, out)
-		  .serialize (c->serializer, base_iter.len (), &(this+baseArray), c->plan->layout_variation_idx_map, base_indexes.iter ());
 
+    out->baseArray.serialize_subset (c, baseArray, this,
+                                     base_iter.len (),
+                                     base_indexes.iter ());
+
     return_trace (true);
   }
 
@@ -2002,17 +2173,17 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		markCoverage;		/* Offset to MarkCoverage table--from
 					 * beginning of MarkBasePos subtable */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		baseCoverage;		/* Offset to BaseCoverage table--from
 					 * beginning of MarkBasePos subtable */
   HBUINT16	classCount;		/* Number of classes defined for marks */
-  OffsetTo<MarkArray>
+  Offset16To<MarkArray>
 		markArray;		/* Offset to MarkArray table--from
 					 * beginning of MarkBasePos subtable */
-  OffsetTo<BaseArray>
+  Offset16To<BaseArray>
 		baseArray;		/* Offset to BaseArray table--from
 					 * beginning of MarkBasePos subtable */
   public:
@@ -2046,12 +2217,12 @@
 					 * ordered by class--zero-based. */
 
 /* Array of LigatureAttach tables ordered by LigatureCoverage Index */
-struct LigatureArray : OffsetListOf<LigatureAttach>
+struct LigatureArray : List16OfOffset16To<LigatureAttach>
 {
   template <typename Iterator,
 	    hb_requires (hb_is_iterator (Iterator))>
   bool subset (hb_subset_context_t *c,
-	       Iterator		    coverage,
+               Iterator		    coverage,
 	       unsigned		    class_count,
 	       const hb_map_t	   *klass_mapping) const
   {
@@ -2067,11 +2238,16 @@
       auto *matrix = out->serialize_append (c->serializer);
       if (unlikely (!matrix)) return_trace (false);
 
+      const LigatureAttach& src = (this + _.second);
+      auto indexes =
+          + hb_range (src.rows * class_count)
+          | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
+          ;
       matrix->serialize_subset (c,
 				_.second,
 				this,
-				class_count,
-				klass_mapping);
+                                src.rows,
+                                indexes);
     }
     return_trace (this->len);
   }
@@ -2205,13 +2381,9 @@
 			  .serialize (c->serializer, new_mark_coverage))
       return_trace (false);
 
-    out->markArray.serialize (c->serializer, out)
-		  .serialize (c->serializer,
-                              &klass_mapping,
-                              c->plan->layout_variation_idx_map,
-                              &(this+markArray),
-                              + mark_iter
-                              | hb_map (hb_second));
+    out->markArray.serialize_subset (c, markArray, this,
+                                     (this+markCoverage).iter (),
+                                     &klass_mapping);
 
     auto new_ligature_coverage =
     + hb_iter (this + ligatureCoverage)
@@ -2241,18 +2413,18 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		markCoverage;		/* Offset to Mark Coverage table--from
 					 * beginning of MarkLigPos subtable */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		ligatureCoverage;	/* Offset to Ligature Coverage
 					 * table--from beginning of MarkLigPos
 					 * subtable */
   HBUINT16	classCount;		/* Number of defined mark classes */
-  OffsetTo<MarkArray>
+  Offset16To<MarkArray>
 		markArray;		/* Offset to MarkArray table--from
 					 * beginning of MarkLigPos subtable */
-  OffsetTo<LigatureArray>
+  Offset16To<LigatureArray>
 		ligatureArray;		/* Offset to LigatureArray table--from
 					 * beginning of MarkLigPos subtable */
   public:
@@ -2413,9 +2585,9 @@
 			   .serialize (c->serializer, new_coverage.iter ()))
       return_trace (false);
 
-    out->mark1Array.serialize (c->serializer, out)
-		   .serialize (c->serializer, &klass_mapping, c->plan->layout_variation_idx_map, &(this+mark1Array), + mark1_iter
-										                                     | hb_map (hb_second));
+    out->mark1Array.serialize_subset (c, mark1Array, this,
+                                      (this+mark1Coverage).iter (),
+                                      &klass_mapping);
 
     unsigned mark2count = (this+mark2Array).rows;
     auto mark2_iter =
@@ -2444,9 +2616,9 @@
       | hb_sink (mark2_indexes)
       ;
     }
-    out->mark2Array.serialize (c->serializer, out)
-		   .serialize (c->serializer, mark2_iter.len (), &(this+mark2Array), c->plan->layout_variation_idx_map, mark2_indexes.iter ());
 
+    out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ());
+
     return_trace (true);
   }
 
@@ -2462,19 +2634,19 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		mark1Coverage;		/* Offset to Combining Mark1 Coverage
 					 * table--from beginning of MarkMarkPos
 					 * subtable */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		mark2Coverage;		/* Offset to Combining Mark2 Coverage
 					 * table--from beginning of MarkMarkPos
 					 * subtable */
   HBUINT16	classCount;		/* Number of defined mark classes */
-  OffsetTo<MarkArray>
+  Offset16To<MarkArray>
 		mark1Array;		/* Offset to Mark1Array table--from
 					 * beginning of MarkMarkPos subtable */
-  OffsetTo<Mark2Array>
+  Offset16To<Mark2Array>
 		mark2Array;		/* Offset to Mark2Array table--from
 					 * beginning of MarkMarkPos subtable */
   public:
@@ -2663,7 +2835,7 @@
 
   bool subset (hb_subset_context_t *c) const
   {
-    hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_features);
+    hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features);
     return GSUBGPOS::subset<PosLookup> (&l);
   }
 

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -46,14 +46,19 @@
   bool intersects (const hb_set_t *glyphs) const
   { return (this+coverage).intersects (glyphs); }
 
+  bool may_have_non_1to1 () const
+  { return false; }
+
   void closure (hb_closure_context_t *c) const
   {
     unsigned d = deltaGlyphID;
+
     + hb_iter (this+coverage)
-    | hb_filter (*c->glyphs)
+    | hb_filter (c->parent_active_glyphs ())
     | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
     | hb_sink (c->output)
     ;
+
   }
 
   void closure_lookups (hb_closure_lookups_context_t *c) const {}
@@ -97,7 +102,7 @@
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
     if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
-    c->check_assign (deltaGlyphID, delta);
+    c->check_assign (deltaGlyphID, delta, HB_SERIALIZE_ERROR_INT_OVERFLOW);
     return_trace (true);
   }
 
@@ -133,7 +138,7 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
   HBUINT16	deltaGlyphID;		/* Add to original GlyphID to get
@@ -147,13 +152,17 @@
   bool intersects (const hb_set_t *glyphs) const
   { return (this+coverage).intersects (glyphs); }
 
+  bool may_have_non_1to1 () const
+  { return false; }
+
   void closure (hb_closure_context_t *c) const
   {
     + hb_zip (this+coverage, substitute)
-    | hb_filter (*c->glyphs, hb_first)
+    | hb_filter (c->parent_active_glyphs (), hb_first)
     | hb_map (hb_second)
     | hb_sink (c->output)
     ;
+
   }
 
   void closure_lookups (hb_closure_lookups_context_t *c) const {}
@@ -233,10 +242,10 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 2 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
-  ArrayOf<HBGlyphID>
+  Array16Of<HBGlyphID>
 		substitute;		/* Array of substitute
 					 * GlyphIDs--ordered by Coverage Index */
   public:
@@ -377,7 +386,7 @@
   }
 
   protected:
-  ArrayOf<HBGlyphID>
+  Array16Of<HBGlyphID>
 		substitute;		/* String of GlyphIDs to substitute */
   public:
   DEFINE_SIZE_ARRAY (2, substitute);
@@ -388,14 +397,18 @@
   bool intersects (const hb_set_t *glyphs) const
   { return (this+coverage).intersects (glyphs); }
 
+  bool may_have_non_1to1 () const
+  { return true; }
+
   void closure (hb_closure_context_t *c) const
   {
     + hb_zip (this+coverage, sequence)
-    | hb_filter (*c->glyphs, hb_first)
+    | hb_filter (c->parent_active_glyphs (), hb_first)
     | hb_map (hb_second)
     | hb_map (hb_add (this))
     | hb_apply ([c] (const Sequence &_) { _.closure (c); })
     ;
+
   }
 
   void closure_lookups (hb_closure_lookups_context_t *c) const {}
@@ -475,10 +488,10 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
-  OffsetArrayOf<Sequence>
+  Array16OfOffset16To<Sequence>
 		sequence;		/* Array of Sequence tables
 					 * ordered by Coverage Index */
   public:
@@ -603,7 +616,7 @@
   }
 
   protected:
-  ArrayOf<HBGlyphID>
+  Array16Of<HBGlyphID>
 		alternates;		/* Array of alternate GlyphIDs--in
 					 * arbitrary order */
   public:
@@ -615,14 +628,18 @@
   bool intersects (const hb_set_t *glyphs) const
   { return (this+coverage).intersects (glyphs); }
 
+  bool may_have_non_1to1 () const
+  { return false; }
+
   void closure (hb_closure_context_t *c) const
   {
     + hb_zip (this+coverage, alternateSet)
-    | hb_filter (c->glyphs, hb_first)
+    | hb_filter (c->parent_active_glyphs (), hb_first)
     | hb_map (hb_second)
     | hb_map (hb_add (this))
     | hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
     ;
+
   }
 
   void closure_lookups (hb_closure_lookups_context_t *c) const {}
@@ -710,10 +727,10 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
-  OffsetArrayOf<AlternateSet>
+  Array16OfOffset16To<AlternateSet>
 		alternateSet;		/* Array of AlternateSet tables
 					 * ordered by Coverage Index */
   public:
@@ -965,7 +982,7 @@
   }
 
   protected:
-  OffsetArrayOf<Ligature>
+  Array16OfOffset16To<Ligature>
 		ligature;		/* Array LigatureSet tables
 					 * ordered by preference */
   public:
@@ -980,20 +997,24 @@
     + hb_zip (this+coverage, ligatureSet)
     | hb_filter (*glyphs, hb_first)
     | hb_map (hb_second)
-    | hb_map ([this, glyphs] (const OffsetTo<LigatureSet> &_)
+    | hb_map ([this, glyphs] (const Offset16To<LigatureSet> &_)
 	      { return (this+_).intersects (glyphs); })
     | hb_any
     ;
   }
 
+  bool may_have_non_1to1 () const
+  { return true; }
+
   void closure (hb_closure_context_t *c) const
   {
     + hb_zip (this+coverage, ligatureSet)
-    | hb_filter (*c->glyphs, hb_first)
+    | hb_filter (c->parent_active_glyphs (), hb_first)
     | hb_map (hb_second)
     | hb_map (hb_add (this))
     | hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
     ;
+
   }
 
   void closure_lookups (hb_closure_lookups_context_t *c) const {}
@@ -1086,10 +1107,10 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
-  OffsetArrayOf<LigatureSet>
+  Array16OfOffset16To<LigatureSet>
 		ligatureSet;		/* Array LigatureSet tables
 					 * ordered by Coverage Index */
   public:
@@ -1157,7 +1178,7 @@
     if (!(this+coverage).intersects (glyphs))
       return false;
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
 
     unsigned int count;
 
@@ -1174,15 +1195,18 @@
     return true;
   }
 
+  bool may_have_non_1to1 () const
+  { return false; }
+
   void closure (hb_closure_context_t *c) const
   {
     if (!intersects (c->glyphs)) return;
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
-    const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+    const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
 
     + hb_zip (this+coverage, substitute)
-    | hb_filter (*c->glyphs, hb_first)
+    | hb_filter (c->parent_active_glyphs (), hb_first)
     | hb_map (hb_second)
     | hb_sink (c->output)
     ;
@@ -1200,12 +1224,12 @@
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return;
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
     count = lookahead.len;
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
 
-    const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
+    const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
     count = substitute.len;
     c->output->add_array (substitute.arrayZ, substitute.len);
   }
@@ -1224,8 +1248,8 @@
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
-    const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+    const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
 
     if (unlikely (index >= substitute.len)) return_trace (false);
 
@@ -1250,11 +1274,80 @@
     return_trace (false);
   }
 
+  template<typename Iterator,
+           hb_requires (hb_is_iterator (Iterator))>
+  bool serialize_coverage_offset_array (hb_subset_context_t *c, Iterator it) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> ();
+
+    if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
+      return_trace (false);
+
+    for (auto& offset : it) {
+      auto *o = out->serialize_append (c->serializer);
+      if (unlikely (!o) || !o->serialize_subset (c, offset, this))
+        return_trace (false);
+    }
+
+    return_trace (true);
+  }
+
+  template<typename Iterator, typename BacktrackIterator, typename LookaheadIterator,
+           hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_pair_t)),
+           hb_requires (hb_is_iterator (BacktrackIterator)),
+           hb_requires (hb_is_iterator (LookaheadIterator))>
+  bool serialize (hb_subset_context_t *c,
+                  Iterator coverage_subst_iter,
+                  BacktrackIterator backtrack_iter,
+                  LookaheadIterator lookahead_iter) const
+  {
+    TRACE_SERIALIZE (this);
+
+    auto *out = c->serializer->start_embed (this);
+    if (unlikely (!c->serializer->check_success (out))) return_trace (false);
+    if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
+    if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false);
+
+    if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false);
+    if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false);
+
+    auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID>> ();
+    auto substitutes =
+    + coverage_subst_iter
+    | hb_map (hb_second)
+    ;
+
+    auto glyphs =
+    + coverage_subst_iter
+    | hb_map_retains_sorting (hb_first)
+    ;
+    if (unlikely (! c->serializer->check_success (substitute_out->serialize (c->serializer, substitutes))))
+        return_trace (false);
+
+    if (unlikely (!out->coverage.serialize (c->serializer, out).serialize (c->serializer, glyphs)))
+      return_trace (false);
+    return_trace (true);
+  }
+
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+    const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
+
+    auto it =
+    + hb_zip (this+coverage, substitute)
+    | hb_filter (glyphset, hb_first)
+    | hb_filter (glyphset, hb_second)
+    | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID &> p) -> hb_codepoint_pair_t
+                              { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
+    ;
+
+    return_trace (bool (it) && serialize (c, it, backtrack.iter (), lookahead.iter ()));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -1262,27 +1355,27 @@
     TRACE_SANITIZE (this);
     if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
       return_trace (false);
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
     if (!lookahead.sanitize (c, this))
       return_trace (false);
-    const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
+    const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
     return_trace (substitute.sanitize (c));
   }
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
-  OffsetArrayOf<Coverage>
+  Array16OfOffset16To<Coverage>
 		backtrack;		/* Array of coverage tables
 					 * in backtracking sequence, in glyph
 					 * sequence order */
-  OffsetArrayOf<Coverage>
+  Array16OfOffset16To<Coverage>
 		lookaheadX;		/* Array of coverage tables
 					 * in lookahead sequence, in glyph
 					 * sequence order */
-  ArrayOf<HBGlyphID>
+  Array16Of<HBGlyphID>
 		substituteX;		/* Array of substitute
 					 * GlyphIDs--ordered by Coverage Index */
   public:
@@ -1388,6 +1481,12 @@
     return lookup_type_is_reverse (type);
   }
 
+  bool may_have_non_1to1 () const
+  {
+    hb_have_non_1to1_context_t c;
+    return dispatch (&c);
+  }
+
   bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
@@ -1522,12 +1621,14 @@
   template <typename context_t>
   static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
 
-  static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index)
+  static inline typename hb_closure_context_t::return_t closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index);
+
+  static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
   {
     if (!c->should_visit_lookup (lookup_index))
       return hb_empty_t ();
 
-    hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index);
+    hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, covered_seq_indices, seq_index, end_index);
 
     /* While in theory we should flush here, it will cause timeouts because a recursive
      * lookup can keep growing the glyph set.  Skip, and outer loop will retry up to
@@ -1564,7 +1665,7 @@
 
   bool subset (hb_subset_context_t *c) const
   {
-    hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_features);
+    hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features);
     return GSUBGPOS::subset<SubstLookup> (&l);
   }
 
@@ -1600,6 +1701,14 @@
   return l.dispatch (c);
 }
 
+/*static*/ typename hb_closure_context_t::return_t SubstLookup::closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
+{
+  const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
+  if (l.may_have_non_1to1 ())
+      hb_set_add_range (covered_seq_indices, seq_index, end_index);
+  return l.dispatch (c);
+}
+
 /*static*/ inline hb_closure_lookups_context_t::return_t SubstLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
 {
   const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (this_index);

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -52,23 +52,32 @@
   const hb_set_t *glyphs;
 
   hb_intersects_context_t (const hb_set_t *glyphs_) :
-			     glyphs (glyphs_) {}
+                            glyphs (glyphs_) {}
 };
 
+struct hb_have_non_1to1_context_t :
+       hb_dispatch_context_t<hb_have_non_1to1_context_t, bool>
+{
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.may_have_non_1to1 (); }
+  static return_t default_return_value () { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+};
+
 struct hb_closure_context_t :
        hb_dispatch_context_t<hb_closure_context_t>
 {
-  typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
+  typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indicies, unsigned seq_index, unsigned end_index);
   template <typename T>
   return_t dispatch (const T &obj) { obj.closure (this); return hb_empty_t (); }
   static return_t default_return_value () { return hb_empty_t (); }
-  void recurse (unsigned int lookup_index)
+  void recurse (unsigned lookup_index, hb_set_t *covered_seq_indicies, unsigned seq_index, unsigned end_index)
   {
     if (unlikely (nesting_level_left == 0 || !recurse_func))
       return;
 
     nesting_level_left--;
-    recurse_func (this, lookup_index);
+    recurse_func (this, lookup_index, covered_seq_indicies, seq_index, end_index);
     nesting_level_left++;
   }
 
@@ -83,36 +92,90 @@
     if (is_lookup_done (lookup_index))
       return false;
 
-    done_lookups->set (lookup_index, glyphs->get_population ());
     return true;
   }
 
   bool is_lookup_done (unsigned int lookup_index)
   {
-    if (unlikely (done_lookups->in_error ()))
+    if (done_lookups_glyph_count->in_error () ||
+        done_lookups_glyph_set->in_error ())
       return true;
 
     /* Have we visited this lookup with the current set of glyphs? */
-    return done_lookups->get (lookup_index) == glyphs->get_population ();
+    if (done_lookups_glyph_count->get (lookup_index) != glyphs->get_population ())
+    {
+      done_lookups_glyph_count->set (lookup_index, glyphs->get_population ());
+
+      if (!done_lookups_glyph_set->get (lookup_index))
+      {
+	hb_set_t* empty_set = hb_set_create ();
+	if (unlikely (!done_lookups_glyph_set->set (lookup_index, empty_set)))
+	{
+	  hb_set_destroy (empty_set);
+	  return true;
+	}
+      }
+
+      hb_set_clear (done_lookups_glyph_set->get (lookup_index));
+    }
+
+    hb_set_t *covered_glyph_set = done_lookups_glyph_set->get (lookup_index);
+    if (unlikely (covered_glyph_set->in_error ()))
+      return true;
+    if (parent_active_glyphs ()->is_subset (covered_glyph_set))
+      return true;
+
+    hb_set_union (covered_glyph_set, parent_active_glyphs ());
+    return false;
   }
 
+  hb_set_t* parent_active_glyphs ()
+  {
+    if (active_glyphs_stack.length < 1)
+      return glyphs;
+
+    return active_glyphs_stack.tail ();
+  }
+
+  void push_cur_active_glyphs (hb_set_t* cur_active_glyph_set)
+  {
+    active_glyphs_stack.push (cur_active_glyph_set);
+  }
+
+  bool pop_cur_done_glyphs ()
+  {
+    if (active_glyphs_stack.length < 1)
+      return false;
+
+    active_glyphs_stack.pop ();
+    return true;
+  }
+
   hb_face_t *face;
   hb_set_t *glyphs;
+  hb_set_t *cur_intersected_glyphs;
   hb_set_t output[1];
+  hb_vector_t<hb_set_t *> active_glyphs_stack;
   recurse_func_t recurse_func;
   unsigned int nesting_level_left;
 
   hb_closure_context_t (hb_face_t *face_,
 			hb_set_t *glyphs_,
-			hb_map_t *done_lookups_,
+			hb_set_t *cur_intersected_glyphs_,
+			hb_map_t *done_lookups_glyph_count_,
+			hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *done_lookups_glyph_set_,
 			unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
 			  face (face_),
 			  glyphs (glyphs_),
+			  cur_intersected_glyphs (cur_intersected_glyphs_),
 			  recurse_func (nullptr),
 			  nesting_level_left (nesting_level_left_),
-			  done_lookups (done_lookups_),
+			  done_lookups_glyph_count (done_lookups_glyph_count_),
+			  done_lookups_glyph_set (done_lookups_glyph_set_),
 			  lookup_count (0)
-  {}
+  {
+    push_cur_active_glyphs (glyphs_);
+  }
 
   ~hb_closure_context_t () { flush (); }
 
@@ -123,13 +186,18 @@
     hb_set_del_range (output, face->get_num_glyphs (), hb_set_get_max (output));	/* Remove invalid glyphs. */
     hb_set_union (glyphs, output);
     hb_set_clear (output);
+    active_glyphs_stack.pop ();
+    active_glyphs_stack.fini ();
   }
 
   private:
-  hb_map_t *done_lookups;
+  hb_map_t *done_lookups_glyph_count;
+  hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *done_lookups_glyph_set;
   unsigned int lookup_count;
 };
 
+
+
 struct hb_closure_lookups_context_t :
        hb_dispatch_context_t<hb_closure_lookups_context_t>
 {
@@ -737,6 +805,7 @@
 
 
 typedef bool (*intersects_func_t) (const hb_set_t *glyphs, const HBUINT16 &value, const void *data);
+typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs);
 typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
 typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
 
@@ -743,6 +812,7 @@
 struct ContextClosureFuncs
 {
   intersects_func_t intersects;
+  intersected_glyphs_func_t intersected_glyphs;
 };
 struct ContextCollectGlyphsFuncs
 {
@@ -765,10 +835,29 @@
 }
 static inline bool intersects_coverage (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
 {
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
+  const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value;
   return (data+coverage).intersects (glyphs);
 }
 
+
+static inline void intersected_glyph (const hb_set_t *glyphs HB_UNUSED, const void *data, unsigned value, hb_set_t *intersected_glyphs)
+{
+  unsigned g = reinterpret_cast<const HBUINT16 *>(data)[value];
+  intersected_glyphs->add (g);
+}
+static inline void intersected_class_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs)
+{
+  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+  class_def.intersected_class_glyphs (glyphs, value, intersected_glyphs);
+}
+static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs)
+{
+  Offset16To<Coverage> coverage;
+  coverage = value;
+  (data+coverage).intersected_coverage_glyphs (glyphs, intersected_glyphs);
+}
+
+
 static inline bool array_is_subset_of (const hb_set_t *glyphs,
 				       unsigned int count,
 				       const HBUINT16 values[],
@@ -792,7 +881,7 @@
 }
 static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
 {
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
+  const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value;
   (data+coverage).collect_coverage (glyphs);
 }
 static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
@@ -820,7 +909,7 @@
 }
 static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
 {
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
+  const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value;
   return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
 }
 
@@ -1146,10 +1235,79 @@
   DEFINE_SIZE_STATIC (4);
 };
 
+enum ContextFormat { SimpleContext = 1, ClassBasedContext = 2, CoverageBasedContext = 3 };
+
+static void context_closure_recurse_lookups (hb_closure_context_t *c,
+					     unsigned inputCount, const HBUINT16 input[],
+					     unsigned lookupCount,
+					     const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */,
+					     unsigned value,
+					     ContextFormat context_format,
+					     const void *data,
+					     intersected_glyphs_func_t intersected_glyphs_func)
+{
+  hb_set_t *covered_seq_indicies = hb_set_create ();
+  for (unsigned int i = 0; i < lookupCount; i++)
+  {
+    unsigned seqIndex = lookupRecord[i].sequenceIndex;
+    if (seqIndex >= inputCount) continue;
+
+    hb_set_t *pos_glyphs = nullptr;
+
+    if (hb_set_is_empty (covered_seq_indicies) || !hb_set_has (covered_seq_indicies, seqIndex))
+    {
+      pos_glyphs = hb_set_create ();
+      if (seqIndex == 0)
+      {
+        switch (context_format) {
+        case ContextFormat::SimpleContext:
+          pos_glyphs->add (value);
+          break;
+        case ContextFormat::ClassBasedContext:
+          intersected_glyphs_func (c->cur_intersected_glyphs, data, value, pos_glyphs);
+          break;
+        case ContextFormat::CoverageBasedContext:
+          hb_set_set (pos_glyphs, c->cur_intersected_glyphs);
+          break;
+        }
+      }
+      else
+      {
+        const void *input_data = input;
+        unsigned input_value = seqIndex - 1;
+        if (context_format != ContextFormat::SimpleContext)
+        {
+          input_data = data;
+          input_value = input[seqIndex - 1];
+        }
+
+        intersected_glyphs_func (c->glyphs, input_data, input_value, pos_glyphs);
+      }
+    }
+
+    hb_set_add (covered_seq_indicies, seqIndex);
+    if (pos_glyphs)
+      c->push_cur_active_glyphs (pos_glyphs);
+
+    unsigned endIndex = inputCount;
+    if (context_format == ContextFormat::CoverageBasedContext)
+      endIndex += 1;
+
+    c->recurse (lookupRecord[i].lookupListIndex, covered_seq_indicies, seqIndex, endIndex);
+
+    if (pos_glyphs) {
+      c->pop_cur_done_glyphs ();
+      hb_set_destroy (pos_glyphs);
+    }
+  }
+
+  hb_set_destroy (covered_seq_indicies);
+}
+
 template <typename context_t>
 static inline void recurse_lookups (context_t *c,
-				    unsigned int lookupCount,
-				    const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
+                                    unsigned int lookupCount,
+                                    const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
 {
   for (unsigned int i = 0; i < lookupCount; i++)
     c->recurse (lookupRecord[i].lookupListIndex);
@@ -1284,6 +1442,7 @@
 struct ContextClosureLookupContext
 {
   ContextClosureFuncs funcs;
+  ContextFormat context_format;
   const void *intersects_data;
 };
 
@@ -1314,13 +1473,19 @@
 					   const HBUINT16 input[], /* Array of input values--start with second glyph */
 					   unsigned int lookupCount,
 					   const LookupRecord lookupRecord[],
+					   unsigned value, /* Index of first glyph in Coverage or Class value in ClassDef table */
 					   ContextClosureLookupContext &lookup_context)
 {
   if (context_intersects (c->glyphs,
 			  inputCount, input,
 			  lookup_context))
-    recurse_lookups (c,
-		     lookupCount, lookupRecord);
+    context_closure_recurse_lookups (c,
+				     inputCount, input,
+				     lookupCount, lookupRecord,
+				     value,
+				     lookup_context.context_format,
+				     lookup_context.intersects_data,
+				     lookup_context.funcs.intersected_glyphs);
 }
 
 static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
@@ -1377,7 +1542,7 @@
 			       lookup_context);
   }
 
-  void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
+  void closure (hb_closure_context_t *c, unsigned value, ContextClosureLookupContext &lookup_context) const
   {
     if (unlikely (c->lookup_limit_exceeded ())) return;
 
@@ -1386,7 +1551,7 @@
     context_closure_lookup (c,
 			    inputCount, inputZ.arrayZ,
 			    lookupCount, lookupRecord.arrayZ,
-			    lookup_context);
+			    value, lookup_context);
   }
 
   void closure_lookups (hb_closure_lookups_context_t *c,
@@ -1511,7 +1676,7 @@
     ;
   }
 
-  void closure (hb_closure_context_t *c,
+  void closure (hb_closure_context_t *c, unsigned value,
 		ContextClosureLookupContext &lookup_context) const
   {
     if (unlikely (c->lookup_limit_exceeded ())) return;
@@ -1519,7 +1684,7 @@
     return
     + hb_iter (rule)
     | hb_map (hb_add (this))
-    | hb_apply ([&] (const Rule &_) { _.closure (c, lookup_context); })
+    | hb_apply ([&] (const Rule &_) { _.closure (c, value, lookup_context); })
     ;
   }
 
@@ -1577,7 +1742,7 @@
     auto *out = c->serializer->start_embed (*this);
     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
 
-    for (const OffsetTo<Rule>& _ : rule)
+    for (const Offset16To<Rule>& _ : rule)
     {
       if (!_) continue;
       auto *o = out->rule.serialize_append (c->serializer);
@@ -1604,7 +1769,7 @@
   }
 
   protected:
-  OffsetArrayOf<Rule>
+  Array16OfOffset16To<Rule>
 		rule;			/* Array of Rule tables
 					 * ordered by preference */
   public:
@@ -1617,7 +1782,8 @@
   bool intersects (const hb_set_t *glyphs) const
   {
     struct ContextClosureLookupContext lookup_context = {
-      {intersects_glyph},
+      {intersects_glyph, intersected_glyph},
+      ContextFormat::SimpleContext,
       nullptr
     };
 
@@ -1631,18 +1797,24 @@
     ;
   }
 
+  bool may_have_non_1to1 () const
+  { return true; }
+
   void closure (hb_closure_context_t *c) const
   {
+    c->cur_intersected_glyphs->clear ();
+    get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
+
     struct ContextClosureLookupContext lookup_context = {
-      {intersects_glyph},
+      {intersects_glyph, intersected_glyph},
+      ContextFormat::SimpleContext,
       nullptr
     };
 
-    + hb_zip (this+coverage, ruleSet)
-    | hb_filter (*c->glyphs, hb_first)
-    | hb_map (hb_second)
-    | hb_map (hb_add (this))
-    | hb_apply ([&] (const RuleSet &_) { _.closure (c, lookup_context); })
+    + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len))
+    | hb_filter (c->parent_active_glyphs (), hb_first)
+    | hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const RuleSet&> (_.first, this+ruleSet[_.second]); })
+    | hb_apply ([&] (const hb_pair_t<unsigned, const RuleSet&>& _) { _.second.closure (c, _.first, lookup_context); })
     ;
   }
 
@@ -1649,7 +1821,8 @@
   void closure_lookups (hb_closure_lookups_context_t *c) const
   {
     struct ContextClosureLookupContext lookup_context = {
-      {intersects_glyph},
+      {intersects_glyph, intersected_glyph},
+      ContextFormat::SimpleContext,
       nullptr
     };
 
@@ -1738,10 +1911,10 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
-  OffsetArrayOf<RuleSet>
+  Array16OfOffset16To<RuleSet>
 		ruleSet;		/* Array of RuleSet tables
 					 * ordered by Coverage Index */
   public:
@@ -1759,7 +1932,8 @@
     const ClassDef &class_def = this+classDef;
 
     struct ContextClosureLookupContext lookup_context = {
-      {intersects_class},
+      {intersects_class, intersected_class_glyphs},
+      ContextFormat::ClassBasedContext,
       &class_def
     };
 
@@ -1774,15 +1948,22 @@
     ;
   }
 
+  bool may_have_non_1to1 () const
+  { return true; }
+
   void closure (hb_closure_context_t *c) const
   {
     if (!(this+coverage).intersects (c->glyphs))
       return;
 
+    c->cur_intersected_glyphs->clear ();
+    get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
+
     const ClassDef &class_def = this+classDef;
 
     struct ContextClosureLookupContext lookup_context = {
-      {intersects_class},
+      {intersects_class, intersected_class_glyphs},
+      ContextFormat::ClassBasedContext,
       &class_def
     };
 
@@ -1789,11 +1970,13 @@
     return
     + hb_enumerate (ruleSet)
     | hb_filter ([&] (unsigned _)
-		 { return class_def.intersects_class (c->glyphs, _); },
+		 { return class_def.intersects_class (c->cur_intersected_glyphs, _); },
 		 hb_first)
-    | hb_map (hb_second)
-    | hb_map (hb_add (this))
-    | hb_apply ([&] (const RuleSet &_) { _.closure (c, lookup_context); })
+    | hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<RuleSet>&> _)
+                {
+                  const RuleSet& rule_set = this+_.second;
+                  rule_set.closure (c, _.first, lookup_context);
+                })
     ;
   }
 
@@ -1805,7 +1988,8 @@
     const ClassDef &class_def = this+classDef;
 
     struct ContextClosureLookupContext lookup_context = {
-      {intersects_class},
+      {intersects_class, intersected_class_glyphs},
+      ContextFormat::ClassBasedContext,
       &class_def
     };
 
@@ -1919,13 +2103,13 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 2 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
-  OffsetTo<ClassDef>
+  Offset16To<ClassDef>
 		classDef;		/* Offset to glyph ClassDef table--from
 					 * beginning of table */
-  OffsetArrayOf<RuleSet>
+  Array16OfOffset16To<RuleSet>
 		ruleSet;		/* Array of RuleSet tables
 					 * ordered by class */
   public:
@@ -1941,7 +2125,8 @@
       return false;
 
     struct ContextClosureLookupContext lookup_context = {
-      {intersects_coverage},
+      {intersects_coverage, intersected_coverage_glyphs},
+      ContextFormat::CoverageBasedContext,
       this
     };
     return context_intersects (glyphs,
@@ -1949,20 +2134,27 @@
 			       lookup_context);
   }
 
+  bool may_have_non_1to1 () const
+  { return true; }
+
   void closure (hb_closure_context_t *c) const
   {
     if (!(this+coverageZ[0]).intersects (c->glyphs))
       return;
 
+    c->cur_intersected_glyphs->clear ();
+    get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
+
     const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
     struct ContextClosureLookupContext lookup_context = {
-      {intersects_coverage},
+      {intersects_coverage, intersected_coverage_glyphs},
+      ContextFormat::CoverageBasedContext,
       this
     };
     context_closure_lookup (c,
 			    glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
 			    lookupCount, lookupRecord,
-			    lookup_context);
+			    0, lookup_context);
   }
 
   void closure_lookups (hb_closure_lookups_context_t *c) const
@@ -2032,10 +2224,10 @@
 
     auto coverages = coverageZ.as_array (glyphCount);
 
-    for (const OffsetTo<Coverage>& offset : coverages)
+    for (const Offset16To<Coverage>& offset : coverages)
     {
       /* TODO(subset) This looks like should not be necessary to write this way. */
-      auto *o = c->serializer->allocate_size<OffsetTo<Coverage>> (OffsetTo<Coverage>::static_size);
+      auto *o = c->serializer->allocate_size<Offset16To<Coverage>> (Offset16To<Coverage>::static_size);
       if (unlikely (!o)) return_trace (false);
       if (!o->serialize_subset (c, offset, this)) return_trace (false);
     }
@@ -2066,7 +2258,7 @@
   HBUINT16	glyphCount;		/* Number of glyphs in the input glyph
 					 * sequence */
   HBUINT16	lookupCount;		/* Number of LookupRecords */
-  UnsizedArrayOf<OffsetTo<Coverage>>
+  UnsizedArrayOf<Offset16To<Coverage>>
 		coverageZ;		/* Array of offsets to Coverage
 					 * table in glyph sequence order */
 /*UnsizedArrayOf<LookupRecord>
@@ -2106,6 +2298,7 @@
 struct ChainContextClosureLookupContext
 {
   ContextClosureFuncs funcs;
+  ContextFormat context_format;
   const void *intersects_data[3];
 };
 
@@ -2150,6 +2343,7 @@
 						 const HBUINT16 lookahead[],
 						 unsigned int lookupCount,
 						 const LookupRecord lookupRecord[],
+						 unsigned value,
 						 ChainContextClosureLookupContext &lookup_context)
 {
   if (chain_context_intersects (c->glyphs,
@@ -2157,8 +2351,13 @@
 				inputCount, input,
 				lookaheadCount, lookahead,
 				lookup_context))
-    recurse_lookups (c,
-		     lookupCount, lookupRecord);
+    context_closure_recurse_lookups (c,
+		     inputCount, input,
+		     lookupCount, lookupRecord,
+		     value,
+		     lookup_context.context_format,
+		     lookup_context.intersects_data[1],
+		     lookup_context.funcs.intersected_glyphs);
 }
 
 static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
@@ -2239,7 +2438,7 @@
   bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
   {
     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
+    const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
     return chain_context_intersects (glyphs,
 				     backtrack.len, backtrack.arrayZ,
 				     input.lenP1, input.arrayZ,
@@ -2247,19 +2446,20 @@
 				     lookup_context);
   }
 
-  void closure (hb_closure_context_t *c,
+  void closure (hb_closure_context_t *c, unsigned value,
 		ChainContextClosureLookupContext &lookup_context) const
   {
     if (unlikely (c->lookup_limit_exceeded ())) return;
 
     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+    const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
     chain_context_closure_lookup (c,
 				  backtrack.len, backtrack.arrayZ,
 				  input.lenP1, input.arrayZ,
 				  lookahead.len, lookahead.arrayZ,
 				  lookup.len, lookup.arrayZ,
+				  value,
 				  lookup_context);
   }
 
@@ -2270,8 +2470,8 @@
     if (!intersects (c->glyphs, lookup_context)) return;
 
     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+    const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
     recurse_lookups (c, lookup.len, lookup.arrayZ);
   }
 
@@ -2279,8 +2479,8 @@
 		       ChainContextCollectGlyphsLookupContext &lookup_context) const
   {
     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+    const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
     chain_context_collect_glyphs_lookup (c,
 					 backtrack.len, backtrack.arrayZ,
 					 input.lenP1, input.arrayZ,
@@ -2293,8 +2493,8 @@
 		    ChainContextApplyLookupContext &lookup_context) const
   {
     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+    const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
     return chain_context_would_apply_lookup (c,
 					     backtrack.len, backtrack.arrayZ,
 					     input.lenP1, input.arrayZ,
@@ -2306,8 +2506,8 @@
   {
     TRACE_APPLY (this);
     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+    const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
     return_trace (chain_context_apply_lookup (c,
 					      backtrack.len, backtrack.arrayZ,
 					      input.lenP1, input.arrayZ,
@@ -2345,12 +2545,12 @@
     serialize_array (c, input.lenP1, + input.iter ()
 				     | hb_map (mapping));
 
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
+    const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
     if (lookahead_map) mapping = lookahead_map;
     serialize_array (c, lookahead.len, + lookahead.iter ()
 				       | hb_map (mapping));
 
-    const ArrayOf<LookupRecord> &lookupRecord = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead);
 
     HBUINT16* lookupCount = c->embed (&(lookupRecord.len));
     if (!lookupCount) return_trace (nullptr);
@@ -2377,7 +2577,7 @@
     TRACE_SUBSET (this);
 
     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
+    const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
 
     if (!backtrack_map)
     {
@@ -2408,14 +2608,14 @@
     if (!backtrack.sanitize (c)) return_trace (false);
     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
     if (!input.sanitize (c)) return_trace (false);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
+    const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
     if (!lookahead.sanitize (c)) return_trace (false);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
     return_trace (lookup.sanitize (c));
   }
 
   protected:
-  ArrayOf<HBUINT16>
+  Array16Of<HBUINT16>
 		backtrack;		/* Array of backtracking values
 					 * (to be matched before the input
 					 * sequence) */
@@ -2422,10 +2622,10 @@
   HeadlessArrayOf<HBUINT16>
 		inputX;			/* Array of input values (start with
 					 * second glyph) */
-  ArrayOf<HBUINT16>
+  Array16Of<HBUINT16>
 		lookaheadX;		/* Array of lookahead values's (to be
 					 * matched after the input sequence) */
-  ArrayOf<LookupRecord>
+  Array16Of<LookupRecord>
 		lookupX;		/* Array of LookupRecords--in
 					 * design order) */
   public:
@@ -2443,7 +2643,7 @@
     | hb_any
     ;
   }
-  void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
+  void closure (hb_closure_context_t *c, unsigned value, ChainContextClosureLookupContext &lookup_context) const
   {
     if (unlikely (c->lookup_limit_exceeded ())) return;
 
@@ -2450,7 +2650,7 @@
     return
     + hb_iter (rule)
     | hb_map (hb_add (this))
-    | hb_apply ([&] (const ChainRule &_) { _.closure (c, lookup_context); })
+    | hb_apply ([&] (const ChainRule &_) { _.closure (c, value, lookup_context); })
     ;
   }
 
@@ -2508,7 +2708,7 @@
     auto *out = c->serializer->start_embed (*this);
     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
 
-    for (const OffsetTo<ChainRule>& _ : rule)
+    for (const Offset16To<ChainRule>& _ : rule)
     {
       if (!_) continue;
       auto *o = out->rule.serialize_append (c->serializer);
@@ -2539,7 +2739,7 @@
   }
 
   protected:
-  OffsetArrayOf<ChainRule>
+  Array16OfOffset16To<ChainRule>
 		rule;			/* Array of ChainRule tables
 					 * ordered by preference */
   public:
@@ -2551,7 +2751,8 @@
   bool intersects (const hb_set_t *glyphs) const
   {
     struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_glyph},
+      {intersects_glyph, intersected_glyph},
+      ContextFormat::SimpleContext,
       {nullptr, nullptr, nullptr}
     };
 
@@ -2565,18 +2766,24 @@
     ;
   }
 
+  bool may_have_non_1to1 () const
+  { return true; }
+
   void closure (hb_closure_context_t *c) const
   {
+    c->cur_intersected_glyphs->clear ();
+    get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
+
     struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_glyph},
+      {intersects_glyph, intersected_glyph},
+      ContextFormat::SimpleContext,
       {nullptr, nullptr, nullptr}
     };
 
-    + hb_zip (this+coverage, ruleSet)
-    | hb_filter (*c->glyphs, hb_first)
-    | hb_map (hb_second)
-    | hb_map (hb_add (this))
-    | hb_apply ([&] (const ChainRuleSet &_) { _.closure (c, lookup_context); })
+    + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len))
+    | hb_filter (c->parent_active_glyphs (), hb_first)
+    | hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const ChainRuleSet&> (_.first, this+ruleSet[_.second]); })
+    | hb_apply ([&] (const hb_pair_t<unsigned, const ChainRuleSet&>& _) { _.second.closure (c, _.first, lookup_context); })
     ;
   }
 
@@ -2583,7 +2790,8 @@
   void closure_lookups (hb_closure_lookups_context_t *c) const
   {
     struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_glyph},
+      {intersects_glyph, intersected_glyph},
+      ContextFormat::SimpleContext,
       {nullptr, nullptr, nullptr}
     };
 
@@ -2671,10 +2879,10 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
-  OffsetArrayOf<ChainRuleSet>
+  Array16OfOffset16To<ChainRuleSet>
 		ruleSet;		/* Array of ChainRuleSet tables
 					 * ordered by Coverage Index */
   public:
@@ -2693,7 +2901,8 @@
     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
 
     struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_class},
+      {intersects_class, intersected_class_glyphs},
+      ContextFormat::ClassBasedContext,
       {&backtrack_class_def,
        &input_class_def,
        &lookahead_class_def}
@@ -2709,17 +2918,25 @@
     | hb_any
     ;
   }
+
+  bool may_have_non_1to1 () const
+  { return true; }
+
   void closure (hb_closure_context_t *c) const
   {
     if (!(this+coverage).intersects (c->glyphs))
       return;
 
+    c->cur_intersected_glyphs->clear ();
+    get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
+
     const ClassDef &backtrack_class_def = this+backtrackClassDef;
     const ClassDef &input_class_def = this+inputClassDef;
     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
 
     struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_class},
+      {intersects_class, intersected_class_glyphs},
+      ContextFormat::ClassBasedContext,
       {&backtrack_class_def,
        &input_class_def,
        &lookahead_class_def}
@@ -2728,11 +2945,13 @@
     return
     + hb_enumerate (ruleSet)
     | hb_filter ([&] (unsigned _)
-		 { return input_class_def.intersects_class (c->glyphs, _); },
+		 { return input_class_def.intersects_class (c->cur_intersected_glyphs, _); },
 		 hb_first)
-    | hb_map (hb_second)
-    | hb_map (hb_add (this))
-    | hb_apply ([&] (const ChainRuleSet &_) { _.closure (c, lookup_context); })
+    | hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<ChainRuleSet>&> _)
+                {
+                  const ChainRuleSet& chainrule_set = this+_.second;
+                  chainrule_set.closure (c, _.first, lookup_context);
+                })
     ;
   }
 
@@ -2746,7 +2965,8 @@
     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
 
     struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_class},
+      {intersects_class, intersected_class_glyphs},
+      ContextFormat::ClassBasedContext,
       {&backtrack_class_def,
        &input_class_def,
        &lookahead_class_def}
@@ -2852,7 +3072,7 @@
     bool ret = true;
     const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
     auto last_non_zero = c->serializer->snapshot ();
-    for (const OffsetTo<ChainRuleSet>& _ : + hb_enumerate (ruleSet)
+    for (const Offset16To<ChainRuleSet>& _ : + hb_enumerate (ruleSet)
 					   | hb_filter (input_klass_map, hb_first)
 					   | hb_map (hb_second))
     {
@@ -2898,22 +3118,22 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 2 */
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
-  OffsetTo<ClassDef>
+  Offset16To<ClassDef>
 		backtrackClassDef;	/* Offset to glyph ClassDef table
 					 * containing backtrack sequence
 					 * data--from beginning of table */
-  OffsetTo<ClassDef>
+  Offset16To<ClassDef>
 		inputClassDef;		/* Offset to glyph ClassDef
 					 * table containing input sequence
 					 * data--from beginning of table */
-  OffsetTo<ClassDef>
+  Offset16To<ClassDef>
 		lookaheadClassDef;	/* Offset to glyph ClassDef table
 					 * containing lookahead sequence
 					 * data--from beginning of table */
-  OffsetArrayOf<ChainRuleSet>
+  Array16OfOffset16To<ChainRuleSet>
 		ruleSet;		/* Array of ChainRuleSet tables
 					 * ordered by class */
   public:
@@ -2924,14 +3144,15 @@
 {
   bool intersects (const hb_set_t *glyphs) const
   {
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
 
     if (!(this+input[0]).intersects (glyphs))
       return false;
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
     struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_coverage},
+      {intersects_coverage, intersected_coverage_glyphs},
+      ContextFormat::CoverageBasedContext,
       {this, this, this}
     };
     return chain_context_intersects (glyphs,
@@ -2941,17 +3162,24 @@
 				     lookup_context);
   }
 
+  bool may_have_non_1to1 () const
+  { return true; }
+
   void closure (hb_closure_context_t *c) const
   {
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
 
     if (!(this+input[0]).intersects (c->glyphs))
       return;
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    c->cur_intersected_glyphs->clear ();
+    get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
+
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
+    const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
     struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_coverage},
+      {intersects_coverage, intersected_coverage_glyphs},
+      ContextFormat::CoverageBasedContext,
       {this, this, this}
     };
     chain_context_closure_lookup (c,
@@ -2959,7 +3187,7 @@
 				  input.len, (const HBUINT16 *) input.arrayZ + 1,
 				  lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
 				  lookup.len, lookup.arrayZ,
-				  lookup_context);
+				  0, lookup_context);
   }
 
   void closure_lookups (hb_closure_lookups_context_t *c) const
@@ -2967,9 +3195,9 @@
     if (!intersects (c->glyphs))
       return;
 
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
+    const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
     recurse_lookups (c, lookup.len, lookup.arrayZ);
   }
 
@@ -2977,12 +3205,12 @@
 
   void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
 
     (this+input[0]).collect_coverage (c->input);
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
+    const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
     struct ChainContextCollectGlyphsLookupContext lookup_context = {
       {collect_coverage},
       {this, this, this}
@@ -2997,9 +3225,9 @@
 
   bool would_apply (hb_would_apply_context_t *c) const
   {
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
+    const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
     struct ChainContextApplyLookupContext lookup_context = {
       {match_coverage},
       {this, this, this}
@@ -3013,7 +3241,7 @@
 
   const Coverage &get_coverage () const
   {
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
     return this+input[0];
   }
 
@@ -3020,13 +3248,13 @@
   bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
 
     unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
+    const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
     struct ChainContextApplyLookupContext lookup_context = {
       {match_coverage},
       {this, this, this}
@@ -3043,7 +3271,7 @@
   bool serialize_coverage_offsets (hb_subset_context_t *c, Iterator it, const void* base) const
   {
     TRACE_SERIALIZE (this);
-    auto *out = c->serializer->start_embed<OffsetArrayOf<Coverage>> ();
+    auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> ();
 
     if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
       return_trace (false);
@@ -3068,15 +3296,15 @@
     if (!serialize_coverage_offsets (c, backtrack.iter (), this))
       return_trace (false);
 
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
     if (!serialize_coverage_offsets (c, input.iter (), this))
       return_trace (false);
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
     if (!serialize_coverage_offsets (c, lookahead.iter (), this))
       return_trace (false);
 
-    const ArrayOf<LookupRecord> &lookupRecord = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead);
     HBUINT16 lookupCount;
     lookupCount = lookupRecord.len;
     if (!c->serializer->copy (lookupCount)) return_trace (false);
@@ -3092,30 +3320,30 @@
   {
     TRACE_SANITIZE (this);
     if (!backtrack.sanitize (c, this)) return_trace (false);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
     if (!input.sanitize (c, this)) return_trace (false);
     if (!input.len) return_trace (false); /* To be consistent with Context. */
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
+    const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
     if (!lookahead.sanitize (c, this)) return_trace (false);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
     return_trace (lookup.sanitize (c));
   }
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 3 */
-  OffsetArrayOf<Coverage>
+  Array16OfOffset16To<Coverage>
 		backtrack;		/* Array of coverage tables
 					 * in backtracking sequence, in  glyph
 					 * sequence order */
-  OffsetArrayOf<Coverage>
+  Array16OfOffset16To<Coverage>
 		inputX		;	/* Array of coverage
 					 * tables in input sequence, in glyph
 					 * sequence order */
-  OffsetArrayOf<Coverage>
+  Array16OfOffset16To<Coverage>
 		lookaheadX;		/* Array of coverage tables
 					 * in lookahead sequence, in glyph
 					 * sequence order */
-  ArrayOf<LookupRecord>
+  Array16Of<LookupRecord>
 		lookupX;		/* Array of LookupRecords--in
 					 * design order) */
   public:
@@ -3154,7 +3382,7 @@
 
   template <typename X>
   const X& get_subtable () const
-  { return this + reinterpret_cast<const LOffsetTo<typename T::SubTable> &> (extensionOffset); }
+  { return this + reinterpret_cast<const Offset32To<typename T::SubTable> &> (extensionOffset); }
 
   template <typename context_t, typename ...Ts>
   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
@@ -3186,9 +3414,9 @@
     out->extensionLookupType = extensionLookupType;
 
     const auto& src_offset =
-        reinterpret_cast<const LOffsetTo<typename T::SubTable> &> (extensionOffset);
+        reinterpret_cast<const Offset32To<typename T::SubTable> &> (extensionOffset);
     auto& dest_offset =
-        reinterpret_cast<LOffsetTo<typename T::SubTable> &> (out->extensionOffset);
+        reinterpret_cast<Offset32To<typename T::SubTable> &> (out->extensionOffset);
 
     return_trace (dest_offset.serialize_subset (c, src_offset, this, get_type ()));
   }
@@ -3372,6 +3600,20 @@
     hb_set_subtract (lookup_indexes, &inactive_lookups);
   }
 
+  void prune_langsys (const hb_map_t *duplicate_feature_map,
+                      hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map,
+                      hb_set_t       *new_feature_indexes /* OUT */) const
+  {
+    hb_prune_langsys_context_t c (this, script_langsys_map, duplicate_feature_map, new_feature_indexes);
+
+    unsigned count = get_script_count ();
+    for (unsigned script_index = 0; script_index < count; script_index++)
+    {
+      const Script& s = get_script (script_index);
+      s.prune_langsys (&c, script_index);
+    }
+  }
+
   template <typename TLookup>
   bool subset (hb_subset_layout_context_t *c) const
   {
@@ -3380,15 +3622,15 @@
     if (unlikely (!out)) return_trace (false);
 
     typedef LookupOffsetList<TLookup> TLookupList;
-    reinterpret_cast<OffsetTo<TLookupList> &> (out->lookupList)
+    reinterpret_cast<Offset16To<TLookupList> &> (out->lookupList)
 	.serialize_subset (c->subset_context,
-			   reinterpret_cast<const OffsetTo<TLookupList> &> (lookupList),
+			   reinterpret_cast<const Offset16To<TLookupList> &> (lookupList),
 			   this,
 			   c);
 
-    reinterpret_cast<OffsetTo<RecordListOfFeature> &> (out->featureList)
+    reinterpret_cast<Offset16To<RecordListOfFeature> &> (out->featureList)
 	.serialize_subset (c->subset_context,
-			   reinterpret_cast<const OffsetTo<RecordListOfFeature> &> (featureList),
+			   reinterpret_cast<const Offset16To<RecordListOfFeature> &> (featureList),
 			   this,
 			   c);
 
@@ -3412,8 +3654,65 @@
     return_trace (true);
   }
 
+  void find_duplicate_features (const hb_map_t *lookup_indices,
+                                const hb_set_t *feature_indices,
+                                hb_map_t *duplicate_feature_map /* OUT */) const
+  {
+    //find out duplicate features after subset
+    unsigned prev = 0xFFFFu;
+    for (unsigned i : feature_indices->iter ())
+    {
+      if (prev == 0xFFFFu)
+      {
+        duplicate_feature_map->set (i, i);
+        prev = i;
+        continue;
+      }
+
+      hb_tag_t t = get_feature_tag (i);
+      hb_tag_t prev_t = get_feature_tag (prev);
+      if (t != prev_t)
+      {
+        duplicate_feature_map->set (i, i);
+        prev = i;
+        continue;
+      }
+
+      const Feature& f = get_feature (i);
+      const Feature& prev_f = get_feature (prev);
+
+      auto f_iter =
+      + hb_iter (f.lookupIndex)
+      | hb_filter (lookup_indices)
+      ;
+
+      auto prev_iter =
+      + hb_iter (prev_f.lookupIndex)
+      | hb_filter (lookup_indices)
+      ;
+
+      if (f_iter.len () != prev_iter.len ())
+      {
+        duplicate_feature_map->set (i, i);
+        prev = i;
+        continue;
+      }
+
+      bool is_equal = true;
+      for (auto _ : + hb_zip (f_iter, prev_iter))
+        if (_.first != _.second) { is_equal = false; break; }
+
+      if (is_equal == true) duplicate_feature_map->set (i, prev);
+      else
+      {
+        duplicate_feature_map->set (i, i);
+        prev = i;
+      }
+    }
+  }
+
   void prune_features (const hb_map_t *lookup_indices, /* IN */
-                       hb_set_t       *feature_indices /* IN/OUT */) const
+		       hb_set_t       *feature_indices /* IN/OUT */) const
   {
 #ifndef HB_NO_VAR
     // This is the set of feature indices which have alternate versions defined
@@ -3431,6 +3730,13 @@
     for (unsigned i : feature_indices->iter())
     {
       const Feature& f = get_feature (i);
+      hb_tag_t tag =  get_feature_tag (i);
+      if (tag == HB_TAG ('p', 'r', 'e', 'f'))
+        // Note: Never ever drop feature 'pref', even if it's empty.
+        // HarfBuzz chooses shaper for Khmer based on presence of this
+        // feature.	See thread at:
+	// http://lists.freedesktop.org/archives/harfbuzz/2012-November/002660.html
+        continue;
 
       if (f.featureParams.is_null ()
 	  && !f.intersects_lookup_indexes (lookup_indices)
@@ -3452,12 +3758,12 @@
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    typedef OffsetListOf<TLookup> TLookupList;
+    typedef List16OfOffset16To<TLookup> TLookupList;
     if (unlikely (!(version.sanitize (c) &&
 		    likely (version.major == 1) &&
 		    scriptList.sanitize (c, this) &&
 		    featureList.sanitize (c, this) &&
-		    reinterpret_cast<const OffsetTo<TLookupList> &> (lookupList).sanitize (c, this))))
+		    reinterpret_cast<const Offset16To<TLookupList> &> (lookupList).sanitize (c, this))))
       return_trace (false);
 
 #ifndef HB_NO_VAR
@@ -3510,13 +3816,13 @@
   protected:
   FixedVersion<>version;	/* Version of the GSUB/GPOS table--initially set
 				 * to 0x00010000u */
-  OffsetTo<ScriptList>
+  Offset16To<ScriptList>
 		scriptList;	/* ScriptList table */
-  OffsetTo<FeatureList>
+  Offset16To<FeatureList>
 		featureList;	/* FeatureList table */
-  OffsetTo<LookupList>
+  Offset16To<LookupList>
 		lookupList;	/* LookupList table */
-  LOffsetTo<FeatureVariations>
+  Offset32To<FeatureVariations>
 		featureVars;	/* Offset to Feature Variations
 				   table--from beginning of table
 				 * (may be NULL).  Introduced

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-jstf-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-jstf-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-jstf-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -45,7 +45,7 @@
  * JstfMax -- Justification Maximum Table
  */
 
-typedef OffsetListOf<PosLookup> JstfMax;
+typedef List16OfOffset16To<PosLookup> JstfMax;
 
 
 /*
@@ -71,43 +71,43 @@
   }
 
   protected:
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		shrinkageEnableGSUB;	/* Offset to Shrinkage Enable GSUB
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		shrinkageDisableGSUB;	/* Offset to Shrinkage Disable GSUB
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		shrinkageEnableGPOS;	/* Offset to Shrinkage Enable GPOS
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		shrinkageDisableGPOS;	/* Offset to Shrinkage Disable GPOS
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfMax>
+  Offset16To<JstfMax>
 		shrinkageJstfMax;	/* Offset to Shrinkage JstfMax table--
 					 * from beginning of JstfPriority table
 					 * --may be NULL */
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		extensionEnableGSUB;	/* Offset to Extension Enable GSUB
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		extensionDisableGSUB;	/* Offset to Extension Disable GSUB
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		extensionEnableGPOS;	/* Offset to Extension Enable GPOS
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
+  Offset16To<JstfModList>
 		extensionDisableGPOS;	/* Offset to Extension Disable GPOS
 					 * JstfModList table--from beginning of
 					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfMax>
+  Offset16To<JstfMax>
 		extensionJstfMax;	/* Offset to Extension JstfMax table--
 					 * from beginning of JstfPriority table
 					 * --may be NULL */
@@ -121,13 +121,13 @@
  * JstfLangSys -- Justification Language System Table
  */
 
-struct JstfLangSys : OffsetListOf<JstfPriority>
+struct JstfLangSys : List16OfOffset16To<JstfPriority>
 {
   bool sanitize (hb_sanitize_context_t *c,
 		 const Record_sanitize_closure_t * = nullptr) const
   {
     TRACE_SANITIZE (this);
-    return_trace (OffsetListOf<JstfPriority>::sanitize (c));
+    return_trace (List16OfOffset16To<JstfPriority>::sanitize (c));
   }
 };
 
@@ -136,7 +136,7 @@
  * ExtenderGlyphs -- Extender Glyph Table
  */
 
-typedef SortedArrayOf<HBGlyphID> ExtenderGlyphs;
+typedef SortedArray16Of<HBGlyphID> ExtenderGlyphs;
 
 
 /*
@@ -174,10 +174,10 @@
   }
 
   protected:
-  OffsetTo<ExtenderGlyphs>
+  Offset16To<ExtenderGlyphs>
 		extenderGlyphs;	/* Offset to ExtenderGlyph table--from beginning
 				 * of JstfScript table-may be NULL */
-  OffsetTo<JstfLangSys>
+  Offset16To<JstfLangSys>
 		defaultLangSys;	/* Offset to DefaultJstfLangSys table--from
 				 * beginning of JstfScript table--may be Null */
   RecordArrayOf<JstfLangSys>

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc	2021-05-05 22:28:05 UTC (rev 59092)
@@ -331,6 +331,8 @@
  *
  * Useful if the client program wishes to cache the list.
  *
+ * Return value: Total number of attachment points for @glyph.
+ *
  **/
 unsigned int
 hb_ot_layout_get_attach_points (hb_face_t      *face,
@@ -357,6 +359,8 @@
  * Fetches a list of the caret positions defined for a ligature glyph in the GDEF
  * table of the font. The list returned will begin at the offset provided.
  *
+ * Return value: Total number of ligature caret positions for @glyph.
+ *
  **/
 unsigned int
 hb_ot_layout_get_ligature_carets (hb_font_t      *font,
@@ -419,6 +423,8 @@
  * Fetches a list of all scripts enumerated in the specified face's GSUB table
  * or GPOS table. The list returned will begin at the offset provided.
  *
+ * Return value: Total number of script tags.
+ *
  **/
 unsigned int
 hb_ot_layout_table_get_script_tags (hb_face_t    *face,
@@ -585,6 +591,8 @@
  *
  * Fetches a list of all feature tags in the given face's GSUB or GPOS table.
  *
+ * Return value: Total number of feature tags.
+ *
  **/
 unsigned int
 hb_ot_layout_table_get_feature_tags (hb_face_t    *face,
@@ -647,6 +655,8 @@
  * Fetches a list of language tags in the given face's GSUB or GPOS table, underneath
  * the specified script index. The list returned will begin at the offset provided.
  *
+ * Return value: Total number of language tags.
+ *
  **/
 unsigned int
 hb_ot_layout_script_get_language_tags (hb_face_t    *face,
@@ -818,6 +828,8 @@
  * Fetches a list of all features in the specified face's GSUB table
  * or GPOS table, underneath the specified script and language. The list
  * returned will begin at the offset provided.
+ *
+ * Return value: Total number of features.
  **/
 unsigned int
 hb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
@@ -850,6 +862,7 @@
  * or GPOS table, underneath the specified script and language. The list
  * returned will begin at the offset provided.
  *
+ * Return value: Total number of feature tags.
  **/
 unsigned int
 hb_ot_layout_language_get_feature_tags (hb_face_t    *face,
@@ -932,6 +945,8 @@
  * the specified face's GSUB table or GPOS table. The list returned will
  * begin at the offset provided.
  *
+ * Return value: Total number of lookups.
+ *
  * Since: 0.9.7
  **/
 unsigned int
@@ -960,6 +975,8 @@
  * Fetches the total number of lookups enumerated in the specified
  * face's GSUB table or GPOS table.
  *
+ * Return value: Total number of lookups.
+ *
  * Since: 0.9.22
  **/
 unsigned int
@@ -1262,6 +1279,8 @@
  * Fetches a list of feature variations in the specified face's GSUB table
  * or GPOS table, at the specified variation coordinates.
  *
+ * Return value: %true if feature variations were found, %false otherwise.
+ *
  **/
 hb_bool_t
 hb_ot_layout_table_find_feature_variations (hb_face_t    *face,
@@ -1291,6 +1310,8 @@
  * the specified face's GSUB table or GPOS table, enabled at the specified
  * variations index. The list returned will begin at the offset provided.
  *
+ * Return value: Total number of lookups.
+ *
  **/
 unsigned int
 hb_ot_layout_feature_with_variations_get_lookups (hb_face_t    *face,
@@ -1443,12 +1464,17 @@
 					unsigned int  lookup_index,
 					hb_set_t     *glyphs /* OUT */)
 {
-  hb_map_t done_lookups;
-  OT::hb_closure_context_t c (face, glyphs, &done_lookups);
+  hb_set_t cur_intersected_glyphs;
+  hb_map_t done_lookups_glyph_count;
+  hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> done_lookups_glyph_set;
+  OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
 
   const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
 
   l.closure (&c, lookup_index);
+
+  for (auto _ : done_lookups_glyph_set.iter ())
+    hb_set_destroy (_.second);
 }
 
 /**
@@ -1467,8 +1493,10 @@
 					 const hb_set_t *lookups,
 					 hb_set_t       *glyphs /* OUT */)
 {
-  hb_map_t done_lookups;
-  OT::hb_closure_context_t c (face, glyphs, &done_lookups);
+  hb_set_t cur_intersected_glyphs;
+  hb_map_t done_lookups_glyph_count;
+  hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> done_lookups_glyph_set;
+  OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
   const OT::GSUB& gsub = *face->table.GSUB->table;
 
   unsigned int iteration_count = 0;
@@ -1488,6 +1516,9 @@
     }
   } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
 	   glyphs_length != glyphs->get_population ());
+
+  for (auto _ : done_lookups_glyph_set.iter ())
+    hb_set_destroy (_.second);
 }
 
 /*
@@ -1925,7 +1956,7 @@
  *
  * Fetches a baseline value from the face.
  *
- * Return value: if found baseline value in the font.
+ * Return value: %true if found baseline value in the font.
  *
  * Since: 2.6.0
  **/
@@ -1984,7 +2015,7 @@
  *
  * Fetches alternates of a glyph from a given GSUB lookup index.
  *
- * Return value: total number of alternates found in the specific lookup index for the given glyph id.
+ * Return value: Total number of alternates found in the specific lookup index for the given glyph id.
  *
  * Since: 2.6.8
  **/

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -314,7 +314,6 @@
 	 hb_unicode_funcs_t::NOT_SPACE;
 }
 
-static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
 static inline bool _hb_glyph_info_substituted (const hb_glyph_info_t *info);
 
 static inline bool
@@ -328,7 +327,7 @@
 {
   return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
 	  == UPROPS_MASK_IGNORABLE) &&
-	 !_hb_glyph_info_ligated (info);
+	 !_hb_glyph_info_substituted (info);
 }
 static inline void
 _hb_glyph_info_unhide (hb_glyph_info_t *info)

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -49,7 +49,7 @@
 
   protected:
   HBINT16		value;		/* The X or Y value in design units */
-  OffsetTo<Device>	deviceTable;	/* Offset to the device table - from the
+  Offset16To<Device>	deviceTable;	/* Offset to the device table - from the
 					 * beginning of parent table.  May be NULL.
 					 * Suggested format for device table is 1. */
 
@@ -181,11 +181,11 @@
   }
 
   protected:
-  OffsetTo<Coverage>       coverage;		/* Offset to Coverage table -
+  Offset16To<Coverage>       coverage;		/* Offset to Coverage table -
 						 * from the beginning of
 						 * MathItalicsCorrectionInfo
 						 * table. */
-  ArrayOf<MathValueRecord> italicsCorrection;	/* Array of MathValueRecords
+  Array16Of<MathValueRecord> italicsCorrection;	/* Array of MathValueRecords
 						 * defining italics correction
 						 * values for each
 						 * covered glyph. */
@@ -214,11 +214,11 @@
   }
 
   protected:
-  OffsetTo<Coverage>       topAccentCoverage;   /* Offset to Coverage table -
+  Offset16To<Coverage>       topAccentCoverage;   /* Offset to Coverage table -
 						 * from the beginning of
 						 * MathTopAccentAttachment
 						 * table. */
-  ArrayOf<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords
+  Array16Of<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords
 						 * defining top accent
 						 * attachment points for each
 						 * covered glyph. */
@@ -320,7 +320,7 @@
   protected:
   /* Offset to MathKern table for each corner -
    * from the beginning of MathKernInfo table.  May be NULL. */
-  OffsetTo<MathKern> mathKern[4];
+  Offset16To<MathKern> mathKern[4];
 
   public:
   DEFINE_SIZE_STATIC (8);
@@ -346,12 +346,12 @@
   }
 
   protected:
-  OffsetTo<Coverage>
+  Offset16To<Coverage>
 		mathKernCoverage;
 				/* Offset to Coverage table -
 				 * from the beginning of the
 				 * MathKernInfo table. */
-  ArrayOf<MathKernInfoRecord>
+  Array16Of<MathKernInfoRecord>
 		mathKernInfoRecords;
 				/* Array of MathKernInfoRecords,
 				 * per-glyph information for
@@ -395,11 +395,11 @@
   protected:
   /* Offset to MathItalicsCorrectionInfo table -
    * from the beginning of MathGlyphInfo table. */
-  OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
+  Offset16To<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
 
   /* Offset to MathTopAccentAttachment table -
    * from the beginning of MathGlyphInfo table. */
-  OffsetTo<MathTopAccentAttachment> mathTopAccentAttachment;
+  Offset16To<MathTopAccentAttachment> mathTopAccentAttachment;
 
   /* Offset to coverage table for Extended Shape glyphs -
    * from the beginning of MathGlyphInfo table. When the left or right glyph of
@@ -406,11 +406,11 @@
    * a box is an extended shape variant, the (ink) box (and not the default
    * position defined by values in MathConstants table) should be used for
    * vertical positioning purposes.  May be NULL.. */
-  OffsetTo<Coverage> extendedShapeCoverage;
+  Offset16To<Coverage> extendedShapeCoverage;
 
    /* Offset to MathKernInfo table -
     * from the beginning of MathGlyphInfo table. */
-  OffsetTo<MathKernInfo> mathKernInfo;
+  Offset16To<MathKernInfo> mathKernInfo;
 
   public:
   DEFINE_SIZE_STATIC (8);
@@ -532,7 +532,7 @@
 				/* Italics correction of this
 				 * MathGlyphAssembly. Should not
 				 * depend on the assembly size. */
-  ArrayOf<MathGlyphPartRecord>
+  Array16Of<MathGlyphPartRecord>
 		partRecords;	/* Array of part records, from
 				 * left to right and bottom to
 				 * top. */
@@ -572,10 +572,10 @@
   protected:
   /* Offset to MathGlyphAssembly table for this shape - from the beginning of
      MathGlyphConstruction table.  May be NULL. */
-  OffsetTo<MathGlyphAssembly>	  glyphAssembly;
+  Offset16To<MathGlyphAssembly>	  glyphAssembly;
 
   /* MathGlyphVariantRecords for alternative variants of the glyphs. */
-  ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord;
+  Array16Of<MathGlyphVariantRecord> mathGlyphVariantRecord;
 
   public:
   DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord);
@@ -636,7 +636,7 @@
   {
     bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
     unsigned int count = vertical ? vertGlyphCount : horizGlyphCount;
-    const OffsetTo<Coverage> &coverage = vertical ? vertGlyphCoverage
+    const Offset16To<Coverage> &coverage = vertical ? vertGlyphCoverage
 						  : horizGlyphCoverage;
 
     unsigned int index = (this+coverage).get_coverage (glyph);
@@ -653,11 +653,11 @@
 				/* Minimum overlap of connecting
 				 * glyphs during glyph construction,
 				 * in design units. */
-  OffsetTo<Coverage> vertGlyphCoverage;
+  Offset16To<Coverage> vertGlyphCoverage;
 				/* Offset to Coverage table -
 				 * from the beginning of MathVariants
 				 * table. */
-  OffsetTo<Coverage> horizGlyphCoverage;
+  Offset16To<Coverage> horizGlyphCoverage;
 				/* Offset to Coverage table -
 				 * from the beginning of MathVariants
 				 * table. */
@@ -671,7 +671,7 @@
   /* Array of offsets to MathGlyphConstruction tables - from the beginning of
      the MathVariants table, for shapes growing in vertical/horizontal
      direction. */
-  UnsizedArrayOf<OffsetTo<MathGlyphConstruction>>
+  UnsizedArrayOf<Offset16To<MathGlyphConstruction>>
 			glyphConstruction;
 
   public:
@@ -711,11 +711,11 @@
   protected:
   FixedVersion<>version;	/* Version of the MATH table
 				 * initially set to 0x00010000u */
-  OffsetTo<MathConstants>
+  Offset16To<MathConstants>
 		mathConstants;	/* MathConstants table */
-  OffsetTo<MathGlyphInfo>
+  Offset16To<MathGlyphInfo>
 		mathGlyphInfo;	/* MathGlyphInfo table */
-  OffsetTo<MathVariants>
+  Offset16To<MathVariants>
 		mathVariants;	/* MathVariants table */
 
   public:

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-meta-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-meta-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-meta-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -56,7 +56,7 @@
 
   protected:
   Tag		tag;		/* A tag indicating the type of metadata. */
-  LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
+  NNOffset32To<UnsizedArrayOf<HBUINT8>>
 		dataZ;		/* Offset in bytes from the beginning of the
 				 * metadata table to the data for this tag. */
   HBUINT32	dataLength;	/* Length of the data. The data is not required to
@@ -113,7 +113,7 @@
 				 * Offset from the beginning of the table to the data.
 				 * Per OT specification:
 				 * Reserved. Not used; should be set to 0. */
-  LArrayOf<DataMap>
+  Array32Of<DataMap>
 		dataMaps;/* Array of data map records. */
   public:
   DEFINE_SIZE_ARRAY (16, dataMaps);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -149,7 +149,7 @@
   HBUINT16	languageID;	/* Language ID. */
   HBUINT16	nameID;		/* Name ID. */
   HBUINT16	length;		/* String length (in bytes). */
-  NNOffsetTo<UnsizedArrayOf<HBUINT8>>
+  NNOffset16To<UnsizedArrayOf<HBUINT8>>
 		offset;		/* String offset from start of storage area (in bytes). */
   public:
   DEFINE_SIZE_STATIC (12);
@@ -230,8 +230,9 @@
     c->copy_all (records, src_string_pool);
     free (records.arrayZ);
 
-    if (unlikely (c->ran_out_of_room)) return_trace (false);
 
+    if (unlikely (c->ran_out_of_room ())) return_trace (false);
+
     this->stringOffset = c->length ();
 
     return_trace (true);
@@ -357,7 +358,7 @@
   /* We only implement format 0 for now. */
   HBUINT16	format;		/* Format selector (=0/1). */
   HBUINT16	count;		/* Number of name records. */
-  NNOffsetTo<UnsizedArrayOf<HBUINT8>>
+  NNOffset16To<UnsizedArrayOf<HBUINT8>>
 		stringOffset;	/* Offset to start of string storage (from start of table). */
   UnsizedArrayOf<NameRecord>
 		nameRecordZ;	/* The name records where count is the number of records. */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -56,7 +56,7 @@
   }
 
   protected:
-  ArrayOf<HBUINT16>	glyphNameIndex;	/* This is not an offset, but is the
+  Array16Of<HBUINT16>	glyphNameIndex;	/* This is not an offset, but is the
 					 * ordinal number of the glyph in 'post'
 					 * string tables. */
 /*UnsizedArrayOf<HBUINT8>
@@ -236,7 +236,7 @@
 
     private:
     uint32_t version;
-    const ArrayOf<HBUINT16> *glyphNameIndex;
+    const Array16Of<HBUINT16> *glyphNameIndex;
     hb_vector_t<uint32_t> index_to_offset;
     const uint8_t *pool;
     hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic-fallback.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -208,11 +208,11 @@
 {
   public:
   OT::Tag tag;
-  OT::OffsetTo<OT::SubstLookup> lookupOffset;
+  OT::Offset16To<OT::SubstLookup> lookupOffset;
   public:
   DEFINE_SIZE_STATIC (6);
 };
-typedef OT::ArrayOf<ManifestLookup> Manifest;
+typedef OT::Array16Of<ManifestLookup> Manifest;
 
 static bool
 arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUSED,

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc	2021-05-05 22:28:05 UTC (rev 59092)
@@ -92,7 +92,7 @@
     case HB_MODIFIED_COMBINING_CLASS_CCC15: /* tsere */
     case HB_MODIFIED_COMBINING_CLASS_CCC16: /* segol */
     case HB_MODIFIED_COMBINING_CLASS_CCC17: /* patah */
-    case HB_MODIFIED_COMBINING_CLASS_CCC18: /* qamats */
+    case HB_MODIFIED_COMBINING_CLASS_CCC18: /* qamats & qamats qatan */
     case HB_MODIFIED_COMBINING_CLASS_CCC20: /* qubuts */
     case HB_MODIFIED_COMBINING_CLASS_CCC22: /* meteg */
       return HB_UNICODE_COMBINING_CLASS_BELOW;
@@ -104,7 +104,7 @@
       return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
 
     case HB_MODIFIED_COMBINING_CLASS_CCC25: /* sin dot */
-    case HB_MODIFIED_COMBINING_CLASS_CCC19: /* holam */
+    case HB_MODIFIED_COMBINING_CLASS_CCC19: /* holam & holam haser for vav */
       return HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT;
 
     case HB_MODIFIED_COMBINING_CLASS_CCC26: /* point varika */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -297,7 +297,7 @@
     unsigned int axis_index;
     if (!get_design_axes ().lfind (tag, &axis_index)) return false;
 
-    hb_array_t<const OffsetTo<AxisValue>> axis_values = get_axis_value_offsets ();
+    hb_array_t<const Offset16To<AxisValue>> axis_values = get_axis_value_offsets ();
     for (unsigned int i = 0; i < axis_values.length; i++)
     {
       const AxisValue& axis_value = this+axis_values[i];
@@ -359,7 +359,7 @@
   hb_array_t<const StatAxisRecord> const get_design_axes () const
   { return (this+designAxesOffset).as_array (designAxisCount); }
 
-  hb_array_t<const OffsetTo<AxisValue>> const get_axis_value_offsets () const
+  hb_array_t<const Offset16To<AxisValue>> const get_axis_value_offsets () const
   { return (this+offsetToAxisValueOffsets).as_array (axisValueCount); }
 
 
@@ -373,7 +373,7 @@
 				 * in the 'fvar' table. In all fonts, must
 				 * be greater than zero if axisValueCount
 				 * is greater than zero. */
-  LNNOffsetTo<UnsizedArrayOf<StatAxisRecord>>
+  NNOffset32To<UnsizedArrayOf<StatAxisRecord>>
 		designAxesOffset;
 				/* Offset in bytes from the beginning of
 				 * the STAT table to the start of the design
@@ -381,7 +381,7 @@
 				 * set to zero; if designAxisCount is greater
 				 * than zero, must be greater than zero. */
   HBUINT16	axisValueCount;	/* The number of axis value tables. */
-  LNNOffsetTo<UnsizedArrayOf<OffsetTo<AxisValue>>>
+  NNOffset32To<UnsizedArrayOf<Offset16To<AxisValue>>>
 		offsetToAxisValueOffsets;
 				/* Offset in bytes from the beginning of
 				 * the STAT table to the start of the design

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-avar-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-avar-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-avar-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -58,7 +58,7 @@
   DEFINE_SIZE_STATIC (4);
 };
 
-struct SegmentMaps : ArrayOf<AxisValueMap>
+struct SegmentMaps : Array16Of<AxisValueMap>
 {
   int map (int value, unsigned int from_offset = 0, unsigned int to_offset = 1) const
   {

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -303,7 +303,7 @@
   protected:
   FixedVersion<>version;	/* Version of the fvar table
 				 * initially set to 0x00010000u */
-  OffsetTo<AxisRecord>
+  Offset16To<AxisRecord>
 		firstAxis;	/* Offset in bytes from the beginning of the table
 				 * to the start of the AxisRecord array. */
   HBUINT16	reserved;	/* This field is permanently reserved. Set to 2. */

Modified: 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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -374,7 +374,7 @@
 				 * low 12 bits are the number of tuple variation tables
 				 * for this glyph. The number of tuple variation tables
 				 * can be any number between 1 and 4095. */
-  OffsetTo<HBUINT8>
+  Offset16To<HBUINT8>
 		data;		/* Offset from the start of the GlyphVariationData table
 				 * to the serialized data. */
   /* TupleVariationHeader tupleVariationHeaders[] *//* Array of tuple variation headers. */
@@ -676,7 +676,7 @@
 				 * can be referenced within glyph variation data tables for
 				 * multiple glyphs, as opposed to other tuple records stored
 				 * directly within a glyph variation data table. */
-  LNNOffsetTo<UnsizedArrayOf<F2DOT14>>
+  NNOffset32To<UnsizedArrayOf<F2DOT14>>
 		sharedTuples;	/* Offset from the start of this table to the shared tuple records.
 				 * Array of tuple records shared across all glyph variation data tables. */
   HBUINT16	glyphCount;	/* The number of glyphs in this font. This must match the number of
@@ -684,7 +684,7 @@
   HBUINT16	flags;		/* Bit-field that gives the format of the offset array that follows.
 				 * If bit 0 is clear, the offsets are uint16; if bit 0 is set, the
 				 * offsets are uint32. */
-  LOffsetTo<GlyphVariationData>
+  Offset32To<GlyphVariationData>
 		dataZ;		/* Offset from the start of this table to the array of
 				 * GlyphVariationData tables. */
   UnsizedArrayOf<HBUINT8>

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -49,7 +49,7 @@
   {
     unsigned int width = plan.get_width ();
     unsigned int inner_bit_count = plan.get_inner_bit_count ();
-    const hb_array_t<const unsigned int> output_map = plan.get_output_map ();
+    const hb_array_t<const uint32_t> output_map = plan.get_output_map ();
 
     TRACE_SERIALIZE (this);
     if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0))))
@@ -76,7 +76,7 @@
     return_trace (true);
   }
 
-  unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */
+  uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */
   {
     /* If count is zero, pass value unchanged.  This takes
      * care of direct mapping for advance map. */
@@ -217,7 +217,7 @@
       hb_codepoint_t	old_gid;
       if (plan->old_gid_for_new_gid (gid, &old_gid))
       {
-	unsigned int v = input_map->map (old_gid);
+	uint32_t v = input_map->map (old_gid);
 	unsigned int outer = v >> 16;
 	output_map[gid] = (outer_map[outer] << 16) | (inner_maps[outer][v & 0xFFFF]);
       }
@@ -234,7 +234,7 @@
   { return (map_count? (DeltaSetIndexMap::min_size + get_width () * map_count): 0); }
 
   bool is_identity () const { return get_output_map ().length == 0; }
-  hb_array_t<const unsigned int> get_output_map () const { return output_map.as_array (); }
+  hb_array_t<const uint32_t> get_output_map () const { return output_map.as_array (); }
 
   protected:
   unsigned int map_count;
@@ -241,7 +241,7 @@
   hb_vector_t<unsigned int> max_inners;
   unsigned int outer_bit_count;
   unsigned int inner_bit_count;
-  hb_vector_t<unsigned int> output_map;
+  hb_vector_t<uint32_t> output_map;
 };
 
 struct hvarvvar_subset_plan_t
@@ -408,7 +408,7 @@
 
   float get_advance_var (hb_codepoint_t glyph, hb_font_t *font) const
   {
-    unsigned int varidx = (this+advMap).map (glyph);
+    uint32_t varidx = (this+advMap).map (glyph);
     return (this+varStore).get_delta (varidx, font->coords, font->num_coords);
   }
 
@@ -416,7 +416,7 @@
 			      const int *coords, unsigned int coord_count) const
   {
     if (!has_side_bearing_deltas ()) return 0.f;
-    unsigned int varidx = (this+lsbMap).map (glyph);
+    uint32_t varidx = (this+lsbMap).map (glyph);
     return (this+varStore).get_delta (varidx, coords, coord_count);
   }
 
@@ -425,13 +425,13 @@
   protected:
   FixedVersion<>version;	/* Version of the metrics variation table
 				 * initially set to 0x00010000u */
-  LOffsetTo<VariationStore>
+  Offset32To<VariationStore>
 		varStore;	/* Offset to item variation store table. */
-  LOffsetTo<DeltaSetIndexMap>
+  Offset32To<DeltaSetIndexMap>
 		advMap;		/* Offset to advance var-idx mapping. */
-  LOffsetTo<DeltaSetIndexMap>
+  Offset32To<DeltaSetIndexMap>
 		lsbMap;		/* Offset to lsb/tsb var-idx mapping. */
-  LOffsetTo<DeltaSetIndexMap>
+  Offset32To<DeltaSetIndexMap>
 		rsbMap;		/* Offset to rsb/bsb var-idx mapping. */
 
   public:
@@ -475,7 +475,7 @@
   bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<VVAR> (c); }
 
   protected:
-  LOffsetTo<DeltaSetIndexMap>
+  Offset32To<DeltaSetIndexMap>
 		vorgMap;	/* Offset to vertical-origin var-idx mapping. */
 
   public:

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-mvar-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-mvar-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-mvar-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -103,7 +103,7 @@
   HBUINT16	valueRecordSize;/* The size in bytes of each value record —
 				 * must be greater than zero. */
   HBUINT16	valueRecordCount;/* The number of value records — may be zero. */
-  OffsetTo<VariationStore>
+  Offset16To<VariationStore>
 		varStore;	/* Offset to item variation store table. */
   UnsizedArrayOf<HBUINT8>
 		valuesZ;	/* Array of value records. The records must be

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -125,7 +125,7 @@
   FixedVersion<>version;	/* Version of VORG table. Set to 0x00010000u. */
   FWORD		defaultVertOriginY;
 				/* The default vertical origin. */
-  SortedArrayOf<VertOriginMetric>
+  SortedArray16Of<VertOriginMetric>
 		vertYOrigins;	/* The array of vertical origins. */
 
   public:

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-priority-queue.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-priority-queue.hh	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-priority-queue.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -0,0 +1,151 @@
+/*
+ * Copyright © 2020  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#ifndef HB_PRIORITY_QUEUE_HH
+#define HB_PRIORITY_QUEUE_HH
+
+#include "hb.hh"
+#include "hb-vector.hh"
+
+/*
+ * hb_priority_queue_t
+ *
+ * Priority queue implemented as a binary heap. Supports extract minimum
+ * and insert operations.
+ */
+struct hb_priority_queue_t
+{
+  HB_DELETE_COPY_ASSIGN (hb_priority_queue_t);
+  hb_priority_queue_t ()  { init (); }
+  ~hb_priority_queue_t () { fini (); }
+
+ private:
+  typedef hb_pair_t<int64_t, unsigned> item_t;
+  hb_vector_t<item_t> heap;
+
+ public:
+  void init () { heap.init (); }
+
+  void fini () { heap.fini (); }
+
+  void reset () { heap.resize (0); }
+
+  bool in_error () const { return heap.in_error (); }
+
+  void insert (int64_t priority, unsigned value)
+  {
+    heap.push (item_t (priority, value));
+    bubble_up (heap.length - 1);
+  }
+
+  item_t pop_minimum ()
+  {
+    item_t result = heap[0];
+
+    heap[0] = heap[heap.length - 1];
+    heap.shrink (heap.length - 1);
+    bubble_down (0);
+
+    return result;
+  }
+
+  const item_t& minimum ()
+  {
+    return heap[0];
+  }
+
+  bool is_empty () const { return heap.length == 0; }
+  explicit operator bool () const { return !is_empty (); }
+  unsigned int get_population () const { return heap.length; }
+
+  /* Sink interface. */
+  hb_priority_queue_t& operator << (item_t item)
+  { insert (item.first, item.second); return *this; }
+
+ private:
+
+  static constexpr unsigned parent (unsigned index)
+  {
+    return (index - 1) / 2;
+  }
+
+  static constexpr unsigned left_child (unsigned index)
+  {
+    return 2 * index + 1;
+  }
+
+  static constexpr unsigned right_child (unsigned index)
+  {
+    return 2 * index + 2;
+  }
+
+  void bubble_down (unsigned index)
+  {
+    unsigned left = left_child (index);
+    unsigned right = right_child (index);
+
+    bool has_left = left < heap.length;
+    if (!has_left)
+      // If there's no left, then there's also no right.
+      return;
+
+    bool has_right = right < heap.length;
+    if (heap[index].first <= heap[left].first
+        && (!has_right || heap[index].first <= heap[right].first))
+      return;
+
+    if (!has_right || heap[left].first < heap[right].first)
+    {
+      swap (index, left);
+      bubble_down (left);
+      return;
+    }
+
+    swap (index, right);
+    bubble_down (right);
+  }
+
+  void bubble_up (unsigned index)
+  {
+    if (index == 0) return;
+
+    unsigned parent_index = parent (index);
+    if (heap[parent_index].first <= heap[index].first)
+      return;
+
+    swap (index, parent_index);
+    bubble_up (parent_index);
+  }
+
+  void swap (unsigned a, unsigned b)
+  {
+    item_t temp = heap[a];
+    heap[a] = heap[b];
+    heap[b] = temp;
+  }
+};
+
+#endif /* HB_PRIORITY_QUEUE_HH */

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -0,0 +1,758 @@
+/*
+ * Copyright © 2020  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#ifndef HB_REPACKER_HH
+#define HB_REPACKER_HH
+
+#include "hb-open-type.hh"
+#include "hb-map.hh"
+#include "hb-priority-queue.hh"
+#include "hb-serialize.hh"
+#include "hb-vector.hh"
+
+
+struct graph_t
+{
+  struct vertex_t
+  {
+    vertex_t () :
+        distance (0),
+        incoming_edges (0),
+        start (0),
+        end (0),
+        priority(0) {}
+
+    void fini () { obj.fini (); }
+
+    hb_serialize_context_t::object_t obj;
+    int64_t distance;
+    unsigned incoming_edges;
+    unsigned start;
+    unsigned end;
+    unsigned priority;
+
+    bool is_shared () const
+    {
+      return incoming_edges > 1;
+    }
+
+    bool is_leaf () const
+    {
+      return !obj.links.length;
+    }
+
+    void raise_priority ()
+    {
+      priority++;
+    }
+
+    int64_t modified_distance (unsigned order) const
+    {
+      // TODO(garretrieger): once priority is high enough, should try
+      // setting distance = 0 which will force to sort immediately after
+      // it's parent where possible.
+
+      int64_t modified_distance =
+          hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFF);
+      return (modified_distance << 24) | (0x00FFFFFF & order);
+    }
+
+    int64_t distance_modifier () const
+    {
+      if (!priority) return 0;
+      int64_t table_size = obj.tail - obj.head;
+      return -(table_size - table_size / (1 << hb_min(priority, 16u)));
+    }
+  };
+
+  struct overflow_record_t
+  {
+    unsigned parent;
+    const hb_serialize_context_t::object_t::link_t* link;
+  };
+
+  struct clone_buffer_t
+  {
+    clone_buffer_t () : head (nullptr), tail (nullptr) {}
+
+    bool copy (const hb_serialize_context_t::object_t& object)
+    {
+      fini ();
+      unsigned size = object.tail - object.head;
+      head = (char*) malloc (size);
+      if (!head) return false;
+
+      memcpy (head, object.head, size);
+      tail = head + size;
+      return true;
+    }
+
+    char* head;
+    char* tail;
+
+    void fini ()
+    {
+      if (!head) return;
+      free (head);
+      head = nullptr;
+    }
+  };
+
+  /*
+   * A topological sorting of an object graph. Ordered
+   * in reverse serialization order (first object in the
+   * serialization is at the end of the list). This matches
+   * the 'packed' object stack used internally in the
+   * serializer
+   */
+  graph_t (const hb_vector_t<hb_serialize_context_t::object_t *>& objects)
+      : edge_count_invalid (true),
+        distance_invalid (true),
+        positions_invalid (true),
+        successful (true)
+  {
+    bool removed_nil = false;
+    for (unsigned i = 0; i < objects.length; i++)
+    {
+      // TODO(grieger): check all links point to valid objects.
+
+      // If this graph came from a serialization buffer object 0 is the
+      // nil object. We don't need it for our purposes here so drop it.
+      if (i == 0 && !objects[i])
+      {
+        removed_nil = true;
+        continue;
+      }
+
+      vertex_t* v = vertices_.push ();
+      if (check_success (!vertices_.in_error ()))
+        v->obj = *objects[i];
+      if (!removed_nil) continue;
+      for (unsigned i = 0; i < v->obj.links.length; i++)
+        // Fix indices to account for removed nil object.
+        v->obj.links[i].objidx--;
+    }
+  }
+
+  ~graph_t ()
+  {
+    vertices_.fini_deep ();
+    clone_buffers_.fini_deep ();
+  }
+
+  bool in_error () const
+  {
+    return !successful || vertices_.in_error () || clone_buffers_.in_error ();
+  }
+
+  const vertex_t& root () const
+  {
+    return vertices_[root_idx ()];
+  }
+
+  unsigned root_idx () const
+  {
+    // Object graphs are in reverse order, the first object is at the end
+    // of the vector. Since the graph is topologically sorted it's safe to
+    // assume the first object has no incoming edges.
+    return vertices_.length - 1;
+  }
+
+  const hb_serialize_context_t::object_t& object(unsigned i) const
+  {
+    return vertices_[i].obj;
+  }
+
+  /*
+   * serialize graph into the provided serialization buffer.
+   */
+  void serialize (hb_serialize_context_t* c) const
+  {
+    c->start_serialize<void> ();
+    for (unsigned i = 0; i < vertices_.length; i++) {
+      c->push ();
+
+      size_t size = vertices_[i].obj.tail - vertices_[i].obj.head;
+      char* start = c->allocate_size <char> (size);
+      if (!start) return;
+
+      memcpy (start, vertices_[i].obj.head, size);
+
+      for (const auto& link : vertices_[i].obj.links)
+        serialize_link (link, start, c);
+
+      // All duplications are already encoded in the graph, so don't
+      // enable sharing during packing.
+      c->pop_pack (false);
+    }
+    c->end_serialize ();
+  }
+
+  /*
+   * Generates a new topological sorting of graph using Kahn's
+   * algorithm: https://en.wikipedia.org/wiki/Topological_sorting#Algorithms
+   */
+  void sort_kahn ()
+  {
+    positions_invalid = true;
+
+    if (vertices_.length <= 1) {
+      // Graph of 1 or less doesn't need sorting.
+      return;
+    }
+
+    hb_vector_t<unsigned> queue;
+    hb_vector_t<vertex_t> sorted_graph;
+    hb_vector_t<unsigned> id_map;
+    if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
+
+    hb_vector_t<unsigned> removed_edges;
+    if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
+    update_incoming_edge_count ();
+
+    queue.push (root_idx ());
+    int new_id = vertices_.length - 1;
+
+    while (!queue.in_error () && queue.length)
+    {
+      unsigned next_id = queue[0];
+      queue.remove (0);
+
+      vertex_t& next = vertices_[next_id];
+      sorted_graph.push (next);
+      id_map[next_id] = new_id--;
+
+      for (const auto& link : next.obj.links) {
+        removed_edges[link.objidx]++;
+        if (!(vertices_[link.objidx].incoming_edges - removed_edges[link.objidx]))
+          queue.push (link.objidx);
+      }
+    }
+
+    check_success (!queue.in_error ());
+    check_success (!sorted_graph.in_error ());
+    if (!check_success (new_id == -1))
+      DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
+
+    remap_obj_indices (id_map, &sorted_graph);
+
+    sorted_graph.as_array ().reverse ();
+
+    vertices_.fini_deep ();
+    vertices_ = sorted_graph;
+    sorted_graph.fini_deep ();
+  }
+
+  /*
+   * Generates a new topological sorting of graph ordered by the shortest
+   * distance to each node.
+   */
+  void sort_shortest_distance ()
+  {
+    positions_invalid = true;
+
+    if (vertices_.length <= 1) {
+      // Graph of 1 or less doesn't need sorting.
+      return;
+    }
+
+    update_distances ();
+
+    hb_priority_queue_t queue;
+    hb_vector_t<vertex_t> sorted_graph;
+    hb_vector_t<unsigned> id_map;
+    if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
+
+    hb_vector_t<unsigned> removed_edges;
+    if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
+    update_incoming_edge_count ();
+
+    queue.insert (root ().modified_distance (0), root_idx ());
+    int new_id = root_idx ();
+    unsigned order = 1;
+    while (!queue.in_error () && !queue.is_empty ())
+    {
+      unsigned next_id = queue.pop_minimum().second;
+
+      vertex_t& next = vertices_[next_id];
+      sorted_graph.push (next);
+      id_map[next_id] = new_id--;
+
+      for (const auto& link : next.obj.links) {
+        removed_edges[link.objidx]++;
+        if (!(vertices_[link.objidx].incoming_edges - removed_edges[link.objidx]))
+          // Add the order that the links were encountered to the priority.
+          // This ensures that ties between priorities objects are broken in a consistent
+          // way. More specifically this is set up so that if a set of objects have the same
+          // distance they'll be added to the topological order in the order that they are
+          // referenced from the parent object.
+          queue.insert (vertices_[link.objidx].modified_distance (order++),
+                        link.objidx);
+      }
+    }
+
+    check_success (!queue.in_error ());
+    check_success (!sorted_graph.in_error ());
+    if (!check_success (new_id == -1))
+      DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
+
+    remap_obj_indices (id_map, &sorted_graph);
+
+    sorted_graph.as_array ().reverse ();
+
+    vertices_.fini_deep ();
+    vertices_ = sorted_graph;
+    sorted_graph.fini_deep ();
+  }
+
+  /*
+   * Creates a copy of child and re-assigns the link from
+   * parent to the clone. The copy is a shallow copy, objects
+   * linked from child are not duplicated.
+   */
+  void duplicate (unsigned parent_idx, unsigned child_idx)
+  {
+    DEBUG_MSG (SUBSET_REPACK, nullptr, "  Duplicating %d => %d",
+               parent_idx, child_idx);
+
+    positions_invalid = true;
+
+    auto* clone = vertices_.push ();
+    auto& child = vertices_[child_idx];
+    clone_buffer_t* buffer = clone_buffers_.push ();
+    if (vertices_.in_error ()
+        || clone_buffers_.in_error ()
+        || !check_success (buffer->copy (child.obj))) {
+      return;
+    }
+
+    clone->obj.head = buffer->head;
+    clone->obj.tail = buffer->tail;
+    clone->distance = child.distance;
+
+    for (const auto& l : child.obj.links)
+      clone->obj.links.push (l);
+
+    check_success (!clone->obj.links.in_error ());
+
+    auto& parent = vertices_[parent_idx];
+    unsigned clone_idx = vertices_.length - 2;
+    for (unsigned i = 0; i < parent.obj.links.length; i++)
+    {
+      auto& l = parent.obj.links[i];
+      if (l.objidx == child_idx)
+      {
+        l.objidx = clone_idx;
+        clone->incoming_edges++;
+        child.incoming_edges--;
+      }
+    }
+
+    // The last object is the root of the graph, so swap back the root to the end.
+    // The root's obj idx does change, however since it's root nothing else refers to it.
+    // all other obj idx's will be unaffected.
+    vertex_t root = vertices_[vertices_.length - 2];
+    vertices_[vertices_.length - 2] = *clone;
+    vertices_[vertices_.length - 1] = root;
+  }
+
+  /*
+   * Raises the sorting priority of all children.
+   */
+  void raise_childrens_priority (unsigned parent_idx)
+  {
+    DEBUG_MSG (SUBSET_REPACK, nullptr, "  Raising priority of all children of %d",
+               parent_idx);
+    // This operation doesn't change ordering until a sort is run, so no need
+    // to invalidate positions. It does not change graph structure so no need
+    // to update distances or edge counts.
+    auto& parent = vertices_[parent_idx].obj;
+    for (unsigned i = 0; i < parent.links.length; i++)
+      vertices_[parent.links[i].objidx].raise_priority ();
+  }
+
+  /*
+   * Will any offsets overflow on graph when it's serialized?
+   */
+  bool will_overflow (hb_vector_t<overflow_record_t>* overflows = nullptr)
+  {
+    if (overflows) overflows->resize (0);
+    update_positions ();
+
+    for (int parent_idx = vertices_.length - 1; parent_idx >= 0; parent_idx--)
+    {
+      for (const auto& link : vertices_[parent_idx].obj.links)
+      {
+        int64_t offset = compute_offset (parent_idx, link);
+        if (is_valid_offset (offset, link))
+          continue;
+
+        if (!overflows) return true;
+
+        overflow_record_t r;
+        r.parent = parent_idx;
+        r.link = &link;
+        overflows->push (r);
+      }
+    }
+
+    if (!overflows) return false;
+    return overflows->length;
+  }
+
+  void print_overflows (const hb_vector_t<overflow_record_t>& overflows)
+  {
+    if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
+
+    update_incoming_edge_count ();
+    for (const auto& o : overflows)
+    {
+      const auto& child = vertices_[o.link->objidx];
+      DEBUG_MSG (SUBSET_REPACK, nullptr, "  overflow from %d => %d (%d incoming , %d outgoing)",
+                 o.parent,
+                 o.link->objidx,
+                 child.incoming_edges,
+                 child.obj.links.length);
+    }
+  }
+
+  void err_other_error () { this->successful = false; }
+
+ private:
+
+  bool check_success (bool success)
+  { return this->successful && (success || (err_other_error (), false)); }
+
+  /*
+   * Creates a map from objid to # of incoming edges.
+   */
+  void update_incoming_edge_count ()
+  {
+    if (!edge_count_invalid) return;
+
+    for (unsigned i = 0; i < vertices_.length; i++)
+      vertices_[i].incoming_edges = 0;
+
+    for (const vertex_t& v : vertices_)
+    {
+      for (auto& l : v.obj.links)
+      {
+        vertices_[l.objidx].incoming_edges++;
+      }
+    }
+
+    edge_count_invalid = false;
+  }
+
+  /*
+   * compute the serialized start and end positions for each vertex.
+   */
+  void update_positions ()
+  {
+    if (!positions_invalid) return;
+
+    unsigned current_pos = 0;
+    for (int i = root_idx (); i >= 0; i--)
+    {
+      auto& v = vertices_[i];
+      v.start = current_pos;
+      current_pos += v.obj.tail - v.obj.head;
+      v.end = current_pos;
+    }
+
+    positions_invalid = false;
+  }
+
+  /*
+   * Finds the distance to each object in the graph
+   * from the initial node.
+   */
+  void update_distances ()
+  {
+    if (!distance_invalid) return;
+
+    // Uses Dijkstra's algorithm to find all of the shortest distances.
+    // https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
+    //
+    // Implementation Note:
+    // Since our priority queue doesn't support fast priority decreases
+    // we instead just add new entries into the queue when a priority changes.
+    // Redundant ones are filtered out later on by the visited set.
+    // According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf
+    // for practical performance this is faster then using a more advanced queue
+    // (such as a fibonaacci queue) with a fast decrease priority.
+    for (unsigned i = 0; i < vertices_.length; i++)
+    {
+      if (i == vertices_.length - 1)
+        vertices_[i].distance = 0;
+      else
+        vertices_[i].distance = hb_int_max (int64_t);
+    }
+
+    hb_priority_queue_t queue;
+    queue.insert (0, vertices_.length - 1);
+
+    hb_set_t visited;
+
+    while (!queue.in_error () && !queue.is_empty ())
+    {
+      unsigned next_idx = queue.pop_minimum ().second;
+      if (visited.has (next_idx)) continue;
+      const auto& next = vertices_[next_idx];
+      int64_t next_distance = vertices_[next_idx].distance;
+      visited.add (next_idx);
+
+      for (const auto& link : next.obj.links)
+      {
+        if (visited.has (link.objidx)) continue;
+
+        const auto& child = vertices_[link.objidx].obj;
+        int64_t child_weight = child.tail - child.head +
+                               (!link.is_wide ? (1 << 16) : ((int64_t) 1 << 32));
+        int64_t child_distance = next_distance + child_weight;
+
+        if (child_distance < vertices_[link.objidx].distance)
+        {
+          vertices_[link.objidx].distance = child_distance;
+          queue.insert (child_distance, link.objidx);
+        }
+      }
+    }
+
+    check_success (!queue.in_error ());
+    if (!check_success (queue.is_empty ()))
+    {
+      DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
+      return;
+    }
+
+    distance_invalid = false;
+  }
+
+  int64_t compute_offset (
+      unsigned parent_idx,
+      const hb_serialize_context_t::object_t::link_t& link) const
+  {
+    const auto& parent = vertices_[parent_idx];
+    const auto& child = vertices_[link.objidx];
+    int64_t offset = 0;
+    switch ((hb_serialize_context_t::whence_t) link.whence) {
+      case hb_serialize_context_t::whence_t::Head:
+        offset = child.start - parent.start; break;
+      case hb_serialize_context_t::whence_t::Tail:
+        offset = child.start - parent.end; break;
+      case hb_serialize_context_t::whence_t::Absolute:
+        offset = child.start; break;
+    }
+
+    assert (offset >= link.bias);
+    offset -= link.bias;
+    return offset;
+  }
+
+  bool is_valid_offset (int64_t offset,
+                        const hb_serialize_context_t::object_t::link_t& link) const
+  {
+    if (link.is_signed)
+    {
+      if (link.is_wide)
+        return offset >= -((int64_t) 1 << 31) && offset < ((int64_t) 1 << 31);
+      else
+        return offset >= -(1 << 15) && offset < (1 << 15);
+    }
+    else
+    {
+      if (link.is_wide)
+        return offset >= 0 && offset < ((int64_t) 1 << 32);
+      else
+        return offset >= 0 && offset < (1 << 16);
+    }
+  }
+
+  /*
+   * Updates all objidx's in all links using the provided mapping.
+   */
+  void remap_obj_indices (const hb_vector_t<unsigned>& id_map,
+                          hb_vector_t<vertex_t>* sorted_graph) const
+  {
+    for (unsigned i = 0; i < sorted_graph->length; i++)
+    {
+      for (unsigned j = 0; j < (*sorted_graph)[i].obj.links.length; j++)
+      {
+        auto& link = (*sorted_graph)[i].obj.links[j];
+        link.objidx = id_map[link.objidx];
+      }
+    }
+  }
+
+  template <typename O> void
+  serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link,
+                          char* head,
+                          hb_serialize_context_t* c) const
+  {
+    OT::Offset<O>* offset = reinterpret_cast<OT::Offset<O>*> (head + link.position);
+    *offset = 0;
+    c->add_link (*offset,
+                 // serializer has an extra nil object at the start of the
+                 // object array. So all id's are +1 of what our id's are.
+                 link.objidx + 1,
+                 (hb_serialize_context_t::whence_t) link.whence,
+                 link.bias);
+  }
+
+  void serialize_link (const hb_serialize_context_t::object_t::link_t& link,
+                 char* head,
+                 hb_serialize_context_t* c) const
+  {
+    if (link.is_wide)
+    {
+      if (link.is_signed)
+      {
+        serialize_link_of_type<OT::HBINT32> (link, head, c);
+      } else {
+        serialize_link_of_type<OT::HBUINT32> (link, head, c);
+      }
+    } else {
+      if (link.is_signed)
+      {
+        serialize_link_of_type<OT::HBINT16> (link, head, c);
+      } else {
+        serialize_link_of_type<OT::HBUINT16> (link, head, c);
+      }
+    }
+  }
+
+ public:
+  // TODO(garretrieger): make private, will need to move most of offset overflow code into graph.
+  hb_vector_t<vertex_t> vertices_;
+ private:
+  hb_vector_t<clone_buffer_t> clone_buffers_;
+  bool edge_count_invalid;
+  bool distance_invalid;
+  bool positions_invalid;
+  bool successful;
+};
+
+
+/*
+ * Attempts to modify the topological sorting of the provided object graph to
+ * eliminate offset overflows in the links between objects of the graph. If a
+ * non-overflowing ordering is found the updated graph is serialized it into the
+ * provided serialization context.
+ *
+ * If necessary the structure of the graph may be modified in ways that do not
+ * affect the functionality of the graph. For example shared objects may be
+ * duplicated.
+ */
+inline void
+hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& packed,
+                      hb_serialize_context_t* c) {
+  // Kahn sort is ~twice as fast as shortest distance sort and works for many fonts
+  // so try it first to save time.
+  graph_t sorted_graph (packed);
+  sorted_graph.sort_kahn ();
+  if (!sorted_graph.will_overflow ())
+  {
+    sorted_graph.serialize (c);
+    return;
+  }
+
+  sorted_graph.sort_shortest_distance ();
+
+  unsigned round = 0;
+  hb_vector_t<graph_t::overflow_record_t> overflows;
+  // TODO(garretrieger): select a good limit for max rounds.
+  while (!sorted_graph.in_error ()
+         && sorted_graph.will_overflow (&overflows)
+         && round++ < 10) {
+    DEBUG_MSG (SUBSET_REPACK, nullptr, "=== Over flow resolution round %d ===", round);
+    sorted_graph.print_overflows (overflows);
+
+    bool resolution_attempted = false;
+    hb_set_t priority_bumped_parents;
+    // Try resolving the furthest overflows first.
+    for (int i = overflows.length - 1; i >= 0; i--)
+    {
+      const graph_t::overflow_record_t& r = overflows[i];
+      const auto& child = sorted_graph.vertices_[r.link->objidx];
+      if (child.is_shared ())
+      {
+        // The child object is shared, we may be able to eliminate the overflow
+        // by duplicating it.
+        sorted_graph.duplicate (r.parent, r.link->objidx);
+        resolution_attempted = true;
+
+        // Stop processing overflows for this round so that object order can be
+        // updated to account for the newly added object.
+        break;
+      }
+
+      if (child.is_leaf () && !priority_bumped_parents.has (r.parent))
+      {
+        // This object is too far from it's parent, attempt to move it closer.
+        //
+        // TODO(garretrieger): initially limiting this to leaf's since they can be
+        //                     moved closer with fewer consequences. However, this can
+        //                     likely can be used for non-leafs as well.
+        // TODO(garretrieger): add a maximum priority, don't try to raise past this.
+        // TODO(garretrieger): also try lowering priority of the parent. Make it
+        //                     get placed further up in the ordering, closer to it's children.
+        //                     this is probably preferable if the total size of the parent object
+        //                     is < then the total size of the children (and the parent can be moved).
+        //                     Since in that case moving the parent will cause a smaller increase in
+        //                     the length of other offsets.
+        sorted_graph.raise_childrens_priority (r.parent);
+        priority_bumped_parents.add (r.parent);
+        resolution_attempted = true;
+        continue;
+      }
+
+      // TODO(garretrieger): add additional offset resolution strategies
+      // - Promotion to extension lookups.
+      // - Table splitting.
+    }
+
+    if (resolution_attempted)
+    {
+      sorted_graph.sort_shortest_distance ();
+      continue;
+    }
+
+    DEBUG_MSG (SUBSET_REPACK, nullptr, "No resolution available :(");
+    c->err (HB_SERIALIZE_ERROR_OFFSET_OVERFLOW);
+    return;
+  }
+
+  if (sorted_graph.in_error ())
+  {
+    c->err (HB_SERIALIZE_ERROR_OTHER);
+    return;
+  }
+  sorted_graph.serialize (c);
+}
+
+
+#endif /* HB_REPACKER_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -105,7 +105,7 @@
 #define HB_SANITIZE_MAX_EDITS 32
 #endif
 #ifndef HB_SANITIZE_MAX_OPS_FACTOR
-#define HB_SANITIZE_MAX_OPS_FACTOR 8
+#define HB_SANITIZE_MAX_OPS_FACTOR 64
 #endif
 #ifndef HB_SANITIZE_MAX_OPS_MIN
 #define HB_SANITIZE_MAX_OPS_MIN 16384
@@ -233,7 +233,7 @@
 	      (this->start <= p &&
 	       p <= this->end &&
 	       (unsigned int) (this->end - p) >= len &&
-	       this->max_ops-- > 0);
+	       (this->max_ops -= len) > 0);
 
     DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
 		     "check_range [%p..%p]"

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -41,6 +41,16 @@
  * Serialize
  */
 
+enum hb_serialize_error_t {
+  HB_SERIALIZE_ERROR_NONE =            0x00000000u,
+  HB_SERIALIZE_ERROR_OTHER =           0x00000001u,
+  HB_SERIALIZE_ERROR_OFFSET_OVERFLOW = 0x00000002u,
+  HB_SERIALIZE_ERROR_OUT_OF_ROOM =     0x00000004u,
+  HB_SERIALIZE_ERROR_INT_OVERFLOW =    0x00000008u,
+  HB_SERIALIZE_ERROR_ARRAY_OVERFLOW =  0x00000010u
+};
+HB_MARK_AS_FLAG_T (hb_serialize_error_t);
+
 struct hb_serialize_context_t
 {
   typedef unsigned objidx_t;
@@ -51,6 +61,8 @@
      Absolute	/* Absolute: from the start of the serialize buffer. */
    };
 
+
+
   struct object_t
   {
     void fini () { links.fini (); }
@@ -117,12 +129,25 @@
     object_pool.fini ();
   }
 
-  bool in_error () const { return !this->successful; }
+  bool in_error () const { return bool (errors); }
 
+  bool successful () const { return !bool (errors); }
+
+  HB_NODISCARD bool ran_out_of_room () const { return errors & HB_SERIALIZE_ERROR_OUT_OF_ROOM; }
+  HB_NODISCARD bool offset_overflow () const { return errors & HB_SERIALIZE_ERROR_OFFSET_OVERFLOW; }
+  HB_NODISCARD bool only_offset_overflow () const { return errors == HB_SERIALIZE_ERROR_OFFSET_OVERFLOW; }
+
+  void reset (void *start_, unsigned int size)
+  {
+    start = (char*) start_;
+    end = start + size;
+    reset ();
+    current = nullptr;
+  }
+
   void reset ()
   {
-    this->successful = true;
-    this->ran_out_of_room = false;
+    this->errors = HB_SERIALIZE_ERROR_NONE;
     this->head = this->start;
     this->tail = this->end;
     this->debug_depth = 0;
@@ -129,18 +154,29 @@
 
     fini ();
     this->packed.push (nullptr);
+    this->packed_map.init ();
   }
 
-  bool check_success (bool success)
-  { return this->successful && (success || (err_other_error (), false)); }
+  bool check_success (bool success,
+                      hb_serialize_error_t err_type = HB_SERIALIZE_ERROR_OTHER)
+  {
+    return successful ()
+        && (success || err (err_type));
+  }
 
   template <typename T1, typename T2>
-  bool check_equal (T1 &&v1, T2 &&v2)
-  { return check_success ((long long) v1 == (long long) v2); }
+  bool check_equal (T1 &&v1, T2 &&v2, hb_serialize_error_t err_type)
+  {
+    if ((long long) v1 != (long long) v2)
+    {
+      return err (err_type);
+    }
+    return true;
+  }
 
   template <typename T1, typename T2>
-  bool check_assign (T1 &v1, T2 &&v2)
-  { return check_equal (v1 = v2, v2); }
+  bool check_assign (T1 &v1, T2 &&v2, hb_serialize_error_t err_type)
+  { return check_equal (v1 = v2, v2, err_type); }
 
   template <typename T> bool propagate_error (T &&obj)
   { return check_success (!hb_deref (obj).in_error ()); }
@@ -167,12 +203,18 @@
 		     "end [%p..%p] serialized %u bytes; %s",
 		     this->start, this->end,
 		     (unsigned) (this->head - this->start),
-		     this->successful ? "successful" : "UNSUCCESSFUL");
+		     successful () ? "successful" : "UNSUCCESSFUL");
 
     propagate_error (packed, packed_map);
 
     if (unlikely (!current)) return;
-    if (unlikely (in_error())) return;
+    if (unlikely (in_error()))
+    {
+      // Offset overflows that occur before link resolution cannot be handled
+      // by repacking, so set a more general error.
+      if (offset_overflow ()) err (HB_SERIALIZE_ERROR_OTHER);
+      return;
+    }
 
     assert (!current->next);
 
@@ -351,7 +393,7 @@
       for (const object_t::link_t &link : parent->links)
       {
 	const object_t* child = packed[link.objidx];
-	if (unlikely (!child)) { err_other_error(); return; }
+	if (unlikely (!child)) { err (HB_SERIALIZE_ERROR_OTHER); return; }
 	unsigned offset = 0;
 	switch ((whence_t) link.whence) {
 	case Head:     offset = child->head - parent->head; break;
@@ -398,19 +440,19 @@
   Type *start_embed (const Type &obj) const
   { return start_embed (hb_addressof (obj)); }
 
-  /* Following two functions exist to allow setting breakpoint on. */
-  void err_ran_out_of_room () { this->ran_out_of_room = true; }
-  void err_other_error () { this->successful = false; }
+  bool err (hb_serialize_error_t err_type)
+  {
+    return !bool ((errors = (errors | err_type)));
+  }
 
   template <typename Type>
   Type *allocate_size (unsigned int size)
   {
-    if (unlikely (!this->successful)) return nullptr;
+    if (unlikely (in_error ())) return nullptr;
 
     if (this->tail - this->head < ptrdiff_t (size))
     {
-      err_ran_out_of_room ();
-      this->successful = false;
+      err (HB_SERIALIZE_ERROR_OUT_OF_ROOM);
       return nullptr;
     }
     memset (this->head, 0, size);
@@ -497,7 +539,7 @@
   /* Output routines. */
   hb_bytes_t copy_bytes () const
   {
-    assert (this->successful);
+    assert (successful ());
     /* Copy both items from head side and tail side... */
     unsigned int len = (this->head - this->start)
 		     + (this->end  - this->tail);
@@ -520,6 +562,9 @@
 			   (char *) b.arrayZ, free);
   }
 
+  const hb_vector_t<object_t *>& object_graph() const
+  { return packed; }
+
   private:
   template <typename T>
   void assign_offset (const object_t* parent, const object_t::link_t &link, unsigned offset)
@@ -526,14 +571,13 @@
   {
     auto &off = * ((BEInt<T> *) (parent->head + link.position));
     assert (0 == off);
-    check_assign (off, offset);
+    check_assign (off, offset, HB_SERIALIZE_ERROR_OFFSET_OVERFLOW);
   }
 
   public: /* TODO Make private. */
   char *start, *head, *tail, *end;
   unsigned int debug_depth;
-  bool successful;
-  bool ran_out_of_room;
+  hb_serialize_error_t errors;
 
   private:
 
@@ -550,5 +594,4 @@
   hb_hashmap_t<const object_t *, objidx_t, nullptr, 0> packed_map;
 };
 
-
 #endif /* HB_SERIALIZE_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -87,6 +87,8 @@
     }
   }
   template <typename T>
+  void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
+  template <typename T>
   bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
   {
     for (unsigned int i = 0; i < count; i++)
@@ -96,6 +98,8 @@
     }
     return true;
   }
+  template <typename T>
+  bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
 
   bool may_have (hb_codepoint_t g) const
   { return !!(mask & mask_for (g)); }
@@ -135,6 +139,8 @@
     tail.add_array (array, count, stride);
   }
   template <typename T>
+  void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
+  template <typename T>
   bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
   {
     head.add_sorted_array (array, count, stride);
@@ -141,6 +147,8 @@
     tail.add_sorted_array (array, count, stride);
     return true;
   }
+  template <typename T>
+  bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
 
   bool may_have (hb_codepoint_t g) const
   {

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -337,6 +337,8 @@
       while (count && (g = *array, start <= g && g < end));
     }
   }
+  template <typename T>
+  void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
 
   /* Might return false if array looks unsorted.
    * Used for faster rejection of corrupt data. */
@@ -368,6 +370,8 @@
     }
     return true;
   }
+  template <typename T>
+  bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
 
   void del (hb_codepoint_t g)
   {
@@ -828,7 +832,7 @@
   hb_codepoint_t get_max () const
   {
     unsigned int count = pages.length;
-    for (int i = count - 1; i >= 0; i++)
+    for (int i = count - 1; i >= 0; i--)
       if (!page_at (i).is_empty ())
 	return page_map[(unsigned) i].major * page_t::PAGE_BITS + page_at (i).get_max ();
     return INVALID;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc	2021-05-05 22:28:05 UTC (rev 59092)
@@ -43,6 +43,7 @@
 /*thread_local*/ uint64_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
 
 DEFINE_NULL_NAMESPACE_BYTES (OT, Index) =  {0xFF,0xFF};
+DEFINE_NULL_NAMESPACE_BYTES (OT, VarIdx) =  {0xFF,0xFF,0xFF,0xFF};
 DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
 DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00};
 DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00};

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc	2021-05-05 22:28:05 UTC (rev 59092)
@@ -56,9 +56,6 @@
 
   hb_tag_t default_drop_tables[] = {
     // Layout disabled by default
-    HB_TAG ('G', 'S', 'U', 'B'),
-    HB_TAG ('G', 'P', 'O', 'S'),
-    HB_TAG ('G', 'D', 'E', 'F'),
     HB_TAG ('m', 'o', 'r', 'x'),
     HB_TAG ('m', 'o', 'r', 't'),
     HB_TAG ('k', 'e', 'r', 'x'),

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	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc	2021-05-05 22:28:05 UTC (rev 59092)
@@ -39,6 +39,7 @@
 #include "hb-ot-stat-table.hh"
 
 
+typedef hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> script_langsys_map;
 #ifndef HB_NO_SUBSET_CFF
 static inline void
 _add_cff_seac_components (const OT::cff1::accelerator_t &cff,
@@ -70,7 +71,8 @@
 _gsub_closure_glyphs_lookups_features (hb_face_t *face,
 				       hb_set_t *gids_to_retain,
 				       hb_map_t *gsub_lookups,
-				       hb_map_t *gsub_features)
+				       hb_map_t *gsub_features,
+				       script_langsys_map *gsub_langsys)
 {
   hb_set_t lookup_indices;
   hb_ot_layout_collect_lookups (face,
@@ -96,7 +98,13 @@
                                  nullptr,
                                  nullptr,
                                  &feature_indices);
+
   gsub->prune_features (gsub_lookups, &feature_indices);
+  hb_map_t duplicate_feature_map;
+  gsub->find_duplicate_features (gsub_lookups, &feature_indices, &duplicate_feature_map);
+
+  feature_indices.clear ();
+  gsub->prune_langsys (&duplicate_feature_map, gsub_langsys, &feature_indices);
   _remap_indexes (&feature_indices, gsub_features);
 
   gsub.destroy ();
@@ -106,7 +114,8 @@
 _gpos_closure_lookups_features (hb_face_t      *face,
 				const hb_set_t *gids_to_retain,
 				hb_map_t       *gpos_lookups,
-				hb_map_t       *gpos_features)
+				hb_map_t       *gpos_features,
+				script_langsys_map *gpos_langsys)
 {
   hb_set_t lookup_indices;
   hb_ot_layout_collect_lookups (face,
@@ -129,8 +138,15 @@
                                  nullptr,
                                  nullptr,
                                  &feature_indices);
+
   gpos->prune_features (gpos_lookups, &feature_indices);
+  hb_map_t duplicate_feature_map;
+  gpos->find_duplicate_features (gpos_lookups, &feature_indices, &duplicate_feature_map);
+
+  feature_indices.clear ();
+  gpos->prune_langsys (&duplicate_feature_map, gpos_langsys, &feature_indices);
   _remap_indexes (&feature_indices, gpos_features);
+
   gpos.destroy ();
 }
 #endif
@@ -231,10 +247,10 @@
 #ifndef HB_NO_SUBSET_LAYOUT
   if (close_over_gsub)
     // closure all glyphs/lookups/features needed for GSUB substitutions.
-    _gsub_closure_glyphs_lookups_features (plan->source, plan->_glyphset_gsub, plan->gsub_lookups, plan->gsub_features);
+    _gsub_closure_glyphs_lookups_features (plan->source, plan->_glyphset_gsub, plan->gsub_lookups, plan->gsub_features, plan->gsub_langsys);
 
   if (close_over_gpos)
-    _gpos_closure_lookups_features (plan->source, plan->_glyphset_gsub, plan->gpos_lookups, plan->gpos_features);
+    _gpos_closure_lookups_features (plan->source, plan->_glyphset_gsub, plan->gpos_lookups, plan->gpos_features, plan->gpos_langsys);
 #endif
   _remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
 
@@ -356,11 +372,21 @@
   plan->reverse_glyph_map = hb_map_create ();
   plan->gsub_lookups = hb_map_create ();
   plan->gpos_lookups = hb_map_create ();
+
+  if (plan->check_success (plan->gsub_langsys = hb_object_create<script_langsys_map> ()))
+    plan->gsub_langsys->init_shallow ();
+  if (plan->check_success (plan->gpos_langsys = hb_object_create<script_langsys_map> ()))
+    plan->gpos_langsys->init_shallow ();
+
   plan->gsub_features = hb_map_create ();
   plan->gpos_features = hb_map_create ();
   plan->layout_variation_indices = hb_set_create ();
   plan->layout_variation_idx_map = hb_map_create ();
 
+  if (plan->in_error ()) {
+    return plan;
+  }
+
   _populate_gids_to_retain (plan,
 			    input->unicodes,
 			    input->glyphs,
@@ -407,6 +433,25 @@
   hb_set_destroy (plan->layout_variation_indices);
   hb_map_destroy (plan->layout_variation_idx_map);
 
+  if (plan->gsub_langsys)
+  {
+    for (auto _ : plan->gsub_langsys->iter ())
+      hb_set_destroy (_.second);
 
+    hb_object_destroy (plan->gsub_langsys);
+    plan->gsub_langsys->fini_shallow ();
+    free (plan->gsub_langsys);
+  }
+
+  if (plan->gpos_langsys)
+  {
+    for (auto _ : plan->gpos_langsys->iter ())
+      hb_set_destroy (_.second);
+
+    hb_object_destroy (plan->gpos_langsys);
+    plan->gpos_langsys->fini_shallow ();
+    free (plan->gpos_langsys);
+  }
+
   free (plan);
 }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -79,7 +79,11 @@
   hb_map_t *gsub_lookups;
   hb_map_t *gpos_lookups;
 
-  //active features we'd like to retain
+  //active langsys we'd like to retain
+  hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *gsub_langsys;
+  hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *gpos_langsys;
+
+  //active features after removing redundant langsys and prune_features
   hb_map_t *gsub_features;
   hb_map_t *gpos_features;
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc	2021-05-05 22:28:05 UTC (rev 59092)
@@ -50,6 +50,7 @@
 #include "hb-ot-layout-gpos-table.hh"
 #include "hb-ot-var-gvar-table.hh"
 #include "hb-ot-var-hvar-table.hh"
+#include "hb-repacker.hh"
 
 
 static unsigned
@@ -64,69 +65,132 @@
   return 512 + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
 }
 
+/*
+ * Repack the serialization buffer if any offset overflows exist.
+ */
+static hb_blob_t*
+_repack (hb_tag_t tag, const hb_serialize_context_t& c)
+{
+  if (tag != HB_OT_TAG_GPOS
+      &&  tag != HB_OT_TAG_GSUB)
+  {
+    // Check for overflow in a non-handled table.
+    return c.successful () ? c.copy_blob () : nullptr;
+  }
+
+  if (!c.offset_overflow ())
+    return c.copy_blob ();
+
+  hb_vector_t<char> buf;
+  int buf_size = c.end - c.start;
+  if (unlikely (!buf.alloc (buf_size)))
+    return nullptr;
+
+  hb_serialize_context_t repacked ((void *) buf, buf_size);
+  hb_resolve_overflows (c.object_graph (), &repacked);
+
+  if (unlikely (repacked.in_error ()))
+    // TODO(garretrieger): refactor so we can share the resize/retry logic with the subset
+    //                     portion.
+    return nullptr;
+
+  return repacked.copy_blob ();
+}
+
 template<typename TableType>
+static
+bool
+_try_subset (const TableType *table,
+             hb_vector_t<char>* buf,
+             unsigned buf_size,
+             hb_subset_context_t* c /* OUT */)
+{
+  c->serializer->start_serialize<TableType> ();
+
+  bool needed = table->subset (c);
+  if (!c->serializer->ran_out_of_room ())
+  {
+    c->serializer->end_serialize ();
+    return needed;
+  }
+
+  buf_size += (buf_size >> 1) + 32;
+  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.",
+             HB_UNTAG (c->table_tag), buf_size);
+
+  if (unlikely (!buf->alloc (buf_size)))
+  {
+    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.",
+               HB_UNTAG (c->table_tag), buf_size);
+    return needed;
+  }
+
+  c->serializer->reset (buf->arrayZ, buf_size);
+  return _try_subset (table, buf, buf_size, c);
+}
+
+template<typename TableType>
 static bool
 _subset (hb_subset_plan_t *plan)
 {
-  bool result = false;
   hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
   const TableType *table = source_blob->as<TableType> ();
 
   hb_tag_t tag = TableType::tableTag;
-  if (source_blob->data)
+  if (!source_blob->data)
   {
-    hb_vector_t<char> buf;
-    /* TODO Not all tables are glyph-related.  'name' table size for example should not be
-     * affected by number of glyphs.  Accommodate that. */
-    unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
-    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
-    if (unlikely (!buf.alloc (buf_size)))
-    {
-      DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
-      hb_blob_destroy (source_blob);
-      return false;
-    }
-  retry:
-    hb_serialize_context_t serializer ((void *) buf, buf_size);
-    serializer.start_serialize<TableType> ();
+    DEBUG_MSG (SUBSET, nullptr,
+               "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
+    hb_blob_destroy (source_blob);
+    return false;
+  }
+
+  hb_vector_t<char> buf;
+  /* TODO Not all tables are glyph-related.  'name' table size for example should not be
+   * affected by number of glyphs.  Accommodate that. */
+  unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
+  DEBUG_MSG (SUBSET, nullptr,
+             "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
+  if (unlikely (!buf.alloc (buf_size)))
+  {
+    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
+    hb_blob_destroy (source_blob);
+    return false;
+  }
+
+  bool needed = false;
+  hb_serialize_context_t serializer (buf.arrayZ, buf_size);
+  {
     hb_subset_context_t c (source_blob, plan, &serializer, tag);
-    bool needed = table->subset (&c);
-    if (serializer.ran_out_of_room)
-    {
-      buf_size += (buf_size >> 1) + 32;
-      DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", HB_UNTAG (tag), buf_size);
-      if (unlikely (!buf.alloc (buf_size)))
-      {
-	DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (tag), buf_size);
-	hb_blob_destroy (source_blob);
-	return false;
-      }
-      goto retry;
-    }
-    serializer.end_serialize ();
+    needed = _try_subset (table, &buf, buf_size, &c);
+  }
+  hb_blob_destroy (source_blob);
 
-    result = !serializer.in_error ();
+  if (serializer.in_error () && !serializer.only_offset_overflow ())
+  {
+    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset FAILED!", HB_UNTAG (tag));
+    return false;
+  }
 
-    if (result)
-    {
-      if (needed)
-      {
-	hb_blob_t *dest_blob = serializer.copy_blob ();
-	DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
-	result = c.plan->add_table (tag, dest_blob);
-	hb_blob_destroy (dest_blob);
-      }
-      else
-      {
-	DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
-      }
-    }
+  if (!needed)
+  {
+    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
+    return true;
   }
-  else
-    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
 
-  hb_blob_destroy (source_blob);
-  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
+  bool result = false;
+  hb_blob_t *dest_blob = _repack (tag, serializer);
+  if (dest_blob)
+  {
+    DEBUG_MSG (SUBSET, nullptr,
+               "OT::%c%c%c%c final subset table size: %u bytes.",
+               HB_UNTAG (tag), dest_blob->length);
+    result = plan->add_table (tag, dest_blob);
+    hb_blob_destroy (dest_blob);
+  }
+
+  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s",
+             HB_UNTAG (tag), result ? "success" : "FAILED!");
   return result;
 }
 
@@ -241,8 +305,10 @@
   if (unlikely (!input || !source)) return hb_face_get_empty ();
 
   hb_subset_plan_t *plan = hb_subset_plan_create (source, input);
-  if (unlikely (plan->in_error ()))
+  if (unlikely (plan->in_error ())) {
+    hb_subset_plan_destroy (plan);
     return hb_face_get_empty ();
+  }
 
   hb_set_t tags_set;
   bool success = true;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -289,8 +289,8 @@
 #define HB_MODIFIED_COMBINING_CLASS_CCC15 18 /* tsere */
 #define HB_MODIFIED_COMBINING_CLASS_CCC16 19 /* segol */
 #define HB_MODIFIED_COMBINING_CLASS_CCC17 20 /* patah */
-#define HB_MODIFIED_COMBINING_CLASS_CCC18 21 /* qamats */
-#define HB_MODIFIED_COMBINING_CLASS_CCC19 14 /* holam */
+#define HB_MODIFIED_COMBINING_CLASS_CCC18 21 /* qamats & qamats qatan */
+#define HB_MODIFIED_COMBINING_CLASS_CCC19 14 /* holam & holam haser for vav*/
 #define HB_MODIFIED_COMBINING_CLASS_CCC20 24 /* qubuts */
 #define HB_MODIFIED_COMBINING_CLASS_CCC21 12 /* dagesh */
 #define HB_MODIFIED_COMBINING_CLASS_CCC22 25 /* meteg */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -177,6 +177,11 @@
   Type *push (T&& v)
   {
     Type *p = push ();
+    if (p == &Crap (Type))
+      // If push failed to allocate then don't copy v, since this may cause
+      // the created copy to leak memory since we won't have stored a
+      // reference to it.
+      return p;
     *p = hb_forward<T> (v);
     return p;
   }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh	2021-05-05 22:28:05 UTC (rev 59092)
@@ -117,7 +117,10 @@
 #pragma GCC diagnostic ignored "-Wshadow"			// TODO fix
 #pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"	// TODO fix
 #pragma GCC diagnostic ignored "-Wunused-parameter"		// TODO fix
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic ignored "-Wunused-result"		// TODO fix
 #endif
+#endif
 
 /* Ignored intentionally. */
 #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
@@ -335,7 +338,6 @@
 #else
 #  define HB_NODISCARD
 #endif
-#define hb_success_t HB_NODISCARD bool
 
 /* https://github.com/harfbuzz/harfbuzz/issues/1852 */
 #if defined(__clang__) && !(defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__)))

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build	2021-05-05 22:28:05 UTC (rev 59092)
@@ -477,6 +477,8 @@
   compiled_tests = {
     'test-algs': ['test-algs.cc', 'hb-static.cc'],
     'test-array': ['test-array.cc'],
+    'test-repacker': ['test-repacker.cc', 'hb-static.cc'],
+    'test-priority-queue': ['test-priority-queue.cc', 'hb-static.cc'],
     'test-iter': ['test-iter.cc', 'hb-static.cc'],
     'test-meta': ['test-meta.cc', 'hb-static.cc'],
     'test-number': ['test-number.cc', 'hb-number.cc'],

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc	2021-05-05 22:28:05 UTC (rev 59092)
@@ -0,0 +1,89 @@
+/*
+ * Copyright © 2020  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "hb.hh"
+#include "hb-priority-queue.hh"
+
+static void
+test_insert ()
+{
+  hb_priority_queue_t queue;
+  assert (queue.is_empty ());
+
+  queue.insert (10, 0);
+  assert (!queue.is_empty ());
+  assert (queue.minimum () == hb_pair (10, 0));
+
+  queue.insert (20, 1);
+  assert (queue.minimum () == hb_pair (10, 0));
+
+  queue.insert (5, 2);
+  assert (queue.minimum () == hb_pair (5, 2));
+
+  queue.insert (15, 3);
+  assert (queue.minimum () == hb_pair (5, 2));
+
+  queue.insert (1, 4);
+  assert (queue.minimum () == hb_pair (1, 4));
+}
+
+static void
+test_extract ()
+{
+  hb_priority_queue_t queue;
+  queue.insert (0, 0);
+  queue.insert (60, 6);
+  queue.insert (30, 3);
+  queue.insert (40 ,4);
+  queue.insert (20, 2);
+  queue.insert (50, 5);
+  queue.insert (70, 7);
+  queue.insert (10, 1);
+
+  for (int i = 0; i < 8; i++)
+  {
+    assert (!queue.is_empty ());
+    assert (queue.minimum () == hb_pair (i * 10, i));
+    assert (queue.pop_minimum () == hb_pair (i * 10, i));
+  }
+
+  assert (queue.is_empty ());
+}
+
+static void
+test_extract_empty ()
+{
+  hb_priority_queue_t queue;
+  assert (queue.pop_minimum () == hb_pair (0, 0));
+}
+
+int
+main (int argc, char **argv)
+{
+  test_insert ();
+  test_extract ();
+  test_extract_empty ();
+}

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc	2021-05-05 22:28:05 UTC (rev 59092)
@@ -0,0 +1,485 @@
+/*
+ * Copyright © 2020  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include <string>
+
+#include "hb-repacker.hh"
+#include "hb-open-type.hh"
+
+static void start_object(const char* tag,
+                         unsigned len,
+                         hb_serialize_context_t* c)
+{
+  c->push ();
+  char* obj = c->allocate_size<char> (len);
+  strncpy (obj, tag, len);
+}
+
+
+static unsigned add_object(const char* tag,
+                           unsigned len,
+                           hb_serialize_context_t* c)
+{
+  start_object (tag, len, c);
+  return c->pop_pack (false);
+}
+
+
+static void add_offset (unsigned id,
+                        hb_serialize_context_t* c)
+{
+  OT::Offset16* offset = c->start_embed<OT::Offset16> ();
+  c->extend_min (offset);
+  c->add_link (*offset, id);
+}
+
+static void
+populate_serializer_simple (hb_serialize_context_t* c)
+{
+  c->start_serialize<char> ();
+
+  unsigned obj_1 = add_object ("ghi", 3, c);
+  unsigned obj_2 = add_object ("def", 3, c);
+
+  start_object ("abc", 3, c);
+  add_offset (obj_2, c);
+  add_offset (obj_1, c);
+  c->pop_pack ();
+
+  c->end_serialize();
+}
+
+static void
+populate_serializer_with_overflow (hb_serialize_context_t* c)
+{
+  std::string large_string(50000, 'a');
+  c->start_serialize<char> ();
+
+  unsigned obj_1 = add_object (large_string.c_str(), 10000, c);
+  unsigned obj_2 = add_object (large_string.c_str(), 20000, c);
+  unsigned obj_3 = add_object (large_string.c_str(), 50000, c);
+
+  start_object ("abc", 3, c);
+  add_offset (obj_3, c);
+  add_offset (obj_2, c);
+  add_offset (obj_1, c);
+  c->pop_pack ();
+
+  c->end_serialize();
+}
+
+static void
+populate_serializer_with_dedup_overflow (hb_serialize_context_t* c)
+{
+  std::string large_string(70000, 'a');
+  c->start_serialize<char> ();
+
+  unsigned obj_1 = add_object ("def", 3, c);
+
+  start_object (large_string.c_str(), 60000, c);
+  add_offset (obj_1, c);
+  unsigned obj_2 = c->pop_pack (false);
+
+  start_object (large_string.c_str(), 10000, c);
+  add_offset (obj_2, c);
+  add_offset (obj_1, c);
+  c->pop_pack (false);
+
+  c->end_serialize();
+}
+
+static void
+populate_serializer_complex_1 (hb_serialize_context_t* c)
+{
+  c->start_serialize<char> ();
+
+  unsigned obj_4 = add_object ("jkl", 3, c);
+  unsigned obj_3 = add_object ("ghi", 3, c);
+
+  start_object ("def", 3, c);
+  add_offset (obj_3, c);
+  unsigned obj_2 = c->pop_pack (false);
+
+  start_object ("abc", 3, c);
+  add_offset (obj_2, c);
+  add_offset (obj_4, c);
+  c->pop_pack ();
+
+  c->end_serialize();
+}
+
+static void
+populate_serializer_complex_2 (hb_serialize_context_t* c)
+{
+  c->start_serialize<char> ();
+
+  unsigned obj_5 = add_object ("mn", 2, c);
+
+  unsigned obj_4 = add_object ("jkl", 3, c);
+
+  start_object ("ghi", 3, c);
+  add_offset (obj_4, c);
+  unsigned obj_3 = c->pop_pack (false);
+
+  start_object ("def", 3, c);
+  add_offset (obj_3, c);
+  unsigned obj_2 = c->pop_pack (false);
+
+  start_object ("abc", 3, c);
+  add_offset (obj_2, c);
+  add_offset (obj_4, c);
+  add_offset (obj_5, c);
+  c->pop_pack ();
+
+  c->end_serialize();
+}
+
+static void
+populate_serializer_complex_3 (hb_serialize_context_t* c)
+{
+  c->start_serialize<char> ();
+
+  unsigned obj_6 = add_object ("opqrst", 6, c);
+
+  unsigned obj_5 = add_object ("mn", 2, c);
+
+  start_object ("jkl", 3, c);
+  add_offset (obj_6, c);
+  unsigned obj_4 = c->pop_pack (false);
+
+  start_object ("ghi", 3, c);
+  add_offset (obj_4, c);
+  unsigned obj_3 = c->pop_pack (false);
+
+  start_object ("def", 3, c);
+  add_offset (obj_3, c);
+  unsigned obj_2 = c->pop_pack (false);
+
+  start_object ("abc", 3, c);
+  add_offset (obj_2, c);
+  add_offset (obj_4, c);
+  add_offset (obj_5, c);
+  c->pop_pack ();
+
+  c->end_serialize();
+}
+
+static void test_sort_kahn_1 ()
+{
+  size_t buffer_size = 100;
+  void* buffer = malloc (buffer_size);
+  hb_serialize_context_t c (buffer, buffer_size);
+  populate_serializer_complex_1 (&c);
+
+  graph_t graph (c.object_graph ());
+  graph.sort_kahn ();
+
+  assert(strncmp (graph.object (3).head, "abc", 3) == 0);
+  assert(graph.object (3).links.length == 2);
+  assert(graph.object (3).links[0].objidx == 2);
+  assert(graph.object (3).links[1].objidx == 1);
+
+  assert(strncmp (graph.object (2).head, "def", 3) == 0);
+  assert(graph.object (2).links.length == 1);
+  assert(graph.object (2).links[0].objidx == 0);
+
+  assert(strncmp (graph.object (1).head, "jkl", 3) == 0);
+  assert(graph.object (1).links.length == 0);
+
+  assert(strncmp (graph.object (0).head, "ghi", 3) == 0);
+  assert(graph.object (0).links.length == 0);
+
+  free (buffer);
+}
+
+static void test_sort_kahn_2 ()
+{
+  size_t buffer_size = 100;
+  void* buffer = malloc (buffer_size);
+  hb_serialize_context_t c (buffer, buffer_size);
+  populate_serializer_complex_2 (&c);
+
+  graph_t graph (c.object_graph ());
+  graph.sort_kahn ();
+
+
+  assert(strncmp (graph.object (4).head, "abc", 3) == 0);
+  assert(graph.object (4).links.length == 3);
+  assert(graph.object (4).links[0].objidx == 3);
+    assert(graph.object (4).links[1].objidx == 0);
+  assert(graph.object (4).links[2].objidx == 2);
+
+  assert(strncmp (graph.object (3).head, "def", 3) == 0);
+  assert(graph.object (3).links.length == 1);
+  assert(graph.object (3).links[0].objidx == 1);
+
+  assert(strncmp (graph.object (2).head, "mn", 2) == 0);
+  assert(graph.object (2).links.length == 0);
+
+  assert(strncmp (graph.object (1).head, "ghi", 3) == 0);
+  assert(graph.object (1).links.length == 1);
+  assert(graph.object (1).links[0].objidx == 0);
+
+  assert(strncmp (graph.object (0).head, "jkl", 3) == 0);
+  assert(graph.object (0).links.length == 0);
+
+  free (buffer);
+}
+
+static void test_sort_shortest ()
+{
+  size_t buffer_size = 100;
+  void* buffer = malloc (buffer_size);
+  hb_serialize_context_t c (buffer, buffer_size);
+  populate_serializer_complex_2 (&c);
+
+  graph_t graph (c.object_graph ());
+  graph.sort_shortest_distance ();
+
+  assert(strncmp (graph.object (4).head, "abc", 3) == 0);
+  assert(graph.object (4).links.length == 3);
+  assert(graph.object (4).links[0].objidx == 2);
+  assert(graph.object (4).links[1].objidx == 0);
+  assert(graph.object (4).links[2].objidx == 3);
+
+  assert(strncmp (graph.object (3).head, "mn", 2) == 0);
+  assert(graph.object (3).links.length == 0);
+
+  assert(strncmp (graph.object (2).head, "def", 3) == 0);
+  assert(graph.object (2).links.length == 1);
+  assert(graph.object (2).links[0].objidx == 1);
+
+  assert(strncmp (graph.object (1).head, "ghi", 3) == 0);
+  assert(graph.object (1).links.length == 1);
+  assert(graph.object (1).links[0].objidx == 0);
+
+  assert(strncmp (graph.object (0).head, "jkl", 3) == 0);
+  assert(graph.object (0).links.length == 0);
+
+  free (buffer);
+}
+
+static void test_duplicate_leaf ()
+{
+  size_t buffer_size = 100;
+  void* buffer = malloc (buffer_size);
+  hb_serialize_context_t c (buffer, buffer_size);
+  populate_serializer_complex_2 (&c);
+
+  graph_t graph (c.object_graph ());
+  graph.duplicate (4, 1);
+
+  assert(strncmp (graph.object (5).head, "abc", 3) == 0);
+  assert(graph.object (5).links.length == 3);
+  assert(graph.object (5).links[0].objidx == 3);
+  assert(graph.object (5).links[1].objidx == 4);
+  assert(graph.object (5).links[2].objidx == 0);
+
+  assert(strncmp (graph.object (4).head, "jkl", 3) == 0);
+  assert(graph.object (4).links.length == 0);
+
+  assert(strncmp (graph.object (3).head, "def", 3) == 0);
+  assert(graph.object (3).links.length == 1);
+  assert(graph.object (3).links[0].objidx == 2);
+
+  assert(strncmp (graph.object (2).head, "ghi", 3) == 0);
+  assert(graph.object (2).links.length == 1);
+  assert(graph.object (2).links[0].objidx == 1);
+
+  assert(strncmp (graph.object (1).head, "jkl", 3) == 0);
+  assert(graph.object (1).links.length == 0);
+
+  assert(strncmp (graph.object (0).head, "mn", 2) == 0);
+  assert(graph.object (0).links.length == 0);
+
+  free (buffer);
+}
+
+static void test_duplicate_interior ()
+{
+  size_t buffer_size = 100;
+  void* buffer = malloc (buffer_size);
+  hb_serialize_context_t c (buffer, buffer_size);
+  populate_serializer_complex_3 (&c);
+
+  graph_t graph (c.object_graph ());
+  graph.duplicate (3, 2);
+
+  assert(strncmp (graph.object (6).head, "abc", 3) == 0);
+  assert(graph.object (6).links.length == 3);
+  assert(graph.object (6).links[0].objidx == 4);
+  assert(graph.object (6).links[1].objidx == 2);
+  assert(graph.object (6).links[2].objidx == 1);
+
+  assert(strncmp (graph.object (5).head, "jkl", 3) == 0);
+  assert(graph.object (5).links.length == 1);
+  assert(graph.object (5).links[0].objidx == 0);
+
+  assert(strncmp (graph.object (4).head, "def", 3) == 0);
+  assert(graph.object (4).links.length == 1);
+  assert(graph.object (4).links[0].objidx == 3);
+
+  assert(strncmp (graph.object (3).head, "ghi", 3) == 0);
+  assert(graph.object (3).links.length == 1);
+  assert(graph.object (3).links[0].objidx == 5);
+
+  assert(strncmp (graph.object (2).head, "jkl", 3) == 0);
+  assert(graph.object (2).links.length == 1);
+  assert(graph.object (2).links[0].objidx == 0);
+
+  assert(strncmp (graph.object (1).head, "mn", 2) == 0);
+  assert(graph.object (1).links.length == 0);
+
+  assert(strncmp (graph.object (0).head, "opqrst", 6) == 0);
+  assert(graph.object (0).links.length == 0);
+
+  free (buffer);
+}
+
+static void
+test_serialize ()
+{
+  size_t buffer_size = 100;
+  void* buffer_1 = malloc (buffer_size);
+  hb_serialize_context_t c1 (buffer_1, buffer_size);
+  populate_serializer_simple (&c1);
+  hb_bytes_t expected = c1.copy_bytes ();
+
+  void* buffer_2 = malloc (buffer_size);
+  hb_serialize_context_t c2 (buffer_2, buffer_size);
+
+  graph_t graph (c1.object_graph ());
+  graph.serialize (&c2);
+  hb_bytes_t actual = c2.copy_bytes ();
+
+  assert (actual == expected);
+
+  actual.free ();
+  expected.free ();
+  free (buffer_1);
+  free (buffer_2);
+}
+
+static void test_will_overflow_1 ()
+{
+  size_t buffer_size = 100;
+  void* buffer = malloc (buffer_size);
+  hb_serialize_context_t c (buffer, buffer_size);
+  populate_serializer_complex_2 (&c);
+  graph_t graph (c.object_graph ());
+
+  assert (!graph.will_overflow (nullptr));
+
+  free (buffer);
+}
+
+static void test_will_overflow_2 ()
+{
+  size_t buffer_size = 160000;
+  void* buffer = malloc (buffer_size);
+  hb_serialize_context_t c (buffer, buffer_size);
+  populate_serializer_with_overflow (&c);
+  graph_t graph (c.object_graph ());
+
+  assert (graph.will_overflow (nullptr));
+
+  free (buffer);
+}
+
+static void test_will_overflow_3 ()
+{
+  size_t buffer_size = 160000;
+  void* buffer = malloc (buffer_size);
+  hb_serialize_context_t c (buffer, buffer_size);
+  populate_serializer_with_dedup_overflow (&c);
+  graph_t graph (c.object_graph ());
+
+  assert (graph.will_overflow (nullptr));
+
+  free (buffer);
+}
+
+static void test_resolve_overflows_via_sort ()
+{
+  size_t buffer_size = 160000;
+  void* buffer = malloc (buffer_size);
+  hb_serialize_context_t c (buffer, buffer_size);
+  populate_serializer_with_overflow (&c);
+  graph_t graph (c.object_graph ());
+
+  void* out_buffer = malloc (buffer_size);
+  hb_serialize_context_t out (out_buffer, buffer_size);
+
+  hb_resolve_overflows (c.object_graph (), &out);
+  assert (!out.offset_overflow ());
+  hb_bytes_t result = out.copy_bytes ();
+  assert (result.length == (80000 + 3 + 3 * 2));
+
+  result.free ();
+  free (buffer);
+  free (out_buffer);
+}
+
+static void test_resolve_overflows_via_duplication ()
+{
+  size_t buffer_size = 160000;
+  void* buffer = malloc (buffer_size);
+  hb_serialize_context_t c (buffer, buffer_size);
+  populate_serializer_with_dedup_overflow (&c);
+  graph_t graph (c.object_graph ());
+
+  void* out_buffer = malloc (buffer_size);
+  hb_serialize_context_t out (out_buffer, buffer_size);
+
+  hb_resolve_overflows (c.object_graph (), &out);
+  assert (!out.offset_overflow ());
+  hb_bytes_t result = out.copy_bytes ();
+  assert (result.length == (10000 + 2 * 2 + 60000 + 2 + 3 * 2));
+
+  result.free ();
+  free (buffer);
+  free (out_buffer);
+}
+
+// TODO(garretrieger): update will_overflow tests to check the overflows array.
+// TODO(garretrieger): add a test(s) using a real font.
+// TODO(garretrieger): add tests for priority raising.
+
+int
+main (int argc, char **argv)
+{
+  test_serialize ();
+  test_sort_kahn_1 ();
+  test_sort_kahn_2 ();
+  test_sort_shortest ();
+  test_will_overflow_1 ();
+  test_will_overflow_2 ();
+  test_will_overflow_3 ();
+  test_resolve_overflows_via_sort ();
+  test_resolve_overflows_via_duplication ();
+  test_duplicate_leaf ();
+  test_duplicate_interior ();
+}

Modified: trunk/Build/source/libs/harfbuzz/version.ac
===================================================================
--- trunk/Build/source/libs/harfbuzz/version.ac	2021-05-05 19:44:19 UTC (rev 59091)
+++ trunk/Build/source/libs/harfbuzz/version.ac	2021-05-05 22:28:05 UTC (rev 59092)
@@ -8,4 +8,4 @@
 dnl --------------------------------------------------------
 dnl
 dnl  m4-include this file to define the current harfbuzz version
-m4_define([harfbuzz_version], [2.8.0])
+m4_define([harfbuzz_version], [2.8.1])



More information about the tex-live-commits mailing list.